diff --git a/MacGLide/Final/ChangeLog.txt b/MacGLide/Final/ChangeLog.txt new file mode 100644 index 0000000..cc0465b --- /dev/null +++ b/MacGLide/Final/ChangeLog.txt @@ -0,0 +1 @@ +New in 0.13: Looks like this is the "Tomb Raider Special Edition" of MacGLide, since all new features have been tailored towards improving the rendering quality of Tomb Raider Gold (and to some extent of TR2 too). Have fun. Features: + Improved rendering quality for Tomb Raider 1 Gold: - Added geometry analysis for removing background-colored gaps between landscape tiles - Runtime analysis of texture content for removing texture border artefacts caused by anisotropic filtering/mipmapping and the way TR stores its textures + adjustable Gamma Bias Bugfixes: 0.13a1: - Restoring the desktop gamma corection value should be more compatible - Gaps in menu screen of Carmageddon 2 and TR3 resolved Behind the scenes: + Revised and extended settings system - Default settings for any game - Game specific settings - Oh yes, older settings are again reset (hopefully for the last time) + Code refactoring as a preparation for Control Panel + Code refactoring as a preparation for texture replacment (a la Tomb Raider Xtra) New in 0.12: Features: + Gamma Correction (ColorSync must be installed) + Better performance (Especially in Carmageddon :^) Bug fixes: + FutureCop radar and dispatcher window working, V1.02 not crashing anymore when pausing the game + Carmagddon retro mirror working + Carmageddon Map 3D-View working in all situations + Fixed crash when moving the cursor in Carmageddon Movie mode + Quake 3Dfx is working (actually it did all the time but it just wanted exactly 2M framebuffer/texture RAM) + Descent 1+2 display the cockpit and instruments + Switching between (emulated) Glide display and Mac-Passthrough display preserves the color depth + Full support for undocumented Delta0 mode (no more special cases for Tomb Raider and Carmageddon) New in 0.11: Features: + New rendering engine (more accurate than in 0.10.1) allows better quality on suitable graphics cards (ATI 7500 and later or similar NVidia cards). Also fixes some rendering glitches such as the haze in Falcon 4.0 (which didn't show up in 0.10.1). To get the higher quality rendering, you need a graphics card with at least 3 texture units, for example an ATI Radeon 7500. Smaller cards like NVidia GForce 2mx or ATI Rage 128 will still use the simple rendering mode, and things will continue to look like in 0.10.1. + Full Scene AntiAliasing (FSAA) for ATI chips (only in the Classic environment) + Global texture smoothing and mipmapping + Tweaked a code a little to gain more speed on slower systems (does anyone notice?) + Original 3dfx-splash animation is displayed when starting a game in order to achive a more authentic appearence. + Better resource management + Added better support for pixel pipeline framebuffer writes. + Reorganised the code base + Lots of bugfixes and smaller improvements Bugfixes: Fixed in 0.11: + Menu backgrounds in Carmageddon 2 + Psychedelic colors in Falcon 4.0 on Dual G5 machines with ATI 9600XT + Settings folder has been renamed to "MacGLide" in order to comply to the product name Fixed in 0.11b1: + Several issues with the frame buffer emulation when pixel pipeline is active. + Unused texture units are disabled in order to speed up rendering. + Fa/18 Korea looks better because of fixes in the pixel pipeline frame buffer emulation (still not playable). + Fixed the color of the "3D" in the splash screen animation Fixed in 0.11a2: + If the exact screen size isn't found, MacGLide tries to choose a slightly larger one. + Carmageddon 2: Menu backgrounds and loading screen images are now showing up. However, the colors are wrong so this needs some more investigation. + FutureCop LAPD Demo: Ammo count digits and some other parts of the headup display are not displayed correctly in the first level in single player. However, the ammo count digits are now visible in multi player mode. But I have just the demo, so I can't tell much about the full version (needs also some more investigation). + Tomb Raider 3: The in-game menu background now shows the current game scene in black & white. + Fa/18 Korea looks better because of texture format fixes Fixed in 0.11a1: + Objects in Carmageddon (and probably other games) don't loose their transparency anymore when the fog becomes thicker. + Tomb Raider 1 Gold: Switching to the In-Game menu got a bit faster. + Less white screen appearence during screen resolution changes + Improved memory management hopefully fixes sudden exits in Falcon 4.0 that happended to some users when firing a rocket. + Haze in Falcon 4.0 rendered correctly. + Translucent Menu backgrounds in Tomb Raider 1 Gold. + Translucent Lightnings in Tomb Raider 1 Gold. + Fixed the multicolored skidmarks in Carmageddon (Splatpack). New in 0.10: Features: + Games can be played in any resolution whatever the monitor/LCD-display/hardware supports (See Readme.txt on how to enable this) + Configuration files are now stored in the System Preferences Folder in the subfolder "OpenGLide Settings". Bugfixes: Fixed in 0.10.1: + Fixed wrong screen resolution after flying a mission in Falcon 4.0 Fixed in 0.10: + Screenshots in Falcon 4.0 have not been rendered correctly Fixed in 0.10b3: + Fixed making screenshots in Falcon 4 for Resolution settings other than 1 + Fixed issues with logging searching for the display mode (resolution, colordepth haven't been reported correctly) + Config file from previous version is correctly replaced with default settings Fixed in 0.10b2: + Fixed a startup problem on machines that do not report a screen refresh rate (that's usally Macs with built-in LCD-Display, like the iMac, or Macs connected to a Cinema display via DVI/ADC) + Fixed a startup problem on machines that don't support resolutions below 640x480 Fixed in 010b1: + Falcon 4.0 can be played in True Color + Tomb Raider can be played with movies enabled + Enhanced display quality in Falcon 4.0 by enabling anisotropic filtering (has caused purple pixel artefacts on buildings/bridges/plane artwork in 0.09) + Enhanced display quality in Carmagedon by sorting out some rendering artefacts when Anisotropic filtering was enabled (for instance on skidmarks) + Fixed crash in Falcon 4.0 when starting a second mission + Fixed crash in Falcon 4.0 on firing a rocket or if an explosion was occuring (some users had reported this problem while it worked for me and others) + Fixed problem with displaying the health status bar in Tomb Raider Gold 1 + No more depth buffer problems on chipsets with 32bit depth buffer (for instance at the starting point of the first level of Tomb Raider Gold 1 the portal was not rendered correctly in 0.09) New in 0.09: + Fixed a bug that made white dots appear in the landscape in Falcon 4.0, and in other games that use 64x64 pixel textures (Carmageddon also uses a lot of 64x64 bit textures) + Optimised memory allocation (may solve performance degration during longer sessions) + Using Altivec in some cases (if the compiler feels like) + Compiler settings have been optimised to minimise the memory footprint (with the intention to fit into the 1st/2nd level cache) + Added ability to use complied vertex arrays to speed up the rendering + Mipmapping enabled by default + Anisotropic filtering default value set to 16 to achive the best rendering quality + Minor speed improvements by tweaking the code New in 0.009rc3: + Fixed remaining Falcon 4.0 missing cockpit displays. + Fixed invisible Myth In-Game dialogs (did already work in the betas but was broken in 0.09rc2) + Fixed transparent areas in Myth In-Game-dialogs + Fixed distorted landscape tiles in Myth (actually that one has already been fixed in 0.09rc2) + Minor speed improvements New in 0.009rc2: + Fixes for Falcon 4.0: * Canopy reflections and smoke effects appear correct. * Blue areas in virtual cockpit mode and the purple dots on areas/objects are gone (for instance the HUD or some weapons labels, probably others as well). * HUD texts are now readable. This bug actually affects all games since it solves a bug in the framebuffer rendering code that caused a dark pixel appearing right of any group of framebuffer pixels. * Instruments display correctly. * In-game menus are now appearing in front of the cockpit overlay. * The mission loading screen displays all stages of the flight preparation. *The screen doesn't turn upside down anymore for one frame when making a screenshot in Falcon 4. + Added a new fog emulation method that produces more accurate results than the previous one (for instance in carmageddon). + Added PedanticFrameBufferEmulation mode for enabling a more accurate emulation of the frame buffer (very slow but renders everything in the correct order). + added fog emluation mode entry to ini-file + ini-file entry "InitFullScreen" has been renamed to "DisplayMode" + Added per-application default settings so games with known issues (for instance Falcon 4.0) can be run "out-of-the-box". New in 0.009rc1: + Shadows and Lighnings in Tomb Raier Gold are displayed correctly + Fixed the "silly colors" problem in Carmageddon Splatpack + added minor speed improvements + Fixed the small icon mask of the shared library + Changed the file name of the archive to make it fit into the macos9 file name length limit + Corrected the list of tested games: Not Unreal Tournament, but the original Unreal has been tested New in 0.09b5: + Anisotropic filtering improves image quality + Carmageddon is playable in Classic on a G4 450Mhz/GeForce 2mx thanks to a new framebuffer emulation (about 5 times faster than before) + Textures are rendered in RGBA when possible (should speed up things a bit) This also fixes non-working mipmaps on ATI Rage 128 chipsets + Colors of on-screen displays and progress bars in Myth are now correct + Falcon 4.0 added to list of supported games, complete with cockpit interior and on-screen display (see details in game section on how to get it working) + Tomb Raider 1 displays the background correctly in In-Game menus + Text in Tomb Raider is displayed correctly on MacOS 9 systems + Tomb Raider 1 + 2 can be played with movies disabled + Tomb Raider 1 & 2 can be played with movies enabled in windowed mode at 640x480 (just set InitFullScreen=0 in the ini-file). But in this mode, there are some zbuffer problems in the first level. New in 0.09b4: + partial Support for ATI Rage 128 (mipmaps disabled, depth buffer size set to 16bit, some display errors) + Less memory usage + OpenGL GL_APPLE_packed_pixels is now a required gl extension + Simple fog emulation New in 0.09b3: + Fixed annoying "3DfxGlideLib2.x not found" message + Cleaned up the log output + Cleaned up the init file + Using the refresh rate requested by Glide and setting the monitor refresh rate to a fixed value works + Game overlays in Carmageddon aren't appearing anymore on top of the in-game menu for one frame when switching from the menu back to the game New in 0.09b2: + Corrected a bug that caused In-Game dialogs in Myth to appear corrupted + Trees and soldiers/Monsters in Myth are drawn without additional pixels around them + Missing menus/in-game graphics in Carmageddon (and probably some other games) are displayed + Added ability to set the screen refresh rate manually + Improved FadeIn/Out when going fullscreen New in 0.09b1: + Initial release \ No newline at end of file diff --git a/MacGLide/Final/Compatibility.txt b/MacGLide/Final/Compatibility.txt new file mode 100644 index 0000000..f634f67 --- /dev/null +++ b/MacGLide/Final/Compatibility.txt @@ -0,0 +1,148 @@ +Compatibility: + +Performance and rendering quality: + +In general, MacGLide works best when used in the MacOS X Classic environment. In this case +it can use the MacOS X OpenGL driver to render better quality images, and offers a lot more +features (like anisotropic filtering, Full Scene Antialiasing, etc.). + +In MacOS 9, the performance is a little bit better, but the rendering quality is not as good +as in the Classic environment. + +Compatibility: + +MacGLide has been tested with a lot of several games, and with several +hardware configurations. Below is a list of games and how they do with MacGLide. + + +Playable Games: + +Carmageddon: Works just fine. There is just a small problem with ExposŽ and + the mouse pointer. To use the mouse, you must set the screen + resolution to your desktop size. + +Carmageddon Splatpack: Works just fine. Set the resolution to the desktop resolution + to get the mouse pointer working correctly. + +Carmageddon 2: Works fine except that in menus and the loading screen, + the colors of the background images are wrong. Otherwise + the game is fully playable. + +Descent 1 & 2: Playable, but there are issues with switching from cockpit to map + view. The textures become corrupt after a few switches, or the screen + behind the cockpit becomes blank (to resolve this you can just switch + the view to rear and back) + +Descent 3 Demo: Works fine, with great graphics. But I have just the demo, and no + twin-stick, so I just gave it a quick try. + +Deus Ex: Works fine except the sunglasses of some characters are sometimes + white. The same goes for gun-smoke effects which are displayed + all the time (instead just when firing a gun). Sometimes, textured + landscape tiles show the wrong textures (or garbage). + +DS9 - The Fallen: Some objects in the intro seem to have problems with transparency. + Otherwise the game looks great but I haven't tested it a lot. + +Falcon 4.0: Works just fine. For maximum performance at 1600x1200, choose 800x600 + in the game menu, and set Resolution=2 in the settings file. + +Futurecop LAPD: Works fine except that in version 1.02, the pause screen is corrupt. + But you can stick with version 1.0. + +Myth The Fallen Lords: Works fine except when you override the Glide resolution in V1.3 + or below, the mouse pointer will not work correctly anymore. + +Quake 3Dfx: Works fine. + +Rune Demo: The Demo seems to work fine. + +Tomb Raider 1 (Gold): Works fine. Please note, that the In-Game menu has a black background, + except for 640x480, where you can see the dimmed paused game. + I believe this is actually a game feature, so don't blame me without + screenshots made with 3dfx hardware. + +Tomb Raider 2 (Gold): Works fine even with movies enabled with Version TR2 1.03. Earlier + versions of TR2 may not display everything as expected. + +Tomb Raider 3: Works fine. + +Unreal: Works fine. + + +Games with issues: + +Diablo 2: In the video driver setup dialog, the 3dfx/Glide options is greyed out + and can't be selected. Probably needs 3DfxGlideLib3.x to run properly + in 3dfx mode. However, there's a MacOS X patch available. + +Driver 3dfx: The main menu screen is missing. Besides that, the game doesn't run + in the MaxOS X classic environment (even with software rendering). + +F-18 Korea: Hardly playable. Although the textures look correct now, there are + severe screen update problems in cockpit mode. + +Waterrace: Needs 3DfxGlideLib3.x to run properly in 3dfx mode. + + +In general, MacGLide works best when used in the MacOS X Classic environment. In this case +it can use the MacOS X OpenGL driver to render better quality images, and offers a lot more +features (like anisotropic filtering, Full Scene Antialiasing, etc.). +In MacOS 9, the performance is a little bit better, but the rendering quality is not as good +as in the Classic environment. + + +Tested systems on MacOS X: + +MacGLide runs on any system with an OpenGL capable graphics card. + +So far, I've tested MacGLide myself with the following cards: + +- NVidia GForce 2MX +- NVidia 4MX +- ATI Radeon 7500 +- ATI Radeon 9000 +- ATI Mobility Radeon 9200 + +With these cards, all supported games work as described above. +But other cards will likely work without problems, too. + + +Same systems with MacOS 9.22: + +On MacOS 9, MacGLide doesn't run very well. The development of MacGLide +is focussed on features available through the Classic environemnt. +As a result, MacOS9 users have to live with the following inconveniences: + +- Fog is missing +- Unreal doesn't work with mipmaps enabled. +- In Carmageddon, textured objects loose their texture adn become white shaded. +- The MacOS 9.22 OpenGL drivers doesn't support Antialiasing. +- Chromakeying mght not work (probably caused by non-working alpha test). + +If you still want to play your games on MacOS 9.22, here's some problems +I have encountered on my machines: + +NVidia GForce 2MX OpenGL 1.2.2 (MacOS 9.22): + +- In Myth, most objects in the game are drawn in the wrong colors. + + +ATI Rage 128 OpenGL Engine Version 1.1.ATI-5.99 (MacOS 9.22): + +- The display in Carmageddon starts to flicker when the race starts. + +- The ATI OpenGL 1.1 driver returns 32 bit as the maximum Depth Buffer bits, causing + display errors. To get a correct display, the maximum number of depth buffer + bits must explicitely be set to 16 in the ini-file (DepthBufferBits=16). + +- Tomb Raider Gold has still zbuffer problems, even with the changed settings. + +- Unreal looks bad when mipmapping is enabled. + +- In Myth, the bounding rectangle of most objects in the game ise drawn with the wrong colors + (seems to be a problem with the Alpha test not working) + +If you have a graphic card not mentioned here, please let me know your experiences. + +Regards, Jens diff --git a/MacGLide/Final/Configuration.txt b/MacGLide/Final/Configuration.txt new file mode 100644 index 0000000..f2c878a --- /dev/null +++ b/MacGLide/Final/Configuration.txt @@ -0,0 +1,72 @@ +Configuration: + +MacGLide stores its settings in the "MacGLide Settings" subfolder of the +Preferences Folder in the MacOS 9 System Folder. There can be settings for +each game, but normally you're just editing the default settings, which +apply to all games. The files are created when you run a game the first +time. + + +The most important settings: + + +Resolution=n Overrides the screen resolution + + values from 1 to 8 are used to multiply the resolution requested by + the game. + + Example: With Resolution=2 and the game requests 800x600, the + screen resolution will be actually 1600x1200. + Because the game still thinks it 800x600, you might + achive higher framerates for games that extensively + write to the framebuffer (for instance Falcon 4.0). + + Greater values override the requested resolution with a fixed value: + + Example: Resolution=1024 sets the screen resolution to 1024x768 + regardless what the game requests (handy if you're using + a LCD with that resolution). + + +FullSceneAntiAliasing=n Sets the amount of samples to be used for antialiasing. + + Values greater than 1 enable full scene antialiasing + (improves rendering quality a lot) + + Example: FullSceneAntiAliasing=4 uses 4 samples to render a pixel. The + maximum value depends on the amount of VRAM of your video card + and the screen resolution. + So if your set the value too high, FSAA may cease to work. In + this case, you have either to decrease the screen resolution + or the FSAA value. + + +TextureSmoothing=n Improves rendering quality by enabling global texture + smoothing and mipmapping for all objects. + + A value of 1 (default) enables texture smoothing, a value of 0 disables + it. When enabled, all textures (instead of just the ones chosen by the + game) are rendered smoothly (using the OpenGL linear filter). If + mipmaps are enabled (they are by default) all textures are also + mipmapped. + + +MonitorRefreshRate=n Overrides the vertical screen refesh rate. + + Values from >=60 set the vertical screen refresh rate to n. + Example: MonitorRefreshRate=75 sets the vertical screen refresh rate to + 75Hz. Some games doesn't allow to change the refresh rate, but you can + change it here. + +All other default values are chosen for each game to provide the best quality/ +compatibility, so it shouldn't be necessary to change them. + +For other setings, see the hints at the top of the ini-file for details. + + +Memory usage: + +In order to get a game running with MacGLide on a MacOS 9 system and to avoid +a sudden exit to the finder, you must raise its memory partition by +about 50000K. When started in the MacOS X classic environment, the memory +setting can be left as it as. diff --git a/MacGLide/Final/Installation.txt b/MacGLide/Final/Installation.txt new file mode 100644 index 0000000..ec9792a --- /dev/null +++ b/MacGLide/Final/Installation.txt @@ -0,0 +1,18 @@ +Installation: + + +With the Installer: + +Just doubleclick the installer and follow the instructions. You'll get +a folder on the desktop with all the necessary readme files (since +you're reading this you've probably already done it) . + + +Installing from an archive: + +To install, unstuff the archive (since you're reading this you've +probably already done it) and drag the file 3DfxGlideLib2.x onto your +your MacOS9 System folder. You will be asked if you want to place it +in the System Extensions folder. Answer Yes. Alternatively, you can +place it in the System Extensions Folder manually. + diff --git a/MacGLide/Final/MacGLide.vct b/MacGLide/Final/MacGLide.vct new file mode 100644 index 0000000..70f4753 Binary files /dev/null and b/MacGLide/Final/MacGLide.vct differ diff --git a/MacGLide/Final/Readme.rtf b/MacGLide/Final/Readme.rtf new file mode 100644 index 0000000..0cbdcc3 --- /dev/null +++ b/MacGLide/Final/Readme.rtf @@ -0,0 +1,61 @@ +{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf380 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica-Oblique;\f2\fswiss\fcharset77 Helvetica; +} +{\colortbl;\red255\green255\blue255;\red21\green6\blue255;\red17\green4\blue255;\red16\green0\blue255; +} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker +}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid1}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} +\paperw11900\paperh16840\margl1440\margr1440\vieww11320\viewh11760\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\b\fs28 \cf0 MacGLide 0.13 Readme +\f1\i\b0 \ + +\f2\i0\fs24 \ +MacGLide is a shared library that emulates 3Dfx Voodoo Graphics hardware.\ +It makes it possible to run games originally made for 3Dfx/Glide without\ +the 3Dfx-hardware by translating Glide-function calls to OpenGL.\ +The project has been started once as a port of the OpenGLide project but\ +has undergone many enhancements since.\ +\ +The MacGLide project aims to preserve a part of Macintosh gaming history.\ +Some of these games are no longer playable, or the user experience itself\ +suffers because the image quality and/or detail level of the software\ +renderer is lacking. Among these games are unique titles like Tomb Raider,\ +Carmageddon and the Falcon 4 flight simulator. These games couldn't be\ +played (or viewed) as intended by the developers but with either the\ +original 3dfx hardware (which will someday cease to exist) or the software\ +emulation provided by the MacGLide project.\ +\ +Thanks to OpenGL and the capabilities of todays graphics hardware MacGLide\ +can spice up things a bit to give these old timers a second life.\ +And with the graphics technology up to date in OS X, it's again possible\ +to relive those moments of yesteryear with the old games we fell in love with.\ +\ +Main features:\ +\ +\pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\ql\qnatural\pardirnatural +\ls1\ilvl0\cf0 + Play your old games out of the box.\ ++ Benefit from todays graphics hardware to play in higher resolutions,\ + smoother images and higher frame rates among others.\ ++ Show your family and friends how you've wasted your time in the past :^)\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural +\cf0 \ +MacGLide is supposed to work with any 3Dfx-enabled game, preferably in the\ +Classic enviroment of MacOS X (10.1.5 or later) or (if you can still boot it)\ +with MacOS 9.22.\ +\ +MacGLide is released under the Gnu Lesser Public License\ +({\field{\*\fldinst{HYPERLINK "http://www.gnu.org/licenses/lgpl.html"}}{\fldrslt \cf2 http://www.gnu.org/licenses/lgpl.html}}).\ +\ +The latest version can be found at\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural +{\field{\*\fldinst{HYPERLINK "http://sourceforge.net/projects/macglide/"}}{\fldrslt \cf3 http://sourceforge.net/projects/macglide/}}\ +\ +If you discover a bug in MacGLide, or have ideas for improvements,\ +or just wanna let me know how it works for you, visit\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural +{\field{\*\fldinst{HYPERLINK "http://sourceforge.net/projects/macglide/"}}{\fldrslt \cf4 http://sourceforge.net/projects/macglide/}} and let me know.\ +\ +Best regards, Jens\ +} \ No newline at end of file diff --git a/MacGLide/Final/Readme.txt b/MacGLide/Final/Readme.txt new file mode 100644 index 0000000..336fd18 --- /dev/null +++ b/MacGLide/Final/Readme.txt @@ -0,0 +1,44 @@ +MacGLide 0.11 Readme + +MacGLide is a shared library that emulates 3Dfx Voodoo Graphics hardware. +It makes it possible to run games originally made for 3Dfx/Glide without +the hardware by translating Glide-function calls to OpenGL. +The project has been started once as a port of the OpenGLide project but +has undergone many enhancements since. + +The MacGLide project aims to preserve a part of Macintosh gaming history. +Some of these games are no longer playable, or the user experience itself +suffers because the image quality and/or detail level of the software +renderer is lacking. Among these games are unique titles like Tomb Raider, +Carmageddon and the Falcon 4 flight simulator. These games couldn't be +played (or viewed) as intended by the developers but with either the +original 3dfx hardware (which will someday cease to exist) or the software +emulation provided by the MacGLide project. + +Thanks to OpenGL and the capabilities of todays graphics hardware MacGLide +can spice up things a bit to give these old timers a second life. +And with the graphics technology up to date in OS X, it's again possible +to relive those moments of yesteryear with the old games we fell in love with. + +Main features: + ++ Play your old games out of the box. ++ Benefit from todays graphics hardware to play in higher resolutions, + smoother images and higher frame rates among others. ++ Show your family and friends how you've wasted your time in the past :^) + +MacGLide is supposed to work with any 3dfx-enabled game, preferably in the +Classic enviroment of MacOS X (10.1.5 or later) or (if you can still boot +it) with MacOS 9.22. + +MacGLide is released under the Gnu Lesser Public License +(http://www.gnu.org/licenses/lgpl.html). + +The latest version can be found at +http://sourceforge.net/projects/macglide/ + +If you discover a bug in MacGLide, or have ideas for improvements, +or just wanna let me know how it works for you, visit +http://sourceforge.net/projects/macglide/ and let me know. + +Regards, Jens diff --git a/MacGLide/Final/lgpl.rtf b/MacGLide/Final/lgpl.rtf new file mode 100644 index 0000000..8a0540e --- /dev/null +++ b/MacGLide/Final/lgpl.rtf @@ -0,0 +1,514 @@ +{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf230 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw11900\paperh16840\margl1440\margr1440\vieww8720\viewh13080\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural + +\f0\fs36 \cf0 GNU LESSER GENERAL PUBLIC LICENSE\ + +\fs28 Version 2.1, February 1999\ +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\fs24 \cf0 \ + Copyright (C) 1991, 1999 Free Software Foundation, Inc.\ + 51 Franklin St, 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.\ +\ +[This is the first released version of the Lesser GPL. It also counts\ + as the successor of the GNU Library Public License, version 2, hence\ + the version number 2.1.]\ +\ + Preamble\ +\ + The licenses for most software are designed to take away your\ +freedom to share and change it. By contrast, the GNU General Public\ +Licenses are intended to guarantee your freedom to share and change\ +free software--to make sure the software is free for all its users.\ +\ + This license, the Lesser General Public License, applies to some\ +specially designated software packages--typically libraries--of the\ +Free Software Foundation and other authors who decide to use it. You\ +can use it too, but we suggest you first think carefully about whether\ +this license or the ordinary General Public License is the better\ +strategy to use in any particular case, based on the explanations below.\ +\ + When we speak of free software, we are referring to freedom of use,\ +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 and use pieces of\ +it in new free programs; and that you are informed that you can do\ +these things.\ +\ + To protect your rights, we need to make restrictions that forbid\ +distributors to deny you these rights or to ask you to surrender these\ +rights. These restrictions translate to certain responsibilities for\ +you if you distribute copies of the library or if you modify it.\ +\ + For example, if you distribute copies of the library, whether gratis\ +or for a fee, you must give the recipients all the rights that we gave\ +you. You must make sure that they, too, receive or can get the source\ +code. If you link other code with the library, you must provide\ +complete object files to the recipients, so that they can relink them\ +with the library after making changes to the library and recompiling\ +it. And you must show them these terms so they know their rights.\ +\ + We protect your rights with a two-step method: (1) we copyright the\ +library, and (2) we offer you this license, which gives you legal\ +permission to copy, distribute and/or modify the library.\ +\ + To protect each distributor, we want to make it very clear that\ +there is no warranty for the free library. Also, if the library is\ +modified by someone else and passed on, the recipients should know\ +that what they have is not the original version, so that the original\ +author's reputation will not be affected by problems that might be\ +introduced by others.\ +\page \ + Finally, software patents pose a constant threat to the existence of\ +any free program. We wish to make sure that a company cannot\ +effectively restrict the users of a free program by obtaining a\ +restrictive license from a patent holder. Therefore, we insist that\ +any patent license obtained for a version of the library must be\ +consistent with the full freedom of use specified in this license.\ +\ + Most GNU software, including some libraries, is covered by the\ +ordinary GNU General Public License. This license, the GNU Lesser\ +General Public License, applies to certain designated libraries, and\ +is quite different from the ordinary General Public License. We use\ +this license for certain libraries in order to permit linking those\ +libraries into non-free programs.\ +\ + When a program is linked with a library, whether statically or using\ +a shared library, the combination of the two is legally speaking a\ +combined work, a derivative of the original library. The ordinary\ +General Public License therefore permits such linking only if the\ +entire combination fits its criteria of freedom. The Lesser General\ +Public License permits more lax criteria for linking other code with\ +the library.\ +\ + We call this license the "Lesser" General Public License because it\ +does Less to protect the user's freedom than the ordinary General\ +Public License. It also provides other free software developers Less\ +of an advantage over competing non-free programs. These disadvantages\ +are the reason we use the ordinary General Public License for many\ +libraries. However, the Lesser license provides advantages in certain\ +special circumstances.\ +\ + For example, on rare occasions, there may be a special need to\ +encourage the widest possible use of a certain library, so that it becomes\ +a de-facto standard. To achieve this, non-free programs must be\ +allowed to use the library. A more frequent case is that a free\ +library does the same job as widely used non-free libraries. In this\ +case, there is little to gain by limiting the free library to free\ +software only, so we use the Lesser General Public License.\ +\ + In other cases, permission to use a particular library in non-free\ +programs enables a greater number of people to use a large body of\ +free software. For example, permission to use the GNU C Library in\ +non-free programs enables many more people to use the whole GNU\ +operating system, as well as its variant, the GNU/Linux operating\ +system.\ +\ + Although the Lesser General Public License is Less protective of the\ +users' freedom, it does ensure that the user of a program that is\ +linked with the Library has the freedom and the wherewithal to run\ +that program using a modified version of the Library.\ +\ + The precise terms and conditions for copying, distribution and\ +modification follow. Pay close attention to the difference between a\ +"work based on the library" and a "work that uses the library". The\ +former contains code derived from the library, whereas the latter must\ +be combined with the library in order to run.\ +\page \ + GNU LESSER GENERAL PUBLIC LICENSE\ + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\ +\ + 0. This License Agreement applies to any software library or other\ +program which contains a notice placed by the copyright holder or\ +other authorized party saying it may be distributed under the terms of\ +this Lesser General Public License (also called "this License").\ +Each licensee is addressed as "you".\ +\ + A "library" means a collection of software functions and/or data\ +prepared so as to be conveniently linked with application programs\ +(which use some of those functions and data) to form executables.\ +\ + The "Library", below, refers to any such software library or work\ +which has been distributed under these terms. A "work based on the\ +Library" means either the Library or any derivative work under\ +copyright law: that is to say, a work containing the Library or a\ +portion of it, either verbatim or with modifications and/or translated\ +straightforwardly into another language. (Hereinafter, translation is\ +included without limitation in the term "modification".)\ +\ + "Source code" for a work means the preferred form of the work for\ +making modifications to it. For a library, 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 library.\ +\ + Activities other than copying, distribution and modification are not\ +covered by this License; they are outside its scope. The act of\ +running a program using the Library is not restricted, and output from\ +such a program is covered only if its contents constitute a work based\ +on the Library (independent of the use of the Library in a tool for\ +writing it). Whether that is true depends on what the Library does\ +and what the program that uses the Library does.\ + \ + 1. You may copy and distribute verbatim copies of the Library's\ +complete 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 distribute a copy of this License along with the\ +Library.\ +\ + 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.\ +\page \ + 2. You may modify your copy or copies of the Library or any portion\ +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.\ +\ + b) You must cause the files modified to carry prominent notices\ + stating that you changed the files and the date of any change.\ +\ + c) You must cause the whole of the work to be licensed at no\ + charge to all third parties under the terms of this License.\ +\ + d) If a facility in the modified Library refers to a function or a\ + table of data to be supplied by an application program that uses\ + the facility, other than as an argument passed when the facility\ + is invoked, then you must make a good faith effort to ensure that,\ + in the event an application does not supply such function or\ + table, the facility still operates, and performs whatever part of\ + its purpose remains meaningful.\ +\ + (For example, a function in a library to compute square roots has\ + a purpose that is entirely well-defined independent of the\ + application. Therefore, Subsection 2d requires that any\ + application-supplied function or table used by this function must\ + be optional: if the application does not supply it, the square\ + root function must still compute square roots.)\ +\ +These requirements apply to the modified work as a whole. If\ +identifiable sections of that work are not derived from the Library,\ +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 Library, 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 Library.\ +\ +In addition, mere aggregation of another work not based on the Library\ +with the Library (or with a work based on the Library) on a volume of\ +a storage or distribution medium does not bring the other work under\ +the scope of this License.\ +\ + 3. You may opt to apply the terms of the ordinary GNU General Public\ +License instead of this License to a given copy of the Library. To do\ +this, you must alter all the notices that refer to this License, so\ +that they refer to the ordinary GNU General Public License, version 2,\ +instead of to this License. (If a newer version than version 2 of the\ +ordinary GNU General Public License has appeared, then you can specify\ +that version instead if you wish.) Do not make any other change in\ +these notices.\ +\page \ + Once this change is made in a given copy, it is irreversible for\ +that copy, so the ordinary GNU General Public License applies to all\ +subsequent copies and derivative works made from that copy.\ +\ + This option is useful when you wish to copy part of the code of\ +the Library into a program that is not a library.\ +\ + 4. You may copy and distribute the Library (or a portion or\ +derivative of it, under Section 2) in object code or executable form\ +under the terms of Sections 1 and 2 above provided that you 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.\ +\ + If distribution of 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 satisfies the requirement to\ +distribute the source code, even though third parties are not\ +compelled to copy the source along with the object code.\ +\ + 5. A program that contains no derivative of any portion of the\ +Library, but is designed to work with the Library by being compiled or\ +linked with it, is called a "work that uses the Library". Such a\ +work, in isolation, is not a derivative work of the Library, and\ +therefore falls outside the scope of this License.\ +\ + However, linking a "work that uses the Library" with the Library\ +creates an executable that is a derivative of the Library (because it\ +contains portions of the Library), rather than a "work that uses the\ +library". The executable is therefore covered by this License.\ +Section 6 states terms for distribution of such executables.\ +\ + When a "work that uses the Library" uses material from a header file\ +that is part of the Library, the object code for the work may be a\ +derivative work of the Library even though the source code is not.\ +Whether this is true is especially significant if the work can be\ +linked without the Library, or if the work is itself a library. The\ +threshold for this to be true is not precisely defined by law.\ +\ + If such an object file uses only numerical parameters, data\ +structure layouts and accessors, and small macros and small inline\ +functions (ten lines or less in length), then the use of the object\ +file is unrestricted, regardless of whether it is legally a derivative\ +work. (Executables containing this object code plus portions of the\ +Library will still fall under Section 6.)\ +\ + Otherwise, if the work is a derivative of the Library, you may\ +distribute the object code for the work under the terms of Section 6.\ +Any executables containing that work also fall under Section 6,\ +whether or not they are linked directly with the Library itself.\ +\page \ + 6. As an exception to the Sections above, you may also combine or\ +link a "work that uses the Library" with the Library to produce a\ +work containing portions of the Library, and distribute that work\ +under terms of your choice, provided that the terms permit\ +modification of the work for the customer's own use and reverse\ +engineering for debugging such modifications.\ +\ + You must give prominent notice with each copy of the work that the\ +Library is used in it and that the Library and its use are covered by\ +this License. You must supply a copy of this License. If the work\ +during execution displays copyright notices, you must include the\ +copyright notice for the Library among them, as well as a reference\ +directing the user to the copy of this License. Also, you must do one\ +of these things:\ +\ + a) Accompany the work with the complete corresponding\ + machine-readable source code for the Library including whatever\ + changes were used in the work (which must be distributed under\ + Sections 1 and 2 above); and, if the work is an executable linked\ + with the Library, with the complete machine-readable "work that\ + uses the Library", as object code and/or source code, so that the\ + user can modify the Library and then relink to produce a modified\ + executable containing the modified Library. (It is understood\ + that the user who changes the contents of definitions files in the\ + Library will not necessarily be able to recompile the application\ + to use the modified definitions.)\ +\ + b) Use a suitable shared library mechanism for linking with the\ + Library. A suitable mechanism is one that (1) uses at run time a\ + copy of the library already present on the user's computer system,\ + rather than copying library functions into the executable, and (2)\ + will operate properly with a modified version of the library, if\ + the user installs one, as long as the modified version is\ + interface-compatible with the version that the work was made with.\ +\ + c) Accompany the work with a written offer, valid for at\ + least three years, to give the same user the materials\ + specified in Subsection 6a, above, for a charge no more\ + than the cost of performing this distribution.\ +\ + d) If distribution of the work is made by offering access to copy\ + from a designated place, offer equivalent access to copy the above\ + specified materials from the same place.\ +\ + e) Verify that the user has already received a copy of these\ + materials or that you have already sent this user a copy.\ +\ + For an executable, the required form of the "work that uses the\ +Library" must include any data and utility programs needed for\ +reproducing the executable from it. However, as a special exception,\ +the materials to be 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.\ +\ + It may happen that this requirement contradicts the license\ +restrictions of other proprietary libraries that do not normally\ +accompany the operating system. Such a contradiction means you cannot\ +use both them and the Library together in an executable that you\ +distribute.\ +\page \ + 7. 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 not covered by this License, and distribute such a combined\ +library, provided that the separate distribution of the work based on\ +the Library and of the other library facilities is otherwise\ +permitted, and provided that you do these two things:\ +\ + a) Accompany the combined library with a copy of the same work\ + based on the Library, uncombined with any other library\ + facilities. This must be distributed under the terms of the\ + Sections above.\ +\ + b) Give prominent notice with the combined library of the fact\ + that part of it is a work based on the Library, and explaining\ + where to find the accompanying uncombined form of the same work.\ +\ + 8. You may not copy, modify, sublicense, link with, or distribute\ +the Library except as expressly provided under this License. Any\ +attempt otherwise to copy, modify, sublicense, link with, or\ +distribute the Library 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.\ +\ + 9. 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 Library or its derivative works. These actions are\ +prohibited by law if you do not accept this License. Therefore, by\ +modifying or distributing the Library (or any work based on the\ +Library), you indicate your acceptance of this License to do so, and\ +all its terms and conditions for copying, distributing or modifying\ +the Library or works based on it.\ +\ + 10. Each time you redistribute the Library (or any work based on the\ +Library), the recipient automatically receives a license from the\ +original licensor to copy, distribute, link with or modify the Library\ +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 with\ +this License.\ +\page \ + 11. 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 Library at all. For example, if a patent\ +license would not permit royalty-free redistribution of the Library 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 Library.\ +\ +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.\ +\ + 12. If the distribution and/or use of the Library is restricted in\ +certain countries either by patents or by copyrighted interfaces, the\ +original copyright holder who places the Library 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.\ +\ + 13. The Free Software Foundation may publish revised and/or new\ +versions of the 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\ +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 Library does not specify a\ +license version number, you may choose any version ever published by\ +the Free Software Foundation.\ +\page \ + 14. If you wish to incorporate parts of the Library into other free\ +programs whose distribution conditions are incompatible with these,\ +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\ +\ + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\ +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\ +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\ +OTHER PARTIES PROVIDE THE LIBRARY "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\ +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\ +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\ +\ + 16. 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 LIBRARY 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\ +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\ +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\ +DAMAGES.\ +\ + END OF TERMS AND CONDITIONS\ +\page \ + How to Apply These Terms to Your New Libraries\ +\ + If you develop a new library, and you want it to be of the greatest\ +possible use to the public, we recommend making it free software that\ +everyone can redistribute and change. You can do so by permitting\ +redistribution under these terms (or, alternatively, under the terms of the\ +ordinary General Public License).\ +\ + To apply these terms, attach the following notices to the library. 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 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 2.1 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 Software\ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\ +\ +Also add information on how to contact you by electronic and paper mail.\ +\ +You should also get your employer (if you work as a programmer) or your\ +school, if any, to sign a "copyright disclaimer" for the library, if\ +necessary. Here is a sample; alter the names:\ +\ + Yoyodyne, Inc., hereby disclaims all copyright interest in the\ + library `Frob' (a library for tweaking knobs) written by James Random Hacker.\ +\ + , 1 April 1990\ + Ty Coon, President of Vice\ +\ +That's all there is to it!\ +\ +\ +} \ No newline at end of file diff --git a/MacGLide/Final/lgpl.txt b/MacGLide/Final/lgpl.txt new file mode 100644 index 0000000..8add30a --- /dev/null +++ b/MacGLide/Final/lgpl.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. 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 not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the 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 +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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 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 2.1 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 Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/MacGLide/Final/localized b/MacGLide/Final/localized new file mode 100644 index 0000000..e69de29 diff --git a/MacGLide/Mac/GlideApplication.cpp b/MacGLide/Mac/GlideApplication.cpp new file mode 100644 index 0000000..9cb20eb --- /dev/null +++ b/MacGLide/Mac/GlideApplication.cpp @@ -0,0 +1,48 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Glide application management +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideApplication.h" + +GlideApplication s_GlideApplication; + +GlideApplication::GlideApplication() +{ + Init(); +} + +void GlideApplication::Init() +{ + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) + { + ProcessInfoRec info; + memset(&info, 0, sizeof(info)); + info.processInfoLength = sizeof(info); + memset(&m_Name[0], 0, sizeof(m_Name)); + info.processName = reinterpret_cast(&m_Name[0]); + GetProcessInformation(&psn, &info); + // Convert pascal to c-string + m_Name[m_Name[0] + 1] = 0x0; + // set application type + if (strstr((char*) &m_Name[1], "Tomb Raider III") ) m_Type = TombRaiderIII; + else if (strstr((char*) &m_Name[1], "Tomb Raider II Gold") ) m_Type = TombRaiderII; + else if (strstr((char*) &m_Name[1], "Tomb Raider II") ) m_Type = TombRaiderII; + else if (strstr((char*) &m_Name[1], "Tomb Raider I") ) m_Type = TombRaiderI; + else if (strstr((char*) &m_Name[1], "TR Unfinished Business") ) m_Type = TombRaiderI; + else if (strstr((char*) &m_Name[1], "Carmageddon 2") ) m_Type = Carmageddon2; + else if (strstr((char*) &m_Name[1], "Carmageddon 3dfx") ) m_Type = Carmageddon; + else if (strstr((char*) &m_Name[1], "Falcon 4.0") ) m_Type = Falcon40; + else if (strstr((char*) &m_Name[1], "F/A-18") ) m_Type = FA18; + else if (strstr((char*) &m_Name[1], "Future Cop") ) m_Type = FutureCop; + else if (strstr((char*) &m_Name[1], "Myth The Fallen Lords") ) m_Type = MythTFL; + else if (strstr((char*) &m_Name[1], "Quake 3Dfx") ) m_Type = Quake; + else m_Type = Generic; + } +} \ No newline at end of file diff --git a/MacGLide/Mac/GlideDisplay.cpp b/MacGLide/Mac/GlideDisplay.cpp new file mode 100644 index 0000000..e013152 --- /dev/null +++ b/MacGLide/Mac/GlideDisplay.cpp @@ -0,0 +1,704 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Macintosh display +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Displays.h" +#include "GlideApplication.h" +#include "GlideDisplay.h" + +// display manager related stuff +const unsigned int VideoGammaTableSize = sizeof(CMVideoCardGamma) + 256 * 2; +struct DisplayModeSpec +{ + unsigned long HorizontalPixels_wanted; + unsigned long VerticalLines_wanted; + unsigned long RefreshRate_wanted; + unsigned long DisplayMode_wanted; + unsigned long HorizontalPixels; + unsigned long VerticalLines; + unsigned long RefreshRate; + unsigned long DisplayMode; + unsigned long ColorDepth; + GDHandle Device; + DisplayIDType DisplayID; + char VideoGammaTable[VideoGammaTableSize]; // Actually the CMVideoCardGamma table + bool Valid; + bool GammaValid; +}; + +// gamma related stuff +CMError DisplayManager_RememberGamma(DisplayModeSpec& display); +CMError DisplayManager_RestoreGamma(DisplayModeSpec& display); +CMError DisplayManager_SetGamma(DisplayModeSpec& display, FxFloat gamma); +bool DisplayManager_applyGamma(); +CMError DisplayManager_SetGammaBlack(DisplayModeSpec& display); +// Usally games have a Glide resolution +DisplayModeSpec DesktopDisplay; +// a resolution for displaying In-Game graphics via passthrough +DisplayModeSpec PassthroughDisplay; +// and the desktop resolution +DisplayModeSpec GlideDisplay; +// Copy of the colorsync profile of the monitor we're using +CMProfileRef DesktopColorSyncProfile; +// Whether to restore the menubar +bool RestoreMenuBar; + +bool DisplayManager_ColorSyncAvailable() +{ + return (Ptr) CMCloseProfile != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMGetSystemProfile != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMProfileElementExists != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMGetProfileByAVID != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMSetProfileByAVID != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMGetGammaByAVID != (Ptr) kUnresolvedCFragSymbolAddress && + (Ptr) CMSetGammaByAVID != (Ptr) kUnresolvedCFragSymbolAddress; +} + +bool DisplayManager_applyGamma() +{ + return DisplayManager_ColorSyncAvailable && DesktopDisplay.GammaValid && DesktopColorSyncProfile; +} + +CMProfileRef DisplayManager_GetDesktopProfile() +{ + CMProfileRef profile = NULL; + // F/A-18 exits here + CMError err = CMGetProfileByAVID(DesktopDisplay.DisplayID, &profile); + if (err == noErr) + { + bool gammatag_found = false; + // Check for gamma tag + err = CMProfileElementExists(profile, (unsigned long) cmVideoCardGammaTag, (unsigned char*) &gammatag_found); + if (gammatag_found == false) + { + GlideMsg("Display Manager Warning: Using CMGetSystemProfile() to retrieve desktop gamma table\n"); + err = CMGetSystemProfile(&profile); + if (err == noErr) + { + // Check for gamma tag + err = CMProfileElementExists(profile, (unsigned long) cmVideoCardGammaTag, (unsigned char*) &gammatag_found); + if (err == noErr && gammatag_found == false) + { + GlideMsg("Display Manager Warning: Gamma correction has been disabled because the System profile doesn't contain a gamma table\n"); + err = cmElementTagNotFound; + } + } + } + } + if (err != noErr) + { + GlideError("Display Manager error: Retrieving the Desktop gamma correction table failed with error %d\n", err); + if (profile) + { + CMCloseProfile(profile); + profile = NULL; + } + } + return profile; +} + +void DisplayManager_Initialise() +{ + memset(&DesktopDisplay, 0, sizeof(DisplayModeSpec)); + memset(&PassthroughDisplay, 0, sizeof(DisplayModeSpec)); + memset(&GlideDisplay, 0, sizeof(DisplayModeSpec)); + // Get devices + DesktopDisplay.Device = GetMainDevice(); + PassthroughDisplay.Device = GetMainDevice(); + GlideDisplay.Device = GetMainDevice(); + DesktopDisplay.GammaValid = false; + RestoreMenuBar = false; + DesktopColorSyncProfile = NULL; + if (DisplayManager_ColorSyncAvailable()) + { + // Get AVids + OSErr err = DMGetDisplayIDByGDevice(DesktopDisplay.Device, &DesktopDisplay.DisplayID, true); + if (err == noErr) + { + err = DMGetDisplayIDByGDevice(PassthroughDisplay.Device, &PassthroughDisplay.DisplayID, true); + if (err == noErr) + { + err = DMGetDisplayIDByGDevice(GlideDisplay.Device, &GlideDisplay.DisplayID, true); + } + } + if (err != noErr) + { + GlideMsg("Error: Unable to determine display id - gamma correction disabled\n"); + } + else + { + // Exits right at the start otherwise + if (s_GlideApplication.GetType() == GlideApplication::FA18) + { + DesktopDisplay.GammaValid = false; + } + else + { + CMProfileRef profile = DisplayManager_GetDesktopProfile(); + if (profile) + { + err = CMCopyProfile(&DesktopColorSyncProfile, NULL, profile); + if (err == noErr) + { + // Finally remember the gamma correction + err = DisplayManager_RememberGamma(DesktopDisplay); + if (err == noErr) + { + DesktopDisplay.GammaValid = true; + } + } + CMCloseProfile(profile); + } + if (err != noErr) + { + GlideMsg("Error: Unable to get desktop colorsync profile - gamma correction disabled\n"); + } + } + } + } + else + { + GlideMsg("Warning: ColorSync not installed or available - gamma correction disabled\n"); + } +} + +void DisplayManager_Cleanup() +{ + // Release the temporary profile + if (DesktopColorSyncProfile) CMCloseProfile(DesktopColorSyncProfile); +} + +extern "C" +{ + pascal void DisplayModeForResolution(void* userData, DMListIndexType itemIndex, DMDisplayModeListEntryPtr displaymodeInfo) + { + DisplayModeSpec* d = static_cast(userData); + VDResolutionInfoRec* res = displaymodeInfo->displayModeResolutionInfo; + // Get the exact resolution, and try to pick the highest available (or exact) refresh rate available below the wanted one + if (res->csHorizontalPixels == d->HorizontalPixels_wanted + && res->csVerticalLines == d->VerticalLines_wanted + && (d->RefreshRate_wanted == 0 + || (d->RefreshRate_wanted >= (res->csRefreshRate / 65536) && d->RefreshRate <= (res->csRefreshRate / 65536))) + ) + { + #ifdef OGL_DEBUG + GlideMsg("Display Manager: Considering matching display mode %d with resolution %dx%d@%dHz\n", + displaymodeInfo->displayModeResolutionInfo->csDisplayModeID, + res->csHorizontalPixels, + res->csVerticalLines, + res->csRefreshRate / 65536); + #endif + // Copy values + d->DisplayMode = displaymodeInfo->displayModeResolutionInfo->csDisplayModeID; + d->HorizontalPixels = res->csHorizontalPixels; + d->VerticalLines = res->csVerticalLines; + d->RefreshRate = res->csRefreshRate / 65536; + d->Valid = true; + } + // Get the next larger resolution, and try to pick the highest available (or exact) refresh rate available below the wanted one + else if (res->csHorizontalPixels >= d->HorizontalPixels_wanted + && res->csVerticalLines >= d->VerticalLines_wanted + && d->HorizontalPixels >= res->csHorizontalPixels + && d->VerticalLines >= res->csVerticalLines + && (d->RefreshRate_wanted == 0 + || (d->RefreshRate_wanted >= (res->csRefreshRate / 65536) && d->RefreshRate <= (res->csRefreshRate / 65536))) + ) + { + #ifdef OGL_DEBUG + GlideMsg("Display Manager: Considering next larger display mode %d with resolution %dx%d@%dHz\n", + displaymodeInfo->displayModeResolutionInfo->csDisplayModeID, + res->csHorizontalPixels, + res->csVerticalLines, + res->csRefreshRate / 65536); + #endif + // Copy values + d->DisplayMode = displaymodeInfo->displayModeResolutionInfo->csDisplayModeID; + d->HorizontalPixels = res->csHorizontalPixels; + d->VerticalLines = res->csVerticalLines; + d->RefreshRate = res->csRefreshRate / 65536; + d->Valid = true; + } + else + { + #ifdef OGL_DEBUG + GlideMsg("Display Manager: Found display mode %d with resolution %dx%d@%dHz\n", + displaymodeInfo->displayModeResolutionInfo->csDisplayModeID, + res->csHorizontalPixels, + res->csVerticalLines, + res->csRefreshRate / 65536); + #endif + } + } + + pascal void ResolutionForDisplayMode(void* userData, DMListIndexType itemIndex, DMDisplayModeListEntryPtr displaymodeInfo) + { + DisplayModeSpec* d = static_cast(userData); + VDResolutionInfoRec* res = displaymodeInfo->displayModeResolutionInfo; + #ifdef OGL_DEBUG + GlideMsg("Display Manager: Found display mode %d with resolution %dx%d@%dHz\n", + displaymodeInfo->displayModeResolutionInfo->csDisplayModeID, + res->csHorizontalPixels, + res->csVerticalLines, + res->csRefreshRate / 65536); + #endif + if (displaymodeInfo->displayModeResolutionInfo->csDisplayModeID == d->DisplayMode_wanted + // && spec.device == res->device + ) + { + d->HorizontalPixels = res->csHorizontalPixels; + d->VerticalLines = res->csVerticalLines; + d->RefreshRate = res->csRefreshRate / 65536; + d->DisplayMode = displaymodeInfo->displayModeResolutionInfo->csDisplayModeID; + d->Valid = true; + } + } +} + +OSErr DisplayManager_Query(DMDisplayModeListIteratorProcPtr iteratorproc, DisplayModeSpec& spec) +{ + OSErr err = noErr; + DMDisplayModeListIteratorUPP MyDMDisplayModeListIteratorUPP; + MyDMDisplayModeListIteratorUPP = NewDMDisplayModeListIteratorUPP(iteratorproc); + // use display manager to change the resolution + spec.Device = DMGetFirstScreenDevice(dmOnlyActiveDisplays); + while (spec.Device != nil) + { + DisplayIDType displayID; + err = DMGetDisplayIDByGDevice(spec.Device, &displayID, true); + if (err == noErr) + { + DMListIndexType thePanelCount; + DMListType thePanelList; + err = DMNewDisplayModeList(displayID, NULL, NULL, &thePanelCount, &thePanelList); + if (err == noErr) + { + for (int i = 0; i < thePanelCount; i++) + { + err = DMGetIndexedDisplayModeFromList(thePanelList, i, NULL, MyDMDisplayModeListIteratorUPP, &spec); + if (err == noErr) + { + // search until the exact resolution with the exact display mode was found + if (spec.Valid && spec.RefreshRate == spec.RefreshRate_wanted) break; + } + } + DMDisposeList(thePanelList); + } + } + // At this point, we might have found a valid spec with the exact resolution, + // but with a refresh rate smaller than requested one, which is ok + // (For instance on LCD-iMacs, the refresh rate may be 0) + // -> Don't get the next screen device + if (spec.Valid) break; + // Get the next device in the list + spec.Device = DMGetNextScreenDevice(spec.Device, dmOnlyActiveDisplays); + } + DisposeDMDisplayModeListIteratorUPP(MyDMDisplayModeListIteratorUPP); + return err; +} + +OSErr DisplayManager_SetGlideDisplay(unsigned int width, unsigned int height, unsigned int freq) +{ + GlideDisplay.HorizontalPixels_wanted = width; + GlideDisplay.VerticalLines_wanted = height; + GlideDisplay.HorizontalPixels = 65535; + GlideDisplay.VerticalLines = 65535; + GlideDisplay.RefreshRate_wanted = freq; + GlideDisplay.ColorDepth = 32; + GlideDisplay.DisplayMode = 0; + GlideDisplay.RefreshRate = 0; + GlideDisplay.Valid = false; + GlideDisplay.GammaValid = true; // we're not remembering this one + Handle displayState = NULL; + OSErr err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Searching for display resolution %dx%dx%d@%dHz\n", + GlideDisplay.HorizontalPixels_wanted, GlideDisplay.VerticalLines_wanted, + GlideDisplay.ColorDepth, GlideDisplay.RefreshRate_wanted); +#endif + err = DisplayManager_Query(&DisplayModeForResolution, GlideDisplay); + if (!GlideDisplay.Valid && err == noErr) + { + GlideMsg("Display Manager: Unable to find a valid display mode for Glide display\n"); + err = kDMNotFoundErr; + } + else if (err == noErr) + { + err = DMSetDisplayMode(GlideDisplay.Device, GlideDisplay.DisplayMode, &GlideDisplay.ColorDepth, NULL, displayState); + } + DMEndConfigureDisplays(displayState); + } + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Using display mode %d with resolution %dx%dx%d@%dHz\n", + GlideDisplay.DisplayMode, + GlideDisplay.HorizontalPixels, GlideDisplay.VerticalLines, + GlideDisplay.ColorDepth, GlideDisplay.RefreshRate); +#endif + if (IsMenuBarVisible()) HideMenuBar(); + + } + else + { + GlideMsg("Display Manager: Error while setting Glide display to %dx%dx%d@%dHz: %d\n", + GlideDisplay.HorizontalPixels_wanted, GlideDisplay.VerticalLines_wanted, + GlideDisplay.ColorDepth, GlideDisplay.RefreshRate_wanted, err); + } + return err; +} + +OSErr DisplayManager_RememberPassthroughDisplay() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + // Invalidate any previous search + PassthroughDisplay.Valid = false; + PassthroughDisplay.GammaValid = false; + Handle displayState = NULL; + OSErr err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { + // save the old desktop resolution + VDSwitchInfoRec switchinfo; + err = DMGetDisplayMode(PassthroughDisplay.Device, &switchinfo); + if (err == noErr) + { + PassthroughDisplay.DisplayMode_wanted = switchinfo.csData; + PassthroughDisplay.ColorDepth = switchinfo.csMode; +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Searching for passthrough display mode %d\n", PassthroughDisplay.DisplayMode_wanted); +#endif + // save previous display resolution + err = DisplayManager_Query(&ResolutionForDisplayMode, PassthroughDisplay); + if (!PassthroughDisplay.Valid && err == noErr) + { + GlideMsg("Display Manager: Unable to find the display resolution for the passthrough display\n"); + err = kDMNotFoundErr; + } + } + DMEndConfigureDisplays(displayState); + } + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Remembering passthrough display mode %d with resolution %dx%dx%d@%dHz\n", + PassthroughDisplay.DisplayMode, + PassthroughDisplay.HorizontalPixels, PassthroughDisplay.VerticalLines, + PassthroughDisplay.ColorDepth, PassthroughDisplay.RefreshRate); +#endif + if (DisplayManager_RememberGamma(PassthroughDisplay) == noErr) + { + PassthroughDisplay.GammaValid = true; + } + // Remember menubar status + RestoreMenuBar = IsMenuBarVisible(); + } + else + { + GlideMsg("Display Manager: Error while remembering passthrough display mode: %d\n", err); + } + return err; +} + +OSErr DisplayManager_RememberDesktopDisplay() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + // Invalidate any previous search + DesktopDisplay.Valid = false; + // save the old desktop resolution + Handle displayState = NULL; + OSErr err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { + VDSwitchInfoRec switchinfo; + err = DMGetDisplayMode(DesktopDisplay.Device, &switchinfo); + if (err == noErr) + { + DesktopDisplay.DisplayMode_wanted = switchinfo.csData; + DesktopDisplay.ColorDepth = switchinfo.csMode; +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Searching for Desktop display mode %d\n", DesktopDisplay.DisplayMode_wanted); +#endif + // save previous display resolution + err = DisplayManager_Query(&ResolutionForDisplayMode, DesktopDisplay); + if (!DesktopDisplay.Valid && err == noErr) + { + GlideMsg("Display Manager: Unable to find the display resolution for the Desktop display\n"); + err = kDMNotFoundErr; + } + } + DMEndConfigureDisplays(displayState); + // Desktop gamma already remembered in DisplayManager_Initialise() + } + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Remembering desktop display mode %d with resolution %dx%dx%d@%dHz\n", + DesktopDisplay.DisplayMode, + DesktopDisplay.HorizontalPixels, DesktopDisplay.VerticalLines, + DesktopDisplay.ColorDepth, DesktopDisplay.RefreshRate); +#endif + } + else + { + GlideMsg("Display Manager: Error while remembering desktop display mode: %d\n", err); + } + return err; +} + +OSErr DisplayManager_RestoreGlideDisplay() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + OSErr err = noErr; + if (GlideDisplay.Valid) + { + Handle displayState = NULL; + err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Restoring Glide display mode %d with resolution %dx%dx%d@%dHz\n", + GlideDisplay.DisplayMode, + GlideDisplay.HorizontalPixels, GlideDisplay.VerticalLines, + GlideDisplay.ColorDepth, GlideDisplay.RefreshRate); +#endif + if (err == noErr) + { + err = DMSetDisplayMode(GlideDisplay.Device, GlideDisplay.DisplayMode, &GlideDisplay.ColorDepth, NULL, displayState); + } + DMEndConfigureDisplays(displayState); + } + } + else + { + GlideMsg("Display Manager: Glide display not restored\n"); + } + if (err == noErr) + { + // Remember menubar status + RestoreMenuBar = IsMenuBarVisible(); + if (RestoreMenuBar) HideMenuBar(); + } + else + { + GlideMsg("Display Manager: Error while restoring Glide display mode: %d\n", err); + } + return noErr; +} + +OSErr DisplayManager_RestorePassthroughDisplay() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + OSErr err = noErr; + if (PassthroughDisplay.Valid) + { + Handle displayState = NULL; + err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Restoring passthrough display mode %d with resolution %dx%dx%d@%dHz\n", + PassthroughDisplay.DisplayMode, + PassthroughDisplay.HorizontalPixels, PassthroughDisplay.VerticalLines, + PassthroughDisplay.ColorDepth, PassthroughDisplay.RefreshRate); +#endif + err = DMSetDisplayMode(PassthroughDisplay.Device, PassthroughDisplay.DisplayMode, &PassthroughDisplay.ColorDepth, NULL, displayState); + DMEndConfigureDisplays(displayState); + } + } + else + { + GlideMsg("Display Manager: Passthrough display not restored\n"); + } + // Restore menubar and gamma + if (err == noErr) + { + if (RestoreMenuBar) ShowMenuBar(); + if (PassthroughDisplay.GammaValid == true) DisplayManager_RestoreGamma(PassthroughDisplay); + } + else + { + GlideMsg("Display Manager: Error while restoring passthrough display mode: %d\n", err); + } + return err; +} + +OSErr DisplayManager_RestoreDesktopDisplay() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + OSErr err = noErr; + if (DesktopDisplay.Valid) + { + Handle displayState = NULL; + err = DMBeginConfigureDisplays(&displayState); + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Restoring desktop display mode %d with resolution %dx%dx%d@%dHz\n", + DesktopDisplay.DisplayMode, + DesktopDisplay.HorizontalPixels, DesktopDisplay.VerticalLines, + DesktopDisplay.ColorDepth, DesktopDisplay.RefreshRate); +#endif + err = DMSetDisplayMode(DesktopDisplay.Device, DesktopDisplay.DisplayMode, &DesktopDisplay.ColorDepth, NULL, displayState); + DMEndConfigureDisplays(displayState); + } + } + else + { +#ifdef OGL_DEBUG + GlideMsg("Display Manager: Desktop display not restored\n"); +#endif + } + if (err == noErr) + { + if (DisplayManager_applyGamma()) + { + err = CMSetProfileByAVID(DesktopDisplay.DisplayID, DesktopColorSyncProfile); + } + } + if (err != noErr) + { + GlideMsg("Display Manager: Error while restoring desktop display mode: %d\n", err); + } + return err; +} + +bool DisplayManager_GetDesktopDisplayResolution(unsigned long& width, unsigned long& height) +{ + width = DesktopDisplay.HorizontalPixels; + height = DesktopDisplay.VerticalLines; + return DesktopDisplay.Valid; +} + +bool DisplayManager_GetGlideDisplayResolution(unsigned long& width, unsigned long& height) +{ + width = GlideDisplay.HorizontalPixels; + height = GlideDisplay.VerticalLines; + return GlideDisplay.Valid; +} + +CMError DisplayManager_SetGamma(DisplayModeSpec& display, FxFloat gamma) +{ + CMError err = noErr; + CMVideoCardGamma* gammatable = reinterpret_cast(display.VideoGammaTable); + if (gammatable && DisplayManager_applyGamma()) + { + gammatable->tagType = cmVideoCardGammaTableType; + gammatable->u.table.channels = 1; + const unsigned int entryCount = 256; + gammatable->u.table.entryCount = entryCount; + gammatable->u.table.entrySize = 2; + FxU16* gray = reinterpret_cast(&gammatable->u.table.data); + FxFloat biased_gamma = gamma + InternalConfig.GammaBias; + // Valid values go from 0.0 to 20.0 according to Glide24pgm + biased_gamma = max(0.0f, biased_gamma); + biased_gamma = min(biased_gamma, 20.0f); + for (unsigned int i = 0; i < entryCount; i++) + { + gray[i] = pow(i / 255.0, 1.0 / biased_gamma) * 65535; + } + err = CMSetGammaByAVID(display.DisplayID, gammatable); + if (err != noErr) + { + GlideMsg("Error: DisplayManager_SetGamma() failed with error code %d\n", err); + } + } + return err; +} + +void DisplayManager_SetGlideDisplayGamma(FxFloat gamma) +{ + CMError err = DisplayManager_SetGamma(GlideDisplay, gamma); +} + +CMError DisplayManager_RememberGamma(DisplayModeSpec& display) +{ + CMError err = noErr; + CMVideoCardGamma* gammatable = reinterpret_cast(display.VideoGammaTable); + if (gammatable && DisplayManager_applyGamma()) + { + UInt32 size = VideoGammaTableSize; + err = CMGetGammaByAVID(display.DisplayID, gammatable, &size); + if (err != noErr) + { + GlideMsg("Error: DisplayManager_RememberGamma() failed with error code %d\n", err); + } + } + return err; +} + +CMError DisplayManager_RestoreGamma(DisplayModeSpec& display) +{ + CMError err = noErr; + CMVideoCardGamma* gammatable = reinterpret_cast(display.VideoGammaTable); + if (display.GammaValid && gammatable && DisplayManager_applyGamma()) + { + err = CMSetGammaByAVID(display.DisplayID, gammatable); + if (err != noErr) + { + GlideMsg("Error: DisplayManager_RestoreGamma() failed with error code %d\n", err); + } + } + return err; +} + +void DisplayManager_RestorePassthroughDisplayGamma() +{ + DisplayManager_RestoreGamma(PassthroughDisplay); +} + +CMError DisplayManager_SetGammaBlack(DisplayModeSpec& display) +{ + CMError err = noErr; + // Only change if the gamma can be restored + if (display.GammaValid && DisplayManager_applyGamma()) + { + // We can savely use the Glide Display table, because it can be restored via SetGlideDisplayGamma() + CMVideoCardGamma* gammatable = reinterpret_cast(GlideDisplay.VideoGammaTable); + gammatable->tagType = cmVideoCardGammaTableType; + gammatable->u.table.channels = 1; + const unsigned int entryCount = 256; + gammatable->u.table.entryCount = entryCount; + gammatable->u.table.entrySize = 2; + FxU16* gray = reinterpret_cast(&gammatable->u.table.data); + memset(gray, 0, entryCount * gammatable->u.table.entrySize); + err = CMSetGammaByAVID(display.DisplayID, gammatable); + if (err != noErr) + { + GlideMsg("Error: DisplayManager_SetGammaBlack() failed with error code %d\n", err); + } + } + return err; +} + +void DisplayManager_SetGlideDisplayGammaBlack() +{ + DisplayManager_SetGammaBlack(GlideDisplay); +} + +void DisplayManager_SetPassthroughDisplayGammaBlack() +{ + DisplayManager_SetGammaBlack(PassthroughDisplay); +} + +void DisplayManager_SetDesktopDisplayGammaBlack() +{ + DisplayManager_SetGammaBlack(DesktopDisplay); +} diff --git a/MacGLide/Mac/GlideSettings.cpp b/MacGLide/Mac/GlideSettings.cpp new file mode 100644 index 0000000..581a484 --- /dev/null +++ b/MacGLide/Mac/GlideSettings.cpp @@ -0,0 +1,241 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideSettings_FSp.h" + +char* s_SettingsFolderName = "XMacGLide Settings"; +const char* s_DefaultSettingsFileName = "Defaults"; +const char* s_LogFileName = "MacGLide.log"; + +OSType s_SettingsFileCreator = 0x54545854; // "ttxt" +OSType s_SettingsFileType = 0x54455854; // "TEXT" +OSType s_LogFileCreator = 0x54545854; // "ttxt" +OSType s_LogFileType = 0x54455854; // "TEXT" + +GlideSettingsFSp::GlideSettingsFSp() +: m_vRefNumPrefsFolder(0) +, m_dirIDPrefsFolder(0) +, m_SettingsFileRefnum(0) +, m_LogFileRefnum(0) +{ +} + +GlideSettingsFSp::~GlideSettingsFSp(void) +{ + if (m_FileBuffer) DisposePtr(m_FileBuffer); + FSClose(m_LogFileRefnum); +} + +GlideSettings::IOErr GlideSettingsFSp::makeSettingsFolderFileSpec(const char* path, const char* filename, FSSpec* fsspec) +{ + char buffer[StringBufferSize]; + strcpy(&buffer[1], ":"); + strcat(&buffer[1], path); + strcat(&buffer[1], ":"); + strcat(&buffer[1], filename); + GlideSettings::IOErr err = FSMakeFSSpec(m_vRefNumPrefsFolder, m_dirIDPrefsFolder, PascalString(buffer), fsspec); + if (err == fnfErr) err = noErr; + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::init(const char* applicationname) +{ + // Make the settings folder + GlideSettings::IOErr err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &m_vRefNumPrefsFolder, &m_dirIDPrefsFolder); + if (err == noErr) + { + FSSpec fsspec; + err = FSMakeFSSpec(m_vRefNumPrefsFolder, m_dirIDPrefsFolder, PascalString(s_SettingsFolderName), &fsspec); + if (err == fnfErr) + { + long dirID; + err = FSpDirCreate(&fsspec, smSystemScript, &dirID); + } + } + // Make references to various files + if (err == noErr) + { + err = makeSettingsFolderFileSpec(&s_SettingsFolderName[1], applicationname, &m_fsSettingsFile); + if (err == noErr) + { + err = makeSettingsFolderFileSpec(&s_SettingsFolderName[1], s_DefaultSettingsFileName, &m_fsDefaultSettingsFile); + if (err == noErr) + { + err = makeSettingsFolderFileSpec(&s_SettingsFolderName[1], s_LogFileName, &m_fsLogFile); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::read_file(FSSpec* file, char** mem, long* size, short* refnum) +{ + GlideSettings::IOErr err = FSpOpenDF(file, fsRdPerm, refnum); + if (err == noErr) + { + err = GetEOF(*refnum, size); + if (err == noErr) + { + *mem = new char[*size + 1]; + (*mem)[*size] = 0x00; + err = FSRead(*refnum, size, *mem); + if (err == noErr) + { + err = FSClose(*refnum); + } + else + { + FSClose(*refnum); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::read_defaults() +{ +#ifdef OGL_DEBUG + GlideMsg("Reading default settings...\n"); +#endif + return read_settings_from_file(&m_fsDefaultSettingsFile, &GlideSettings::create_defaults); +} + +GlideSettings::IOErr GlideSettingsFSp::read() +{ +#ifdef OGL_DEBUG + GlideMsg("Reading application specific settings...\n"); +#endif + return read_settings_from_file(&m_fsSettingsFile, &GlideSettings::create); +} + +GlideSettings::IOErr GlideSettingsFSp::read_settings_from_file(FSSpec* file, GlideSettingsFSp::IOErr (GlideSettings::*default_creator) ()) +{ + GlideSettings::IOErr err = read_file(file, &m_FileBuffer, &m_FileBufferSize, &m_SettingsFileRefnum); + if (err != noErr) + { + // create file with default settings + defaults(); + err = (this->*default_creator)(); + if (err == noErr) + { + err = save(); + if (err == noErr) + { + // Now we have o load the file into memory to make the settings reader happy + err = read_file(file, &m_FileBuffer, &m_FileBufferSize, &m_SettingsFileRefnum); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::create_defaults() +{ +#ifdef OGL_DEBUG + GlideMsg("Creating new file with default settings...\n"); +#endif + GlideSettings::IOErr err = FSpDelete(&m_fsDefaultSettingsFile); + err = FSpCreate(&m_fsDefaultSettingsFile, s_SettingsFileCreator, s_SettingsFileType, smSystemScript); + if (err == noErr || err == dupFNErr) + { + err = FSpOpenDF(&m_fsDefaultSettingsFile, fsWrPerm, &m_SettingsFileRefnum); + } + if (err == noErr) + { +#ifdef OGL_DEBUG + GlideMsg("Looking for obsolete 0.09 settings in app dir...\n"); +#endif + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) + { + ProcessInfoRec info; + memset(&info, 0, sizeof(info)); + info.processInfoLength = sizeof(info); + FSSpec fsspec; + info.processAppSpec = &fsspec; + GlideSettings::IOErr err2 = GetProcessInformation(&psn, &info); + if (err2 == noErr) + { + const unsigned int number_of_old_files = 3; + char* old_files[number_of_old_files] = + { + "X:OpenGLid.INI", + "X:OpenGLid.LOG", + "X:OpenGLid.ERR" + }; + for(unsigned long i = 0; i < number_of_old_files; i++) + { + err2 = HDelete(fsspec.vRefNum, fsspec.parID, PascalString(old_files[i])); + if (err2 == noErr) GlideMsg("Removed 0.09 %s in app dir\n", &(old_files[i])[2]); + } + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::create() +{ +#ifdef OGL_DEBUG + GlideMsg("Creating new file with application specific settings...\n"); +#endif + GlideSettings::IOErr err = FSpDelete(&m_fsSettingsFile); + err = FSpCreate(&m_fsSettingsFile, s_SettingsFileCreator, s_SettingsFileType, smSystemScript); + if (err == noErr || err == dupFNErr) + { + err = FSpOpenDF(&m_fsSettingsFile, fsWrPerm, &m_SettingsFileRefnum); + if (err == noErr) + { + // Enable using this file + UseApplicationSpecificSettings = true; + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::put_raw(const char* string) +{ + long count = strlen(string); + GlideSettings::IOErr err = FSWrite(m_SettingsFileRefnum, &count, string); + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::close() +{ + GlideSettings::IOErr err = FSClose(m_SettingsFileRefnum); + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::create_log() +{ + GlideSettings::IOErr err = FSpDelete(&m_fsLogFile); + if (err == noErr || err == fnfErr) + { + err = FSpCreate(&m_fsLogFile, s_SettingsFileCreator, s_SettingsFileType, smSystemScript); + if (err == noErr) + { + err = FSpOpenDF(&m_fsLogFile, fsWrPerm, &m_LogFileRefnum); + } + } + return err; +} + +GlideSettings::IOErr GlideSettingsFSp::write_log(const char* message) +{ + long count = strlen(message); + IOErr err = FSWrite(m_LogFileRefnum, &count, message); + return err; +} + +const unsigned char* GlideSettingsFSp::PascalString(char* string) +{ + string[0] = static_cast(strlen(&string[1])); + return reinterpret_cast(string); +} diff --git a/MacGLide/Mac/GlideSettings_FSp.h b/MacGLide/Mac/GlideSettings_FSp.h new file mode 100755 index 0000000..c6e1acd --- /dev/null +++ b/MacGLide/Mac/GlideSettings_FSp.h @@ -0,0 +1,42 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "GlideSettings.h" + +class GlideSettingsFSp : public GlideSettings +{ +public: + GlideSettingsFSp(); + virtual ~GlideSettingsFSp(void); +public: + IOErr init(const char* application); + IOErr create_log(); + IOErr write_log(const char* message); +protected: + IOErr create_defaults(); + IOErr create(); + IOErr read_defaults(); + IOErr read(); + IOErr put_raw(const char* string); + IOErr close(); + const unsigned char* PascalString(char* string); + short m_vRefNumPrefsFolder; + long m_dirIDPrefsFolder; + FSSpec m_fsSettingsFile; + FSSpec m_fsDefaultSettingsFile; + short m_SettingsFileRefnum; + FSSpec m_fsLogFile; + short m_LogFileRefnum; + IOErr makeSettingsFolderFileSpec(const char* path, const char* filename, FSSpec* fsspec); + IOErr read_file(FSSpec* file, char** mem, long* size, short* refnum); + IOErr read_settings_from_file(FSSpec* file, IOErr (GlideSettings::*default_creator)()); +}; diff --git a/MacGLide/Mac/MacGLide.cpp b/MacGLide/Mac/MacGLide.cpp new file mode 100644 index 0000000..c746592 --- /dev/null +++ b/MacGLide/Mac/MacGLide.cpp @@ -0,0 +1,449 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Mac specific functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "FormatConversion.h" +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideDisplay.h" +#include "GlideSettings.h" +#include "GLExtensions.h" +#include "GLRender.h" + +#ifdef OGL_PROFILING +#include +#endif + +OSErr __macglide_initialize(struct CFragInitBlock* initBlkPtr) +{ + OSErr err = __initialize((CFragInitBlock*) initBlkPtr); + if (err == noErr) + { +#ifdef OGL_PROFILING + err = ProfilerInit(collectSummary, bestTimeBase, 666, 666); + assert(err == noErr); + ProfilerSetStatus(1); +#endif + err = UserConfig.init(s_GlideApplication.GetName()); + if (err == noErr) + { + if (!ClearAndGenerateLogFile()) + { + GlideError("Unable to init log file: Error code %d", err); + } + else + { + InitMainVariables(); + DisplayManager_Initialise(); + err = DisplayManager_RememberDesktopDisplay(); + GlideMsg(OGL_LOG_SEPARATE); + } + } + } + return err; +} + +void __macglide_terminate() +{ +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + grGlideShutdown(); + OSErr err = DisplayManager_RestoreDesktopDisplay(); + DisplayManager_Cleanup(); + CloseLogFile(); + if (Glide.ReadBuffer.Address) + { + FreeFrameBuffer(Glide.ReadBuffer.Address); + Glide.ReadBuffer.Address = NULL; + } + +#ifdef OGL_PROFILING + char* filename = "XMacGLide Profiler stats"; + filename[0] = strlen(&filename[1]); + err = ProfilerDump(reinterpret_cast(filename)); + ProfilerTerm(); +#endif + + __terminate(); +} + +const char* OpenGLideProductName = "MacGLide"; + +// Allow allocation of memory at 16-byte boundaries to support altivec +void* AllocSysPtr16ByteAligned(long buffersize) +{ + void* buffer = NewPtrSys(buffersize + 16); + if (buffer == NULL) return NULL; + unsigned long aligned_buffer = (reinterpret_cast(buffer) + 16) & 0xfffffff0; + // remember the real location of the buffer + (reinterpret_cast(aligned_buffer))[-1] = reinterpret_cast(buffer); + return reinterpret_cast(aligned_buffer); +} + +void Free16ByteAligned(void* aligned_buffer) +{ + DisposePtr((Ptr) (static_cast(aligned_buffer))[-1]); +} + +void FatalErrorMessageBox(const char* message) +{ + unsigned char buffer1[] = "XMacGLide has encountered an unrecoverable error and cannot continue. Excuse:"; + buffer1[0] = strlen(reinterpret_cast(&buffer1[1])); + unsigned char buffer2[StringBufferSize + 1]; + strncpy(reinterpret_cast(&buffer2[1]), message, StringBufferSize -1); + buffer2[0] = strlen(message); + buffer2[buffer2[0] + 1] = 0x0; + SInt16 itemhit; + StandardAlert(kAlertStopAlert, buffer1, buffer2, NULL, &itemhit); +} + +char* _strtime(char* timebuf) +{ + time_t systime; + struct tm *currtime; + systime = time(NULL); + currtime = localtime(&systime); + strftime(timebuf, 128, "%X", currtime); + return timebuf; +} + +char* _strdate(char* timebuf) +{ + time_t systime; + struct tm *currtime; + systime = time(NULL); + currtime = localtime(&systime); + strftime(timebuf, 128, "%x", currtime); + return timebuf; +} + +////////////////////////////////////////////////////////////// +// Big endian conversion functions +////////////////////////////////////////////////////////////// + +// Note about anisotropy and chromakeying: +// If anisotropy is enabled, some textured objects contain +// chromakey-colored pixels. +// This happens because chromakey pixels keep their color values, +// and only the alpha value is set to 0. If the texture is rendered +// with anisotropy enabled (also happened in the framebuffer emulation +// with linear texture filter), the chromakeyed pixels are somehow +// combined with a neighboring (non-chromakey colored) pixel. +// This seems to change the alpha value and as a result, the pixels +// pass the alpha test and are rendered. +// To minimise the resulting artefacts, the color of the chroma-keyed pixel +// is set to the color of the neighboring pixel. + +// Used by MacGLide for lossy conversions +void Convert565Kto5551(const FxU32* Buffer1, FxU32 key, FxU32* Buffer2, FxU32 NumberOfPixels ) +{ + // Convert565Kto5551((unsigned long*) Src, (unsigned long*) Dst, NumberOfPixels); + // This functions processes 2 pixels at a time, there is no problem in + // passing odd numbers or a number less than 2 for the pixels, but + // the buffers should be large enough + FxU32 key1 = key & 0xffff; + FxU32 key2 = key << 16; + while ( NumberOfPixels > 0) + { + FxU32 src1 = *Buffer1 && 0xffff; + FxU32 dest; + if (key1 == src1) + { + dest = 0; + } + else + { + dest = src1; + } + FxU32 src2 = (*Buffer1 && 0xffff0000); + if (key2 != src2) + { + dest = dest | src2; + } + *Buffer2++ = ( (dest) & 0xFFC0FFC0 ) | + ( ( (dest) & 0x001F001F ) << 1 ) | + 0x00010001; + Buffer1++; + NumberOfPixels -= 2; + } +} + +void Convert565Kto8888(const FxU16* src, FxU16 key, FxU32* dst, FxU32 pixels) +{ + // Scan for first non-chromakey pixel + // in order to find to the starting value + // for the chromakey_replacement + const register FxU32 mask_pixel_r = 0x0000f800; + const register FxU32 mask_pixel_g = 0x000007e0; + const register FxU32 mask_pixel_b = 0x0000001f; + register FxU16 chromakey_replacement_565 = 0x0000; + for(const FxU16* p = src; p < (src + pixels); p++) + { + chromakey_replacement_565 = *p; + if (chromakey_replacement_565 != key) break; + } + register FxU32 rgb_mask_8888 = 0xffffff00; + register FxU32 chromakey_replacement_8888 = 0x00000000; + chromakey_replacement_8888 = (0x00000000 | // A + (chromakey_replacement_565 & mask_pixel_b) << 11 | // B + (chromakey_replacement_565 & mask_pixel_g) << 13 | // G + (chromakey_replacement_565 & mask_pixel_r) << 16); // R + // Start the conversion + register FxU16 pixel_565; + register FxU32 pixel_8888; + while (pixels) + { + pixel_565 = *src++; + if (pixel_565 == key) + { + // Minimise anisotropy artefacts + pixel_8888 = chromakey_replacement_8888; + } + else + { + pixel_8888 = (0x000000ff | // A + (pixel_565 & mask_pixel_b) << 11 | // B + (pixel_565 & mask_pixel_g) << 13 | // G + (pixel_565 & mask_pixel_r) << 16); // R + chromakey_replacement_8888 = pixel_8888 & rgb_mask_8888; + } + *dst++ = pixel_8888; + pixels--; + } +} + +void ConvertA8toAP88(const FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ) +{ + while ( Pixels ) + { + *Buffer2 = ( ( ( *Buffer1 ) << 8 ) | ( *Buffer1 ) ); + Buffer1++; + Buffer2++; + Pixels--; + } +} + +void Convert8332to8888(const FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ) +{ + FxU32 R, G, B, A; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + A = ( ( ( *Buffer1 ) >> 8 ) & 0xFF ); + R = ( ( ( *Buffer1 ) >> 5 ) & 0x07 ) << 5; + G = ( ( ( *Buffer1 ) >> 2 ) & 0x07 ) << 5; + B = ( ( *Buffer1 ) & 0x03 ) << 6; + *Buffer2 = ( R << 24 ) | ( G << 16 ) | ( B << 8 ) | A; + + Buffer1++; + Buffer2++; + } +} + +void ConvertP8to8888(const FxU8 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ) +{ + while ( Pixels-- ) + { + *Buffer2++ = palette[ *Buffer1++ ]; + } +} + +void ConvertP8Kto8888(const FxU8 *Buffer1, FxU32 Key, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ) +{ + // Scan for first non-chromakey pixel + // in order to find to the starting value + // for the chromakey_replacement + register FxU32 chromakey_replacement = 0; + register FxU32 chromakey = Key; + register FxU32 alpha_mask = 0xffffff00; + for(const FxU8* b = Buffer1; b < (Buffer1 + Pixels); b++) + { + chromakey_replacement = (palette[*b] & alpha_mask); + if (chromakey_replacement != chromakey) break; + } + // Start the conversion + register FxU32 current_pixel = 0; + while ( Pixels-- ) + { + current_pixel = palette[*Buffer1++]; + if (current_pixel == chromakey) + { + *Buffer2 = chromakey_replacement; + } + else + { + *Buffer2 = current_pixel; + chromakey_replacement = current_pixel & alpha_mask; + } + Buffer2++; + } +} + +void ConvertAI44toAP88(const FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ) +{ + for ( FxU32 i = Pixels; i > 0; i-- ) + { + *Buffer2 = ( ( ( ( *Buffer1 ) & 0xF0 ) << 8 ) | ( ( ( *Buffer1 ) & 0x0F ) << 4 ) ); + Buffer2++; + Buffer1++; + } +} + +void ConvertAP88to8888(const FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ) +{ + FxU32 RGB, + A; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + RGB = ( palette[ *Buffer1 & 0x00ff ] & 0xffffff00 ); + A = *Buffer1 >> 8; + *Buffer2 = A | RGB; + Buffer1++; + Buffer2++; + } +} + +void ConvertYIQto8888(const FxU8 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc ) +{ + FxI32 R; + FxI32 G; + FxI32 B; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + R = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 0 ]; + + G = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 1 ]; + + B = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 2 ]; + + // Clamp values + R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) ); + G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) ); + B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) ); + + *out = ( (R << 24) | ( G << 16 ) | ( B << 8 ) | 0x000000ff ); + in++; + out++; + } +} + +void ConvertAYIQto8888(const FxU16 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc) +{ + FxI32 R; + FxI32 G; + FxI32 B; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + R = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 0 ]; + + G = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 1 ]; + + B = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 2 ]; + + R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) ); + G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) ); + B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) ); + + *out = ( (R <<24) | ( G << 16 ) | ( B << 8 ) | ( /*0x000000ff &*/ ( *in >> 8 ) ) ); + + in++; + out++; + } +} + +void SplitAP88(const FxU16 *ap88, FxU8 *index, FxU8 *alpha, FxU32 pixels ) +{ + for ( FxU32 i = pixels; i > 0; i-- ) + { + *alpha++ = ( *ap88 >> 8 ); + *index++ = ( *ap88++ & 0xff ); + } +} + +// Color conversion functions: The windows version converts colors to ARGB, +// whereas the mac version converts colors to RGBA (no extension needed) +void ConvertColor4B( GrColor_t GlideColor, FxU32 &C ) +{ + switch ( Glide.State.ColorFormat ) + { + case GR_COLORFORMAT_ARGB: //0xAARRGGBB + C = ( ( GlideColor & 0x00ffffff ) << 8 ) | + ( ( GlideColor & 0xff000000 ) >> 24 ); + break; + + case GR_COLORFORMAT_ABGR: //0xAABBGGRR + C = ( ( GlideColor & 0xff000000 ) >> 24 ) | + ( ( GlideColor & 0x00ff0000 ) >> 8 ) | + ( ( GlideColor & 0x0000ff00 ) << 8 ) | + ( ( GlideColor & 0x000000ff ) << 24 ); + break; + + case GR_COLORFORMAT_RGBA: //0xRRGGBBAA + C = GlideColor; + break; + + case GR_COLORFORMAT_BGRA: //0xBBGGRRAA + C = ( ( GlideColor & 0xFF000000 ) >> 24 ) | + ( ( GlideColor & 0x0000ff00 ) << 16 ) | + ( ( GlideColor & 0x0ff000ff ) ); + break; + } +} + +void Convert1555Kto8888(const FxU16* src, FxU16 key, FxU32* dst, FxU32 pixels) +{ + // Scan for first non-chromakey pixel + // in order to find to the starting value + // for the chromakey_replacement + const register FxU32 mask_pixel_r = 0x00007c00; + const register FxU32 mask_pixel_g = 0x000003e0; + const register FxU32 mask_pixel_b = 0x0000001f; + const register FxU32 mask_pixel_a = 0x00008000; + register FxU16 chromakey_replacement_1555 = 0x0000; + register FxU16 chromakey = key & 0x7fff; + for(const FxU16* p = src; p < (src + pixels); p++) + { + chromakey_replacement_1555 = *p; + if (chromakey_replacement_1555 != chromakey) break; + } + register FxU32 rgb_mask_8888 = 0xffffff00; + register FxU32 chromakey_replacement_8888 = 0x00000000; + chromakey_replacement_8888 = (0x00000000 | // A + (chromakey_replacement_1555 & mask_pixel_b) << 11 | // B + (chromakey_replacement_1555 & mask_pixel_g) << 14 | // G + (chromakey_replacement_1555 & mask_pixel_r) << 17); // R + // Start the conversion + register FxU16 pixel_1555; + register FxU32 pixel_8888; + while (pixels) + { + pixel_1555 = *src++; + if ((pixel_1555 & 0x7fff) == chromakey) + { + // Minimise anisotropy artefacts + pixel_8888 = chromakey_replacement_8888; + } + else + { + pixel_8888 = (((pixel_1555 & mask_pixel_a) ? 0x000000ff : 0x00000080) | // A + (pixel_1555 & mask_pixel_b) << 11 | // B + (pixel_1555 & mask_pixel_g) << 14 | // G + (pixel_1555 & mask_pixel_r) << 17); // R + chromakey_replacement_8888 = pixel_8888 & rgb_mask_8888; + } + *dst++ = pixel_8888; + pixels--; + } +} diff --git a/MacGLide/Mac/MacGLide.h b/MacGLide/Mac/MacGLide.h new file mode 100644 index 0000000..9728209 --- /dev/null +++ b/MacGLide/Mac/MacGLide.h @@ -0,0 +1,50 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Shared Library entry points +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +// library entry points +#pragma export on +extern "C" OSErr __macglide_initialize(struct CFragInitBlock* initBlkPtr); +extern "C" void __macglide_terminate(); +extern "C" OSErr __initialize(struct CFragInitBlock* initBlkPtr); +extern "C" void __terminate(); +#pragma export off + +// Not declared in MSL +char* _strtime(char* tmpbuf); +char* _strdate(char* tmpbuf); + +// OpenGL extension data not available in MacOS 9 but +// provided by the MacOS X OpenGL driver in Classic + +// GL_APPLE_client_storage +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 + +// GL_ARB_multisample +// aglChoosePixelFormat +#define AGL_SAMPLE_BUFFERS_ARB 55 +#define AGL_SAMPLES_ARB 56 +// aglSetInteger +#define AGL_ATI_FSAA_LEVEL 510 + +// GL_NV_multisample_filter_hint +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +// GL_ARB_texture_env_combine +#define GL_SUBTRACT_ARB 0x84E7 + +// GL_ATI_texture_env_combine3 +#define GL_MODULATE_ADD_ATI 0x8744 + +// Swap limit +#define AGL_SWAP_LIMIT 203 diff --git a/MacGLide/Mac/MacGLide.rsrc b/MacGLide/Mac/MacGLide.rsrc new file mode 100644 index 0000000..e69de29 diff --git a/MacGLide/Mac/SetupGL/Carbon_Error_Handler.c b/MacGLide/Mac/SetupGL/Carbon_Error_Handler.c new file mode 100755 index 0000000..79f3966 --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_Error_Handler.c @@ -0,0 +1,261 @@ +/* + File: Carbon Error Handler.c + + Contains: SetupGL error handling + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999-2001 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <1> 1/19/01 ggs Initial re-add + <4> 1/24/00 ggs double check for latest + <4> 1/24/00 ggs double check for latest + <3> 12/18/99 ggs Fix headers + <2> 11/28/99 ggs Added verbose error flag + <1> 11/28/99 ggs Initial add. Split of just error handling functions. Need to + add more reporting examples + <1> 11/11/99 ggs Initial Add + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleŐs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define kVerboseErrors +//#define kQuake3 + +// system includes ---------------------------------------------------------- + +#ifdef kQuake3 +typedef int sysEventType_t; // FIXME... +#endif + +#ifdef __APPLE_CC__ + #include +#else + #include +#endif + +#include + + +// project includes --------------------------------------------------------- + +#include "Carbon_SetupDSp.h" +#include "Carbon_Error_Handler.h" + +#ifdef kQuake3 +#include "../renderer/tr_local.h" +#include "mac_local.h" +#endif + + +// globals (internal/private) ----------------------------------------------- + + +// prototypes (internal/private) -------------------------------------------- + +static void CStrToPStr (StringPtr outString, const char *inString); + + +// functions (internal/private) --------------------------------------------- + +// Copy C string to Pascal string + +static void CStrToPStr (StringPtr outString, const char *inString) +{ + unsigned char x = 0; + do + *(((char*)outString) + x + 1) = *(inString + x++); + while ((*(inString + x) != 0) && (x < 256)); + *((char*)outString) = (char) x; +} + +#pragma mark - +// -------------------------------------------------------------------------- + +// central error reporting + +void ReportErrorNum (char * strError, long numError) +{ + GlideMsg(strError, "%s %ld (0x%lx)\n", strError, numError, numError); + +/* + char errMsgCStr [256]; + Str255 strErr = "\p"; + + // out as debug string +#ifdef kVerboseErrors + #ifdef kQuake3 + ri.Printf( PRINT_ALL, errMsgCStr); + #else + // ensure we are faded in + if (gDSpStarted) + DSpContext_CustomFadeGammaIn (NULL, NULL, 0); + CStrToPStr (strErr, errMsgCStr); + DebugStr (strErr); + #endif // kQuake3 +#endif // kVerboseErrors +*/ +} + +// -------------------------------------------------------------------------- + +void ReportError (char * strError) +{ + GlideError(strError); + +/* + char errMsgCStr [256]; + Str255 strErr = "\p"; + + sprintf (errMsgCStr, "%s\n", strError); + // out as debug string +#ifdef kVerboseErrors + #ifdef kQuake3 + ri.Printf( PRINT_ALL, errMsgCStr); + #else + // ensure we are faded in + if (gDSpStarted) + DSpContext_CustomFadeGammaIn (NULL, NULL, 0); + CStrToPStr (strErr, errMsgCStr); + DebugStr (strErr); + #endif // kQuake3 +#endif // kVerboseErrors +*/ +} + +//----------------------------------------------------------------------------------------------------------------------- + +OSStatus DSpReportError (OSStatus error) +{ + switch (error) + { + case noErr: + break; + case kDSpNotInitializedErr: + ReportError ("DSp Error: Not initialized"); + break; + case kDSpSystemSWTooOldErr: + ReportError ("DSp Error: system Software too old"); + break; + case kDSpInvalidContextErr: + ReportError ("DSp Error: Invalid context"); + break; + case kDSpInvalidAttributesErr: + ReportError ("DSp Error: Invalid attributes"); + break; + case kDSpContextAlreadyReservedErr: + ReportError ("DSp Error: Context already reserved"); + break; + case kDSpContextNotReservedErr: + ReportError ("DSp Error: Context not reserved"); + break; + case kDSpContextNotFoundErr: + ReportError ("DSp Error: Context not found"); + break; + case kDSpFrameRateNotReadyErr: + ReportError ("DSp Error: Frame rate not ready"); + break; + case kDSpConfirmSwitchWarning: +// ReportError ("DSp Warning: Must confirm switch"); // removed since it is just a warning, add back for debugging + return 0; // don't want to fail on this warning + break; + case kDSpInternalErr: + ReportError ("DSp Error: Internal error"); + break; + case kDSpStereoContextErr: + ReportError ("DSp Error: Stereo context"); + break; + } + return error; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// if error dump agl errors to debugger string, return error + +OSStatus aglReportError (void) +{ + GLenum err = aglGetError(); + if (AGL_NO_ERROR != err) + { + GlideError("AGL-Error: %s\n", reinterpret_cast(aglErrorString(err))); + } + // ensure we are returning an OSStatus noErr if no error condition + if (err == AGL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// if error dump gl errors to debugger string, return error +/* +OSStatus glReportError (void) +{ + GLenum err = glGetError(); + switch (err) + { + case GL_NO_ERROR: + break; + case GL_INVALID_ENUM: + ReportError ("GL Error: Invalid enumeration"); + break; + case GL_INVALID_VALUE: + ReportError ("GL Error: Invalid value"); + break; + case GL_INVALID_OPERATION: + ReportError ("GL Error: Invalid operation"); + break; + case GL_STACK_OVERFLOW: + ReportError ("GL Error: Stack overflow"); + break; + case GL_STACK_UNDERFLOW: + ReportError ("GL Error: Stack underflow"); + break; + case GL_OUT_OF_MEMORY: + ReportError ("GL Error: Out of memory"); + break; + } + // ensure we are returning an OSStatus noErr if no error condition + if (err == GL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} +*/ \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Carbon_Error_Handler.h b/MacGLide/Mac/SetupGL/Carbon_Error_Handler.h new file mode 100755 index 0000000..7afa34a --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_Error_Handler.h @@ -0,0 +1,106 @@ +/* + File: Carbon Error Handler.h + + Contains: Functions to enable build and destory a GL fullscreen context + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <1> 1/19/01 ggs Initial re-add + <3> 1/24/00 ggs added C++ support + <2> 12/18/99 ggs Fix headers + <1> 11/28/99 ggs Initial add. Split of just error handling functions. Need to + add more reporting examples + <1> 11/11/99 ggs Initial Add + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleŐs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +// Usage notes: + + + +// include control -------------------------------------------------- + +#ifndef Error_Handler_h +#define Error_Handler_h + + +// includes --------------------------------------------------------- + +#ifdef __APPLE_CC__ + #include + #include +#else + #include + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// structures (public) ----------------------------------------------- + + +// public function declarations ------------------------------------- + +// Error reporter, can be set to report however the application desires +void ReportError (char * strError); + +// Error with numeric code reporter, can be set to report however the application desires +void ReportErrorNum (char * strError, long numError); + +// Handle reporting of DSp errors, error code is passed through +OSStatus DSpReportError (OSStatus error); + +// Handle reporting of agl errors, error code is passed through +OSStatus aglReportError (void); + +// Handle reporting of OpenGL errors, error code is passed through +//OSStatus glReportError (void); + + +#ifdef __cplusplus +} +#endif + +#endif // Error_Handler_h \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Carbon_SetupDSp.c b/MacGLide/Mac/SetupGL/Carbon_SetupDSp.c new file mode 100755 index 0000000..774fa38 --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_SetupDSp.c @@ -0,0 +1,925 @@ +/* + File: SetupDSp.c + + Contains: Functions to enable building and destorying a DSp fullscreen context + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <3> 3/26/01 ggs Add DSp version check and other items for full screen on X + <2> 3/26/01 ggs Add new DSp functinality for Mac OS X + <1> 1/19/01 ggs Initial re-add + <7> 3/21/00 ggs Added windowed mode and clean up various implementation details + <6> 2/22/00 ggs fix fades + <5> 1/26/00 ggs Add fade code back in, ensure NULL pointer/context checks are in + <4> 1/24/00 ggs add new disclaimer, protection from NULL dispose, better + software renderer handling + <3> 12/18/99 ggs Fixed err use before init + <2> 12/18/99 ggs Fix headers + <1> 11/28/99 ggs Initial add. Split of just DSp handling functions. Added total + device RAM checks, better step downs using actual supported + resolutions. Need to add user verify for contexts that require + it, integration of this in context step down, and a freq bit + field. + <1> 11/11/99 ggs Initial Add + + Disclaimer: You may incorporate this sample code into your applications without + restriction, though the sample code has been provided "AS IS" and the + responsibility for its operation is 100% yours. However, what you are + not permitted to do is to redistribute the source as "DSC Sample Code" + after having made changes. If you're going to re-distribute the source, + we require that you make it clear in the source that the code was + descended from Apple Sample Code, but that you've made changes. +*/ + +/* changes for OpenGLide for Macintosh + + Change History (most recent first): + + <1> 2/6/04 jenz Changed BuildResolutionList to list up all frequencies for each resolution +*/ + +// Usage notes: +// kUseFades enables gamma fades for activates and deactivates +#define kUseFades + +// kUseRAMCheck enables estimated video card RAM checks +#define kUseRAMCheck + + +// system includes ---------------------------------------------------------- + +#ifdef __APPLE_CC__ + #include +#else + #include + #include + + #include +#endif + +#include + +// project includes --------------------------------------------------------- + +#include "Carbon_Error_Handler.h" +#include "Carbon_SetupDSp.h" + +// globals (internal/private) ----------------------------------------------- + +enum +{ + kMaxNumRes = 128, // max number of resolution slots + kMaxRefreshFreq = 120 +}; + +Boolean gDSpStarted = false; // will never be true unless DSp is installed and start succeeds +Boolean gNeedFade = false; + +// prototypes (internal/private) -------------------------------------------- + +DSpContextReference * ReserveUnusedDevices (GDHandle hGD); +OSStatus FreeUnusedDevices (GDHandle hGD, DSpContextReference ** ppContextRefUnused); +void BuildResolutionList (GDHandle hGD, Point * pResList, SInt32 * pFreqList); +OSStatus DoDeviceRAMCheck (pstructGLInfo pcontextInfo, Point * pResList, SInt32 * pFreqList, GLint depthSizeSupport); +Boolean DoContextStepDown (pstructGLInfo pcontextInfo, DSpContextAttributes * pContextAttributes, Point * pResList, SInt32 * pFreqList); + + +// functions (internal/private) --------------------------------------------- + +// ReserveUnusedDevices + +// reserves contexts on unused devices to vprevent their selection by DSp, returns list of these devices + +DSpContextReference * ReserveUnusedDevices (GDHandle hGD) +{ + DSpContextAttributes theContextAttributes; + DSpContextReference * pContextRefUnused = NULL; + GDHandle hDevice = DMGetFirstScreenDevice (true); // check number of screens + DisplayIDType displayID = 0; + short numDevices = 0, indexDevice = 0; + + do + { + numDevices++; + hDevice = DMGetNextScreenDevice (hDevice, true); + } + while (hDevice); + numDevices--; // only count unused screens + if (numDevices) + { + pContextRefUnused = (DSpContextReference *) NewPtr ((long) sizeof (DSpContextReference) * numDevices); + hDevice = DMGetFirstScreenDevice (true); // check number of screens + do + { + if (hDevice != hGD) // if this device is not the one the user chose + { + if (noErr == DSpReportError (DMGetDisplayIDByGDevice (hDevice, &displayID, false))) + if (noErr == DSpReportError (DSpGetFirstContext (displayID, &pContextRefUnused [indexDevice]))) // get a context and + if (noErr == DSpReportError (DSpContext_GetAttributes (pContextRefUnused [indexDevice], &theContextAttributes))) // find attributes + DSpReportError (DSpContext_Reserve (pContextRefUnused [indexDevice], &theContextAttributes)); // reserve it + indexDevice++; + } + hDevice = DMGetNextScreenDevice (hDevice, true); + } + while (hDevice); + } + return pContextRefUnused; +} + +// -------------------------------------------------------------------------- + +// FreeUnusedDevices + +// frees screen that were previously reserved to prevent selection + +OSStatus FreeUnusedDevices (GDHandle hGD, DSpContextReference ** ppContextRefUnused) +{ + OSStatus err = noErr; + GDHandle hDevice = DMGetFirstScreenDevice (true); // check number of screens + short indexDevice = 0; + + do + { + if (hDevice != hGD) // if this device is not the one the user chose + { + err = DSpContext_Release (*ppContextRefUnused [indexDevice]); // release it + DSpReportError (err); + indexDevice++; + } + hDevice = DMGetNextScreenDevice (hDevice, true); + } + while (hDevice); + + if (*ppContextRefUnused) + DisposePtr ((Ptr) *ppContextRefUnused); + *ppContextRefUnused = NULL; + return err; +} + +// -------------------------------------------------------------------------- + +// BuildResolutionList + +// builds a list of supported resolutions and frequencies for GDevice + +void BuildResolutionList (GDHandle hGD, Point * pResList, SInt32 * pFreqList) +{ + DSpContextAttributes theContextAttributes; + DSpContextReference currContext; + OSStatus err; + DisplayIDType displayID = 0; + short i; + + for (i = 0; i < kMaxNumRes; i++) // clear resolution list + { + pResList [i].h = 0x7FFF; + pResList [i].v = 0x7FFF; + pFreqList [i] = 0; // some context require certain frequencies find highest for each (not higher than 85 + } + + err = DMGetDisplayIDByGDevice (hGD, &displayID, true); + if (noErr != err) + ReportErrorNum ("DMGetDisplayIDByGDevice error", err); + else + { + if (noErr == DSpReportError (DSpGetFirstContext (displayID, &currContext))) + do + { + // insertion sort into resolution list + if (noErr == DSpReportError (DSpContext_GetAttributes (currContext, &theContextAttributes))) + { + Point pntTemp; + Boolean fDone = false; + short i = 0; + while ((i < kMaxNumRes) && (!fDone)) + { + // Don't just look for the highest vertical refresh rate, + // get all refresh rates for a resolution + if ((theContextAttributes.displayWidth == pResList [i].h) + && (theContextAttributes.displayHeight == pResList [i].v) + && (theContextAttributes.frequency == pFreqList[i] )) //skip + { + // avoid zero frequency + if ((pFreqList [i] == 0) || ((theContextAttributes.frequency <= (kMaxRefreshFreq << 16)) + && (theContextAttributes.frequency > pFreqList [i]))) + { + pFreqList [i] = theContextAttributes.frequency; + } + break; + } + if (theContextAttributes.displayWidth * theContextAttributes.displayHeight < pResList [i].h * pResList [i].v) //insert + { + pntTemp = pResList [i]; + pResList [i].h = (short) theContextAttributes.displayWidth; + pResList [i].v = (short) theContextAttributes.displayHeight; + pFreqList [i] = theContextAttributes.frequency; + fDone = true; + } + i++; + } + // i points to next element to switch; finish array swaps (if + while ((i < kMaxNumRes) && (fDone)) + { + Point pntSwitch = pResList [i]; + pResList [i++] = pntTemp; + pntTemp = pntSwitch; + } + } + err = DSpGetNextContext (currContext, &currContext); + if (noErr != err) + { + if (kDSpContextNotFoundErr != err) + DSpReportError (err); + currContext = 0; // ensure we drop out + } + } + while (currContext); + else + ReportErrorNum ("DSpGetFirstContext error", err); + } + // zeroize unused elements + for (i = 0; i < kMaxNumRes; i++) + if ((pResList [i].h == 0x7FFF) || (pResList [i].v == 0x7FFF)) + { + pResList [i].h = 0; + pResList [i].v = 0; + } +} + +// -------------------------------------------------------------------------- + +// DoDeviceRAMCheck + +// checks requested allocation against device RAM +// Note: may modify pcontextInfo +// this should be equal or less strigent than OpenGL actual allocation to avoid failing on valid drawables + +OSStatus DoDeviceRAMCheck (pstructGLInfo pcontextInfo, Point * pResList, SInt32 * pFreqList, GLint depthSizeSupport) +{ + float frontBufferFactor = 1.0f, backBufferFactor = 0.0f; // amount of screen(front) or request(back) sized buffers required, in bytes + Point pntFrontBuffer; // size of front buffer that wil be allocated + short i, indexFrontBuffer; + OSStatus err = noErr; + + // must take into account the entire front buffer, so figure out what screen resolution we are really going to use + // find front buffer for request + i = 0; + while (((pResList [i].h < pcontextInfo->width) || (pResList [i].v < pcontextInfo->height)) && + ((pResList [i].h != 0) || (pResList [i].v != 0)) && + (i < kMaxNumRes)) + i++; + while (((pResList [i].h == pcontextInfo->width) || (pResList [i].v == pcontextInfo->height)) && + ((pResList [i].h != 0) || (pResList [i].v != 0)) && + (i < kMaxNumRes) && pFreqList[i + 1] <= pcontextInfo->freq << 16) + i++; + // save front buffer sizes + pntFrontBuffer.h = pResList [i].h; + pntFrontBuffer.v = pResList [i].v; + // if we have a valid frequency for the context set it (to ensure a good selection + pcontextInfo->freq = pFreqList [i] >> 16; + indexFrontBuffer = i; + + // front buffers required + if (16 == pcontextInfo->pixelDepth) + frontBufferFactor *= 2.0; + else if (32 == pcontextInfo->pixelDepth) + frontBufferFactor *= 4.0; + + // back buffers required + backBufferFactor = 0.0f; + i = 0; + while (64 > i) + if (AGL_DOUBLEBUFFER == pcontextInfo->aglAttributes[i++]) + { + if (16 == pcontextInfo->pixelDepth) + backBufferFactor = 2.0f; + else if (32 == pcontextInfo->pixelDepth) + backBufferFactor = 4.0f; + break; + } + i = 0; + while (64 > i) + if (AGL_DEPTH_SIZE == pcontextInfo->aglAttributes[i++]) + { + long requestDepth = pcontextInfo->aglAttributes[i]; + GLint bit = 0x00000001; + short currDepth = 0, prevDepth = 0; +// if (depthSizeSupport) +// { + do + { + if (bit & depthSizeSupport) // if the card supports the depth + { + prevDepth = currDepth; + switch (bit) + { + case AGL_1_BIT: + currDepth = 1; + break; + case AGL_2_BIT: + currDepth = 2; + break; + case AGL_3_BIT: + currDepth = 3; + break; + case AGL_4_BIT: + currDepth = 4; + break; + case AGL_5_BIT: + currDepth = 5; + break; + case AGL_6_BIT: + currDepth = 6; + break; + case AGL_8_BIT: + currDepth = 8; + break; + case AGL_10_BIT: + currDepth = 10; + break; + case AGL_12_BIT: + currDepth = 12; + break; + case AGL_16_BIT: + currDepth = 16; + break; + case AGL_24_BIT: + currDepth = 24; + break; + case AGL_32_BIT: + currDepth = 32; + break; + case AGL_48_BIT: + currDepth = 48; + break; + case AGL_64_BIT: + currDepth = 64; + break; + case AGL_96_BIT: + currDepth = 96; + break; + case AGL_128_BIT: + currDepth = 128; + break; + } + } + bit *= 2; + } while (!((requestDepth > prevDepth) && (requestDepth <= currDepth)) && (bit < AGL_128_BIT + 1)); +// } +// else // no card depth support info +// currDepth = requestDepth; // we don't have card info thus assume we can support exact depth requested (may fail later but will always be equal or less stringent) + if ((AGL_128_BIT >= bit) && (0 != currDepth)) + backBufferFactor += (float) currDepth / 8.0; + break; + } + + // What we now have: + // pcontextInfo->width, height: request width and height + // pResList: sorted list of resolutions supported on this display + // pntFrontBuffer : size of front buffer that will currently be allocated + // indexFrontBuffer: position in array of current front buffer request + // frontBufferFactor: number of screen resolution size buffers that will be needed + // backBufferFactor: number of request size buffers that will be needed + + // if we see zero VRAM here we must be looking at the software renderer thus this check is moot. + if (pcontextInfo->VRAM == 0) + { + // no changes required + return noErr; + } + + + // find a context size that can support our texture requirements in the current total VRAM + if ((pcontextInfo->VRAM - pcontextInfo->textureRAM) < (pntFrontBuffer.h * pntFrontBuffer.v * frontBufferFactor + + pcontextInfo->width * pcontextInfo->height * backBufferFactor)) + { + if (pcontextInfo->fDepthMust && pcontextInfo->fSizeMust) + { + // cannot accomdate request + ReportError ("Not enough total VRAM for drawable and textures (depth buffer and pixel size must be as requested)"); + return err; + } + else if (pcontextInfo->fSizeMust) // if we can adjust the size, try adjusting the + { + // try 16 bit if must size is true + if ((pcontextInfo->pixelDepth > 16) && + (pcontextInfo->VRAM - pcontextInfo->textureRAM) > (pntFrontBuffer.h * pntFrontBuffer.v * frontBufferFactor / 2.0 + + pcontextInfo->width * pcontextInfo->height * (backBufferFactor - 2.0))) + pcontextInfo->pixelDepth = 16; + else + { + // cannot accomdate request + ReportError ("Not enough total VRAM for drawable and textures"); + return err; + } + } + else // can adjust size and might be able to adjust depth + { // make drawable fit + Boolean fFound = false; + // see if we can just adjust the pixel depth + if ((pcontextInfo->pixelDepth > 16) && // if we are requesting 32 bit + (!pcontextInfo->fDepthMust) && // if we can adjust the pixel depth + (pcontextInfo->VRAM - pcontextInfo->textureRAM) > (pntFrontBuffer.h * pntFrontBuffer.v * frontBufferFactor / 2.0 + + pcontextInfo->width * pcontextInfo->height * (backBufferFactor - 2.0))) + { + fFound = true; + pcontextInfo->pixelDepth = 16; + } + else // pixel depth alone wont do it + { + i = (short) (indexFrontBuffer - 1); + while (i >= 0) + { + // + if ((pcontextInfo->VRAM - pcontextInfo->textureRAM) > (pResList [i].h * pResList [i].v * frontBufferFactor + + pResList [i].h * pResList [i].v * backBufferFactor)) + { + fFound = true; + pcontextInfo->width = pResList [i].h; + pcontextInfo->height = pResList [i].v; + pcontextInfo->freq = pFreqList [i] >> 16; + break; + } + else if ((pcontextInfo->pixelDepth > 16) && // if we are requesting 32 bit + (!pcontextInfo->fDepthMust) && // if we can adjust the pixel depth + (pcontextInfo->VRAM - pcontextInfo->textureRAM) > (pResList [i].h * pResList [i].v * frontBufferFactor / 2.0 + + pResList [i].h * pResList [i].v * (backBufferFactor - 2.0))) + { + fFound = true; + pcontextInfo->width = pResList [i].h; + pcontextInfo->height = pResList [i].v; + pcontextInfo->freq = pFreqList [i] >> 16; + pcontextInfo->pixelDepth = 16; + break; + } + i--; + } + // we tried the smallest screen size and still need to use less VRAM, adjust backbuffer to what is available + if ((!fFound) && (((pcontextInfo->VRAM - pcontextInfo->textureRAM) - pResList [0].h * pResList [0].v * frontBufferFactor) > 0)) + { + float factor; + fFound = true; + factor = (float) sqrt((float) (pcontextInfo->width * pcontextInfo->height * backBufferFactor) / + (float) ((pcontextInfo->VRAM - pcontextInfo->textureRAM) - pResList [0].h * pResList [0].v * frontBufferFactor)); + pcontextInfo->width /= factor; + pcontextInfo->height /= factor; + pcontextInfo->freq = pFreqList [0] >> 16; + } + } + if (!fFound) + { + // cannot accomdate request + ReportError ("Not enough total VRAM for drawable and textures"); + return err; + } + + } + } + return noErr; +} + +// -------------------------------------------------------------------------- + +// DoContextStepDown + +// steps down through frequencies, depths and sizes to try to find a valid context +// bounded by flags for SizeMust and DepthMust +// Note: may modify pcontextInfo + +Boolean DoContextStepDown (pstructGLInfo pcontextInfo, DSpContextAttributes * pContextAttributes, Point * pResList, SInt32 * pFreqList) +{ + // find current resolution + short i = 0; + while (((pResList [i].h <= pContextAttributes->displayWidth) || (pResList [i].v <= pContextAttributes->displayHeight)) && + ((pResList [i].h != 0) || (pResList [i].v != 0)) && + (i < kMaxNumRes)) + i++; + i--; // i points to index of current resolution + if (pcontextInfo->freq > 0) + { + // adjust index to (equal or less than) desired refresh rate + while (((pResList [i + 1].h <= pContextAttributes->displayWidth) || (pResList [i + 1].v <= pContextAttributes->displayHeight)) && + ((pResList [i + 1].h != 0) || (pResList [i + 1].v != 0)) && + (i + 1 < kMaxNumRes) && + (pFreqList[i + 1] >= pcontextInfo->freq << 16)) + { + i++; + } + pcontextInfo->freq = pFreqList [i] >> 16; + } + if (pcontextInfo->fSizeMust) // adjust depth only + { + if (pcontextInfo->pixelDepth > 16) // also try pixel depth step down + { + pContextAttributes->displayBestDepth = 16; + pContextAttributes->backBufferBestDepth = 16; + } + else + return false; // no more options to try + } + else if (pcontextInfo->fDepthMust) // adjust size only + { + if (i > 0) + { + while ((pResList [i].h == pContextAttributes->displayWidth) + && (pResList [i].v == pContextAttributes->displayHeight) + && i > 0) + { + i--; // i was pointing at current resolution, now it is pointing at new resolution to try + } + // set new resolution + pContextAttributes->displayWidth = pResList [i].h; + pContextAttributes->displayHeight = pResList [i].v; + // find refresh rate equal or smaller + while ((pResList [i - 1].h == pContextAttributes->displayWidth) + && (pResList [i - 1].v == pContextAttributes->displayHeight) + && i > 0 + && pFreqList[i] > pcontextInfo->freq << 16) + { + i--; + } + // set new refresh rate + pcontextInfo->freq = pFreqList [i] >> 16; + } + else + return false; + } + else // adjust size and depth + { + if (pContextAttributes->displayBestDepth > 16) + { + pContextAttributes->displayBestDepth = 16; + pContextAttributes->backBufferBestDepth = 16; + } + else if (i > 0) + { + while ((pResList [i].h == pContextAttributes->displayWidth) + && (pResList [i].v == pContextAttributes->displayHeight) + && i > 0) + { + i--; // i was pointing at current resolution, now it is pointing at new resolution to try + } + // set new resolution + pContextAttributes->displayWidth = pResList [i].h; + pContextAttributes->displayHeight = pResList [i].v; + // find refresh rate equal or smaller + while ((pResList [i - 1].h == pContextAttributes->displayWidth) + && (pResList [i - 1].v == pContextAttributes->displayHeight) + && i > 0 + && pFreqList[i] > pcontextInfo->freq << 16) + { + i--; + } + // set new refresh rate + pcontextInfo->freq = pFreqList [i] >> 16; + // reset pixel depth + pContextAttributes->displayBestDepth = pcontextInfo->pixelDepth; + pContextAttributes->backBufferBestDepth = pcontextInfo->pixelDepth; + } + else + return false; + + } + return true; +} + +#pragma mark - +// functions (public) ------------------------------------------------------- + +// GetDSpVersion + +// Gets the current version of DSp + +NumVersion GetDSpVersion (void) +{ + NumVersion versionDSp = { 0, 0, 0, 0 }; + OSStatus err = noErr; + if (!gDSpStarted) + err = StartDSp (); + if (noErr == err) + versionDSp = DSpGetVersion (); + return versionDSp; +} + +// -------------------------------------------------------------------------- + +// StartDSp + +// handles starting up DrawSprocket + +OSStatus StartDSp (void) +{ + OSStatus err = noErr; + if (!gDSpStarted) + { + // check for DSp + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpStartup) + { + ReportError ("DSp not installed"); + return kDSpNotInitializedErr; + } + else + { + err = DSpReportError (DSpStartup()); // start DSp + if (noErr != err) + return err; + else + gDSpStarted = true; + } + } + return err; +} + +// -------------------------------------------------------------------------- + +// ShutdownDSpContext + +// shuts down DrawSprocket + +void ShutdownDSp (void) +{ + if (gDSpStarted) + { + DSpShutdown (); + gDSpStarted = false; + } +} + +#pragma mark - +// -------------------------------------------------------------------------- + +// GetDSpDrawable + +// Just returns the front buffer + +// Inputs: *pdspContext +// pcontextInfo: request and requirements for cotext and drawable + +// Outputs: returns CGrafPtr thaat is front buffer of context + +// if error: will return NULL + +CGrafPtr GetDSpDrawable (DSpContextReference dspContext) +{ + CGrafPtr pCGraf = NULL; + if (noErr == DSpReportError (DSpContext_GetFrontBuffer (dspContext, &pCGraf))) + return pCGraf; + else + return NULL; +} + +// -------------------------------------------------------------------------- + +// BuildDSpContext + +// contextInfo and tries to allocate the corresponding DSp context + +// Inputs: hGD: GDHandle to device to look at +// pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *pdspContext as allocated +// pcontextInfo: allocated parameters + +// if fail to allocate: pdspContext will be NULL +// if error: will return error pdspContext will be NULL + +OSStatus BuildDSpContext (DSpContextReference* pdspContext, GDHandle hGD, GLint depthSizeSupport, pstructGLInfo pcontextInfo) +{ + DSpContextAttributes theContextAttributes, foundAttributes; + DSpContextReference * pContextRefUnused; + SInt32 aFreqList [kMaxNumRes]; + Point aResList [kMaxNumRes]; // list for resolution information + OSStatus err = noErr; + + *pdspContext = 0; + + // check for DSp + if (noErr != StartDSp ()) + { + ReportError ("DSp startup failed"); + return noErr; // already reported + } + + // reserve contexts on other screens to prevent their selection + pContextRefUnused = ReserveUnusedDevices (hGD); + + // build resolution list + BuildResolutionList (hGD, aResList, aFreqList); + + // handle default pixel depths + if (pcontextInfo->pixelDepth == 0) // default + { + pcontextInfo->pixelDepth = (**(**hGD).gdPMap).pixelSize; + if (pcontextInfo->pixelDepth < 16) + pcontextInfo->pixelDepth = 16; + } + +#ifdef kUseRAMCheck + if (noErr != DoDeviceRAMCheck (pcontextInfo, aResList, aFreqList, depthSizeSupport)) + return err; +#endif // kUseRAMCheck + + // Note: DSp < 1.7.3 REQUIRES the back buffer attributes even if only one buffer is required + BlockZero (&theContextAttributes, sizeof (DSpContextAttributes)); +// memset(&theContextAttributes, 0, sizeof (DSpContextAttributes)); + theContextAttributes.displayWidth = pcontextInfo->width; + theContextAttributes.displayHeight = pcontextInfo->height; + theContextAttributes.displayBestDepth = pcontextInfo->pixelDepth; + theContextAttributes.backBufferBestDepth = pcontextInfo->pixelDepth; + do + { + theContextAttributes.frequency = pcontextInfo->freq * 0x10000; + theContextAttributes.colorNeeds = kDSpColorNeeds_Require; + theContextAttributes.displayDepthMask = kDSpDepthMask_All; + theContextAttributes.backBufferDepthMask = kDSpDepthMask_All; + theContextAttributes.pageCount = 1; // only the front buffer is needed + err = DSpFindBestContext(&theContextAttributes, pdspContext); + if (noErr != err) // if we had any errors, reset for next try + if (!DoContextStepDown (pcontextInfo, &theContextAttributes, aResList, aFreqList)) + break; // have run out of options + } while (err == kDSpContextNotFoundErr); + + // check find best context errors + if (kDSpContextNotFoundErr == err) + { + *pdspContext = 0; + return noErr; + } + else if (noErr != err) + { + DSpReportError (err); + *pdspContext = 0; + return err; + } + + err = DSpReportError (DSpContext_GetAttributes (*pdspContext, &foundAttributes)); + if (noErr != err) + { + *pdspContext = 0; + return err; + } + // reset width and height to full screen and handle our own centering + // HWA will not correctly center less than full screen size contexts + theContextAttributes.displayWidth = foundAttributes.displayWidth; + theContextAttributes.displayHeight = foundAttributes.displayHeight; + theContextAttributes.pageCount = 1; // only the front buffer is needed + theContextAttributes.contextOptions = 0 | kDSpContextOption_DontSyncVBL; // no page flipping and no VBL sync needed + + err = DSpReportError (DSpContext_Reserve(*pdspContext, &theContextAttributes )); // reserve our context + if (noErr != err) + { + *pdspContext = 0; + return err; + } + if (gNeedFade == true) + { + DSpReportError (DSpContext_CustomFadeGammaOut (NULL, NULL, fadeTicks)); + gNeedFade = false; + } + err = DSpReportError (DSpContext_SetState (*pdspContext, kDSpContextState_Active)); // activate our context + if (noErr != err) + { + DSpContext_Release (*pdspContext); + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + *pdspContext = 0; + return err; + } + + FreeUnusedDevices (hGD, &pContextRefUnused); + + if (!pcontextInfo->fSizeMust) // if we got whatever was available + { + // reset inputs to what was allocated (constrain aspect ratio) + // unless we ask for smaller, then leave the same + if ((pcontextInfo->width > foundAttributes.displayWidth) || (pcontextInfo->height > foundAttributes.displayHeight)) + { + float hFactor = (float) pcontextInfo->width / (float) foundAttributes.displayWidth; + float vFactor = (float) pcontextInfo->height / (float) foundAttributes.displayHeight; + if (hFactor > vFactor) + { + pcontextInfo->width = (short) foundAttributes.displayWidth; + pcontextInfo->height /= hFactor; + } + else + { + pcontextInfo->height = (short) foundAttributes.displayHeight; + pcontextInfo->width /= vFactor; + } + } + } + // else still use inputs to allocate drawable + + pcontextInfo->freq = foundAttributes.frequency / 0x10000; + pcontextInfo->pixelDepth = foundAttributes.displayBestDepth; + + return noErr; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// Deactivates and dumps context + +void DestroyDSpContext (DSpContextReference* pdspContext) +{ + if (gDSpStarted) + { + if (*pdspContext) + { + DSpReportError (DSpContext_SetState(*pdspContext, kDSpContextState_Inactive)); + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + DSpReportError (DSpContext_Release (*pdspContext)); + *pdspContext = NULL; + } + } +} + + +#pragma mark - +//----------------------------------------------------------------------------------------------------------------------- + +OSStatus DSpContext_CustomFadeGammaIn (DSpContextReference inContext, const RGBColor *fadeColor, long fadeTicks) +{ + OSStatus err = noErr; +#ifndef kUseFades + #pragma unused (inContext, fadeColor, fadeTicks) +#else + RGBColor inZeroIntensityColor; + UInt32 currTick; + UInt16 step = (UInt16) (800 / fadeTicks); + long x, percent = 0; + + if (gDSpStarted) + { + if (fadeTicks == 0) + fadeTicks = 1; + if (fadeColor == NULL) + { + inZeroIntensityColor.red = 0x0000; + inZeroIntensityColor.green = 0x0000; + inZeroIntensityColor.blue = 0x0000; + } + else + inZeroIntensityColor = *fadeColor; + currTick = TickCount (); + for (x = 1; x <= fadeTicks; x++) + { + percent = step * x / 8; + err = DSpContext_FadeGamma(inContext, percent, &inZeroIntensityColor); + if (err != noErr) + break; + while (currTick >= TickCount ()) {} +// SystemTask (); + currTick = TickCount (); + } + if (err == noErr) + err = DSpContext_FadeGamma(inContext, 100, &inZeroIntensityColor); + } +#endif // kUseFades + return err; +} + +//----------------------------------------------------------------------------------------------------------------------- + +OSStatus DSpContext_CustomFadeGammaOut (DSpContextReference inContext, const RGBColor *fadeColor, long fadeTicks ) +{ + + OSStatus err = noErr; +#ifndef kUseFades + #pragma unused (inContext, fadeColor, fadeTicks) +#else + RGBColor inZeroIntensityColor; + UInt32 currTick; + UInt16 step = (UInt16) (800 / fadeTicks); + long x, percent = 0; + + if (gDSpStarted) + { + if (fadeTicks == 0) + fadeTicks = 1; // ensure we do not have zero fade time + if (fadeColor == NULL) + { + inZeroIntensityColor.red = 0x0000; + inZeroIntensityColor.green = 0x0000; + inZeroIntensityColor.blue = 0x0000; + } + else + inZeroIntensityColor = *fadeColor; + currTick = TickCount (); + for (x = fadeTicks - 1; x >= 0; x--) + { + percent = step * x / 8; + err = DSpContext_FadeGamma(inContext, percent, &inZeroIntensityColor); + if (err != noErr) + break; + while (currTick >= TickCount ()) {} +// SystemTask (); + currTick = TickCount (); + } + } +#endif // kUseFades + return err; +} \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Carbon_SetupDSp.h b/MacGLide/Mac/SetupGL/Carbon_SetupDSp.h new file mode 100755 index 0000000..2448060 --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_SetupDSp.h @@ -0,0 +1,110 @@ +/* + File: SetupDSp.h + + Contains: Functions to enable building and destorying a DSp fullscreen context + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <2> 3/26/01 ggs Add DSp version check and other items for full screen on X + <1> 1/19/01 ggs Initial re-add + <4> 1/26/00 ggs Add fade code back in, ensure NULL pointer/context checks are in + <3> 1/24/00 ggs Add C++ support + <2> 12/18/99 ggs Fix headers + <1> 11/28/99 ggs Initial add. Split of just DSp handling functions. Added total + device RAM checks, better step downs using actual supported + resolutions. Need to add user verify for contexts that require + it, integration of this in context step down, and a freq bit + field. + <1> 11/11/99 ggs Initial Add + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleŐs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +// Usage notes: + + + +// include control -------------------------------------------------- + +#ifndef SetupDSp_h +#define SetupDSp_h + + +// includes --------------------------------------------------------- + +#ifdef __APPLE_CC__ + #include +#else + #include +#endif + +#include "Carbon_SetupGL.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// structures (public) ----------------------------------------------- + +enum { fadeTicks = 10 }; + +// public function declarations ------------------------------------- + +NumVersion GetDSpVersion (void); +OSStatus StartDSp (void); +void ShutdownDSp (void); + +CGrafPtr GetDSpDrawable (DSpContextReference dspContext); +OSStatus BuildDSpContext (DSpContextReference* pdspContext, GDHandle hGD, GLint depthSizeSupport, pstructGLInfo pcontextInfo); +void DestroyDSpContext (DSpContextReference* pdspContext); + +OSStatus DSpContext_CustomFadeGammaOut (DSpContextReference inContext, const RGBColor *fadeColor, long fadeTicks); +OSStatus DSpContext_CustomFadeGammaIn (DSpContextReference inContext, const RGBColor *fadeColor, long fadeTicks); + +extern Boolean gDSpStarted; +extern Boolean gNeedFade; + +#ifdef __cplusplus +} +#endif + +#endif // SetupDSp_h \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Carbon_SetupGL.c b/MacGLide/Mac/SetupGL/Carbon_SetupGL.c new file mode 100755 index 0000000..a067da0 --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_SetupGL.c @@ -0,0 +1,1186 @@ +/* + File: Carbon SetupGL.c + + Contains: Functions to enable building and destorying a GL full screen or windowed context + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <4> 8/23/01 ggs Fixed texture sharing and added number of bug fixes + <3> 4/20/01 ggs Added support for texture sharing by sharing all contexts by default + <2> 3/26/01 ggs Add DSp version check and other items for full screen on X + <1> 1/19/01 ggs Initial re-add + <7> 3/22/00 ggs remove extranious prototype + <6> 3/21/00 ggs Added windowed mode and clean up various implementation details + <5> 1/26/00 ggs Add fade code back in, ensure NULL pointer/context/drawable + checks are in, add Preflight + <4> 1/24/00 ggs Added glFinish to shutdown code + <3> 1/24/00 ggs update to latest, better rendrere info handling for 3dfx, better + checks on pause and resume, added frin devce numer and gdhandle + from point + <2.7> 11/28/99 ggs Split out DSp and error handling. Added texture memory + considerations, assume VRAM is required if other than zero + <2.6> 11/14/99 ggs Fix source server copy + <2.5> 11/13/99 ggs fixed default pixel depth (0) condition that was causing failures + <2.4> 11/13/99 ggs added custom fade code + <2.3> 11/13/99 ggs Reset for Quake 3 use + <2.2> 11/12/99 ggs re-add + <2.1> 11/12/99 ggs added support for frequency retrieval, fixed display number + output to be correct if display number input was -1 + <2> 11/12/99 ggs 1.0 functionality + <1> 11/11/99 ggs Initial Add + + Disclaimer: You may incorporate this sample code into your applications without + restriction, though the sample code has been provided "AS IS" and the + responsibility for its operation is 100% yours. However, what you are + not permitted to do is to redistribute the source as "DSC Sample Code" + after having made changes. If you're going to re-distribute the source, + we require that you make it clear in the source that the code was + descended from Apple Sample Code, but that you've made changes. +*/ + +// system includes ---------------------------------------------------------- + +#ifdef __APPLE_CC__ + #include +#else + #include + #include +#endif + +// project includes --------------------------------------------------------- + +#include "Carbon_Error_Handler.h" +#include "Carbon_SetupDSp.h" +#include "Carbon_SetupGL.h" + + +// globals (internal/private) ----------------------------------------------- + +const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 }; + +const short kWindowType = kWindowDocumentProc; + +// prototypes (internal/private) -------------------------------------------- + +static Boolean CheckRenderer (GDHandle hGD, long *VRAM, long *textureRAM, GLint* , Boolean fAccelMust); +static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust); +static Boolean CheckWindowExtents (GDHandle hGD, short width, short height); +static void DumpCurrent (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, pstructGLInfo pcontextInfo); + +static OSStatus BuildGLContext (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, GDHandle hGD, + pstructGLInfo pcontextInfo, AGLContext aglShareContext); +static OSStatus BuildDrawable (AGLDrawable* paglDraw, GDHandle hGD, pstructGLInfo pcontextInfo); +static OSStatus BuildGLonDevice (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, + GDHandle hGD, pstructGLInfo pcontextInfo, AGLContext aglShareContext); +static OSStatus BuildGLonWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext); + + +// functions (internal/private) --------------------------------------------- + +// CheckRenderer + +// looks at renderer attributes it has at least the VRAM is accelerated + +// Inputs: hGD: GDHandle to device to look at +// pVRAM: pointer to VRAM in bytes required; out is actual VRAM if a renderer was found, otherwise it is the input parameter +// pTextureRAM: pointer to texture RAM in bytes required; out is same (implementation assume VRAM returned by card is total so we add texture and VRAM) +// fAccelMust: do we check for acceleration + +// Returns: true if renderer for the requested device complies, false otherwise + +static Boolean CheckRenderer (GDHandle hGD, long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust) +{ + AGLRendererInfo info, head_info; + GLint inum; + GLint dAccel = 0; + GLint dVRAM = 0, dMaxVRAM = 0; + Boolean canAccel = false, found = false; + head_info = aglQueryRendererInfo(&hGD, 1); + aglReportError (); + if(!head_info) + { + ReportError ("aglQueryRendererInfo error"); + return false; + } + else + { + info = head_info; + inum = 0; + // see if we have an accelerated renderer, if so ignore non-accelerated ones + // this prevents returning info on software renderer when actually we'll get the hardware one + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + if (dAccel) + canAccel = true; + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + + info = head_info; + inum = 0; + while (info) + { + aglDescribeRenderer (info, AGL_ACCELERATED, &dAccel); + aglReportError (); + // if we can accel then we will choose the accelerated renderer + // how about compliant renderers??? + if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel))) + { + aglDescribeRenderer (info, AGL_VIDEO_MEMORY, &dVRAM); // we assume that VRAM returned is total thus add texture and VRAM required + aglReportError (); + if (dVRAM >= (*pVRAM + *pTextureRAM)) + { + if (dVRAM >= dMaxVRAM) // find card with max VRAM + { + aglDescribeRenderer (info, AGL_DEPTH_MODES, pDepthSizeSupport); // which depth buffer modes are supported + aglReportError (); + dMaxVRAM = dVRAM; // store max + found = true; + } + } + } + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + } + aglDestroyRendererInfo(head_info); + if (found) // if we found a card that has enough VRAM and meets the accel criteria + { + *pVRAM = dMaxVRAM; // return VRAM + return true; + } + // VRAM will remain to same as it did when sent in + return false; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// CheckAllDeviceRenderers + +// looks at renderer attributes and each device must have at least one renderer that fits the profile + +// Inputs: pVRAM: pointer to VRAM in bytes required; out is actual min VRAM of all renderers found, otherwise it is the input parameter +// pTextureRAM: pointer to texture RAM in bytes required; out is same (implementation assume VRAM returned by card is total so we add texture and VRAM) +// fAccelMust: do we check fro acceleration + +// Returns: true if any renderer for on each device complies (not necessarily the same renderer), false otherwise + +static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust) +{ + AGLRendererInfo info, head_info; + GLint inum; + GLint dAccel = 0; + GLint dVRAM = 0, dMaxVRAM = 0; + Boolean canAccel = false, found = false, goodCheck = true; // can the renderer accelerate, did we find a valid renderer for the device, are we still successfully on all the devices looked at + long MinVRAM = 0x8FFFFFFF; // max long + GDHandle hGD = GetDeviceList (); // get the first screen + while (hGD && goodCheck) + { + head_info = aglQueryRendererInfo(&hGD, 1); + aglReportError (); + if(!head_info) + { + ReportError ("aglQueryRendererInfo error"); + return false; + } + else + { + info = head_info; + inum = 0; + // see if we have an accelerated renderer, if so ignore non-accelerated ones + // this prevents returning info on software renderer when actually we'll get the hardware one + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + if (dAccel) + canAccel = true; + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + + info = head_info; + inum = 0; + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + // if we can accel then we will choose the accelerated renderer + // how about compliant renderers??? + if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel))) + { + aglDescribeRenderer(info, AGL_VIDEO_MEMORY, &dVRAM); // we assume that VRAM returned is total thus add texture and VRAM required + aglReportError (); + if (dVRAM >= (*pVRAM + *pTextureRAM)) + { + if (dVRAM >= dMaxVRAM) // find card with max VRAM + { + aglDescribeRenderer(info, AGL_DEPTH_MODES, pDepthSizeSupport); // which depth buffer modes are supported + aglReportError (); + dMaxVRAM = dVRAM; // store max + found = true; + } + } + } + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + } + aglDestroyRendererInfo(head_info); + if (found) // if we found a card that has enough VRAM and meets the accel criteria + { + if (MinVRAM > dMaxVRAM) + MinVRAM = dMaxVRAM; // return VRAM + + } + else + goodCheck = false; // one device failed thus entire requirement fails + hGD = GetNextDevice (hGD); // get next device + } // while + if (goodCheck) // we check all devices and each was good + { + *pVRAM = MinVRAM; // return VRAM + return true; + } + return false; //at least one device failed to have mins +} + +//----------------------------------------------------------------------------------------------------------------------- + +// CheckWindowExtents + +// checks to see window fits on screen completely + +// Inputs: hGD: GDHandle to device to look at +// width/height: requested width and height of window + +// Returns: true if window and borders fit, false otherwise + +static Boolean CheckWindowExtents (GDHandle hGD, short width, short height) +{ + Rect strucRect, rectWin = {0, 0, 1, 1}; + short deviceHeight = (short) ((**hGD).gdRect.bottom - (**hGD).gdRect.top - GetMBarHeight ()); + short deviceWidth = (short) ((**hGD).gdRect.right - (**hGD).gdRect.left); + short windowWidthExtra, windowHeightExtra; + // build window (not visible) + WindowPtr pWindow = NewCWindow (NULL, &rectWin, "\p", true, kWindowType, (WindowPtr)-1, 0, 0); + +#if !TARGET_API_MAC_CARBON + strucRect = (**(((WindowPeek)pWindow)->strucRgn)).rgnBBox; +#else + GetWindowBounds (pWindow, kWindowStructureRgn, &strucRect); +#endif + windowWidthExtra = (short) ((strucRect.right - strucRect.left) - 1); + windowHeightExtra = (short) ((strucRect.bottom - strucRect.top) - 1); + DisposeWindow (pWindow); + if ((width + windowWidthExtra <= deviceWidth) && + (height + windowHeightExtra <= deviceHeight)) + return true; + return false; +} + +// -------------------------------------------------------------------------- + +// DumpCurrent + +// Kills currently allocated context +// does not care about being pretty (assumes display is likely faded) + +// Inputs: paglDraw, paglContext, pdspContext: things to be destroyed + +void DumpCurrent (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, pstructGLInfo pcontextInfo) +{ + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaOut (NULL, NULL, fadeTicks)); + + if (*paglContext) + { + aglSetCurrentContext (NULL); + aglReportError (); + aglSetDrawable (*paglContext, NULL); + aglReportError (); + aglDestroyContext (*paglContext); + aglReportError (); + *paglContext = NULL; + } + + if (pcontextInfo->fmt) + { + aglDestroyPixelFormat (pcontextInfo->fmt); // pixel format is no longer needed + aglReportError (); + } + pcontextInfo->fmt = 0; + + if (*paglDraw && !(pcontextInfo->fFullscreen && CheckMacOSX ())) // do not destory a window on DSp if in Mac OS X + // since there is no window built in X +#if TARGET_API_MAC_CARBON + DisposeWindow (GetWindowFromPort (*paglDraw)); +#else + DisposeWindow ((WindowPtr) *paglDraw); +#endif + *paglDraw = NULL; + DestroyDSpContext (pdspContext); // fades in, safe to call at all times +} + +#pragma mark - +// -------------------------------------------------------------------------- + +// BuildGLContext + +// Builds OpenGL context + +// Inputs: hGD: GDHandle to device to look at +// pcontextInfo: request and requirements for cotext and drawable + +// Outputs: paglContext as allocated +// pcontextInfo: allocated parameters + +// if fail to allocate: paglContext will be NULL +// if error: will return error paglContext will be NULL + +static OSStatus BuildGLContext (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, + GDHandle hGD, pstructGLInfo pcontextInfo, AGLContext aglShareContext) +{ + OSStatus err = noErr; + NumVersion versionDSp = GetDSpVersion (); + + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL + { + ReportError ("OpenGL not installed"); + return noErr; + } + + // DSp has problems on Mac OS X with DSp version less than 1.99 so use agl full screen + if ((pcontextInfo->fFullscreen) && (CheckMacOSX ()) && ((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev < 0x99))) // need to set pixel format for full screen + { + short i = 0; + while (pcontextInfo->aglAttributes[i++] != AGL_NONE) {} + i--; // point to AGL_NONE + pcontextInfo->aglAttributes [i++] = AGL_FULLSCREEN; + pcontextInfo->aglAttributes [i++] = AGL_PIXEL_SIZE; + pcontextInfo->aglAttributes [i++] = (SInt32) pcontextInfo->pixelDepth; + pcontextInfo->aglAttributes [i++] = AGL_NONE; + } + + pcontextInfo->fmt = aglChoosePixelFormat (&hGD, 1, pcontextInfo->aglAttributes); // get an appropriate pixel format + aglReportError (); + if (NULL == pcontextInfo->fmt) + { + ReportError("Could not find valid pixel format"); + return noErr; + } + + // using a default method of sharing all the contexts enables texture sharing across these contexts by default + *paglContext = aglCreateContext (pcontextInfo->fmt, aglShareContext); // Create an AGL context + if (AGL_BAD_MATCH == aglGetError()) + *paglContext = aglCreateContext (pcontextInfo->fmt, 0); // unable to sahre context, create without sharing + aglReportError (); + if (NULL == *paglContext) + { + ReportError ("Could not create context"); + return paramErr; + } + if (aglShareContext == NULL) + aglShareContext = *paglContext; + + // set our drawable + + // DSp has problems on Mac OS X use DSp only when version is not less than 1.99 + if ((pcontextInfo->fFullscreen) && (CheckMacOSX ()) && !((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev < 0x99))) // fullscreen X late DSp + { + // use DSp's front buffer on Mac OS X + *paglDraw = GetDSpDrawable (*pdspContext); + // there is a problem in Mac OS X GM CoreGraphics that may not size the port pixmap correctly + // this will check the vertical sizes and offset if required to fix the problem + // this will not center ports that are smaller then a particular resolution + { + short deltaV, deltaH; + Rect portBounds; +#if TARGET_API_MAC_CARBON + PixMapHandle hPix = GetPortPixMap (*paglDraw); + Rect pixBounds = (**hPix).bounds; + GetPortBounds (*paglDraw, &portBounds); +#else + PixMapHandle hPix = (*paglDraw)->portPixMap; + Rect pixBounds = (**hPix).bounds; + portBounds = (*paglDraw)->portRect; +#endif + deltaV = (short) ((portBounds.bottom - portBounds.top) - (pixBounds.bottom - pixBounds.top) + + (portBounds.bottom - portBounds.top - pcontextInfo->height) / 2); + deltaH = (short) (-(portBounds.right - portBounds.left - pcontextInfo->width) / 2); + if (deltaV || deltaH) + { + GrafPtr pPortSave; + GetPort (&pPortSave); + SetPort ((GrafPtr)*paglDraw); + // set origin to account for CG offset and if requested drawable smaller than screen rez + SetOrigin (deltaH, deltaV); + SetPort (pPortSave); + } + } + if (!aglSetDrawable (*paglContext, *paglDraw)) // attach the CGrafPtr to the context + return aglReportError (); + } + // DSp has problems on Mac OS X with DSp version less than 1.99 so use agl full screen + else if ((pcontextInfo->fFullscreen) && (CheckMacOSX ()) && ((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev < 0x99))) // fulscreen X early DSp + { + // use aglFullScreen + short display = 0; + if (!aglSetFullScreen (*paglContext, pcontextInfo->width, pcontextInfo->height, 60, display)) // attach fulls screen device to the context + { + ReportError ("SetFullScreen failed"); + aglReportError (); + return paramErr; + } + } + else // not Mac OS X fullscreen: this is for three cases 1) Mac OS 9 windowed 2) Mac OS X windowed 3) Mac OS 9 fullscreen (as you need to build a window on top of DSp for GL to work correctly + { + // build window as late as possible + err = BuildDrawable (paglDraw, hGD, pcontextInfo); + if (err != noErr) + { + ReportError ("Could not build drawable"); + return err; + } + if (!aglSetDrawable (*paglContext, *paglDraw)) // attach the CGrafPtr to the context + return aglReportError (); + } + if(!aglSetCurrentContext (*paglContext)) // make the context the current context + return aglReportError (); + + return err; +} + +// -------------------------------------------------------------------------- + +// BuildDrawable + +// Builds window to be used as drawable + +// Inputs: hGD: GDHandle to device to look at +// pcontextInfo: request and requirements for cotext and drawable + +// Outputs: paglDraw as allocated +// pcontextInfo: allocated parameters + +// if fail to allocate: paglDraw will be NULL +// if error: will return error paglDraw will be NULL + +static OSStatus BuildDrawable (AGLDrawable* paglDraw, GDHandle hGD, pstructGLInfo pcontextInfo) +{ + Rect rectWin; + RGBColor rgbSave; + GrafPtr pGrafSave; + OSStatus err = noErr; + + // center window in our context's gdevice + rectWin.top = (short) ((**hGD).gdRect.top + ((**hGD).gdRect.bottom - (**hGD).gdRect.top) / 2); // v center + rectWin.top -= pcontextInfo->height / 2; + rectWin.left = (short) ((**hGD).gdRect.left + ((**hGD).gdRect.right - (**hGD).gdRect.left) / 2); // h center + rectWin.left -= pcontextInfo->width / 2; + rectWin.right = (short) (rectWin.left + pcontextInfo->width); + rectWin.bottom = (short) (rectWin.top + pcontextInfo->height); + + +#if TARGET_API_MAC_CARBON + if (pcontextInfo->fFullscreen) + *paglDraw = GetWindowPort (NewCWindow (NULL, &rectWin, "\p", 0, plainDBox, (WindowPtr)-1, 0, 0)); + else + *paglDraw = GetWindowPort (NewCWindow (NULL, &rectWin, "\p", 0, kWindowType, (WindowPtr)-1, 0, 0)); + ShowWindow (GetWindowFromPort (*paglDraw)); +#else + if (pcontextInfo->fFullscreen) + *paglDraw = (AGLDrawable) NewCWindow (NULL, &rectWin, "\p", 0, plainDBox, (WindowPtr)-1, 0, 0); + else + *paglDraw = (AGLDrawable) NewCWindow (NULL, &rectWin, "\p", 0, kWindowType, (WindowPtr)-1, 0, 0); + ShowWindow ((WindowPtr) *paglDraw); +#endif + GetPort (&pGrafSave); + SetPort ((GrafPtr)*paglDraw); + GetForeColor (&rgbSave); + RGBForeColor (&rgbBlack); +#if TARGET_API_MAC_CARBON + GetWindowBounds (GetWindowFromPort (*paglDraw), kWindowContentRgn, &rectWin); +#else + rectWin = ((GrafPtr) *paglDraw)->portRect; +#endif + PaintRect (&rectWin); + RGBForeColor (&rgbSave); // ensure color is reset for proper blitting + SetPort (pGrafSave); + return err; +} + +// -------------------------------------------------------------------------- + +// BuildGLonDevice + +// Takes device single device and tries to build on it + +// Inputs: hGD: GDHandle to device to look at +// *pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *paglDraw, *paglContext and *pdspContext as allocated +// *pcontextInfo: allocated parameters + +// if fail to allocate: paglDraw, paglContext and pdspContext will be NULL +// if error: will return error and paglDraw, paglContext and pdspContext will be NULL +// Note: *paglDraw and *pdspContext can be null is aglFullScreen is used + +static OSStatus BuildGLonDevice (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, + GDHandle hGD, pstructGLInfo pcontextInfo, AGLContext aglShareContext) +{ + GLint depthSizeSupport; + OSStatus err = noErr; + Boolean fCheckRenderer = false; + NumVersion versionDSp = GetDSpVersion (); + + if (pcontextInfo->fFullscreen) + { + // if we are in 16 or 32 bit mode already, we can check the renderer now (we will double check later) + if (16 <= (**(**hGD).gdPMap).pixelSize) + { + // check for VRAM and accelerated + if (!CheckRenderer (hGD, &(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust)) + { + ReportError ("Renderer check failed"); + return err; + } + else + fCheckRenderer = true; + } + + // only for Mac OS 9 or less and greater than Mac OS X 10.0.2 + // DSp has problems on Mac OS X with DSp version less than 1.99 (10.0.2 or less) + if ((!CheckMacOSX ()) || ((versionDSp.majorRev > 0x01) || ((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev >= 0x99)))) // DSp should be supported in version after 1.98 + { + err = BuildDSpContext (pdspContext, hGD, depthSizeSupport, pcontextInfo); + // we are now faded + if ((err != noErr) || (*pdspContext == NULL)) + { + if (err != noErr) + ReportErrorNum ("BuildDSpContext failed with error:", err); + else + ReportError ("Could not build DrawSprocket context"); + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + return err; + } + } + // else we are using aglFullScreen and no DSp work is required + } + else + { + if (pcontextInfo->pixelDepth == 0) // default + { + pcontextInfo->pixelDepth = (**(**hGD).gdPMap).pixelSize; + if (16 > pcontextInfo->pixelDepth) + pcontextInfo->pixelDepth = 16; + } + if (pcontextInfo->fDepthMust && (pcontextInfo->pixelDepth != (**(**hGD).gdPMap).pixelSize)) // device depth must match and does not + { + ReportError ("Pixel Depth does not match device in windowed mode."); + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + return err; + } + // copy back the curretn depth + pcontextInfo->pixelDepth = (**(**hGD).gdPMap).pixelSize; + if (!CheckWindowExtents (hGD, pcontextInfo->width, pcontextInfo->height)) + { + ReportError ("Window will not fit on device in windowed mode."); + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + return err; + } + } + + // if we have not already checked the renderer, check for VRAM and accelerated + if (!fCheckRenderer) + if (!CheckRenderer (hGD, &(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust)) + { + ReportError ("Renderer check failed"); + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + return err; + } + + // do agl + // need to send device #'s through this + err = BuildGLContext (paglDraw, paglContext, pdspContext, hGD, pcontextInfo, aglShareContext); + + // DSp has problems on Mac OS X with DSp version less than 1.99 + if ((!CheckMacOSX ()) || ((versionDSp.majorRev > 0x01) || ((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev >= 0x99))))// DSp should be supported in version after 1.98 + { + if (*pdspContext) + DSpReportError (DSpContext_CustomFadeGammaIn (NULL, NULL, fadeTicks)); + } + return err; +} + + +// -------------------------------------------------------------------------- + +// BuildGLonDrawable + +// Takes a drawable and tries to build on it + +// Inputs: aglDraw: a valid AGLDrawable +// *pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *paglContext as allocated +// *pcontextInfo: allocated parameters + +// if fail to allocate: paglContext will be NULL +// if error: will return error and paglContext will be NULL + +static OSStatus BuildGLonWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext) +{ + GDHandle hGD = NULL; + GrafPtr cgrafSave = NULL; + short numDevices; + GLint depthSizeSupport; + OSStatus err = noErr; + + if (!pWindow || !pcontextInfo) + { + ReportError ("NULL parameter passed to BuildGLonDrawable."); + return paramErr; + } + + GetPort (&cgrafSave); + SetPortWindowPort(pWindow); + + // check renderere VRAM and acceleration + numDevices = FindGDHandleFromWindow (pWindow, &hGD); + if (!pcontextInfo->fDraggable) // if numDevices > 1 then we will only be using the software renderer otherwise check only window device + { + if ((numDevices > 1) || (numDevices == 0)) // this window spans mulitple devices thus will be software only + { + // software renderer + // infinite VRAM, infinite textureRAM, not accelerated + if (pcontextInfo->fAcceleratedMust) + { + ReportError ("Unable to accelerate window that spans multiple devices"); + return err; + } + } + else // not draggable on single device + { + if (!CheckRenderer (hGD, &(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust)) + { + ReportError ("Renderer check failed"); + return err; + } + } + } + // else draggable so must check all for support (each device should have at least one renderer that meets the requirements) + else if (!CheckAllDeviceRenderers (&(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust)) + { + ReportError ("Renderer check failed"); + return err; + } + + // do agl + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL + { + ReportError ("OpenGL not installed"); + return NULL; + } + // we successfully passed the renderer check + + if ((!pcontextInfo->fDraggable && (numDevices == 1))) // not draggable on a single device + pcontextInfo->fmt = aglChoosePixelFormat (&hGD, 1, pcontextInfo->aglAttributes); // get an appropriate pixel format + else + pcontextInfo->fmt = aglChoosePixelFormat (NULL, 0, pcontextInfo->aglAttributes); // get an appropriate pixel format + aglReportError (); + if (NULL == pcontextInfo->fmt) + { + ReportError("Could not find valid pixel format"); + return NULL; + } + + *paglContext = aglCreateContext (pcontextInfo->fmt, aglShareContext); // Create an AGL context + if (AGL_BAD_MATCH == aglGetError()) + *paglContext = aglCreateContext (pcontextInfo->fmt, 0); // unable to sahre context, create without sharing + aglReportError (); + if (NULL == *paglContext) + { + ReportError ("Could not create context"); + return NULL; + } + + if (!aglSetDrawable (*paglContext, GetWindowPort (pWindow))) // attach the CGrafPtr to the context + return aglReportError (); + + if(!aglSetCurrentContext (*paglContext)) // make the context the current context + return aglReportError (); + + SetPort (cgrafSave); + + return err; +} + +#pragma mark - + +// functions (public) ------------------------------------------------------- + +// CheckMacOSX + +// Runtime check to see if we are running on Mac OS X + +// Inputs: None + +// Returns: 0 if < Mac OS X or version number of Mac OS X (10.0 for GM) + +UInt32 CheckMacOSX (void) +{ + UInt32 response; + + if ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x01000)) + return response; + else + return 0; +} + +// -------------------------------------------------------------------------- + +// PreflightGL + +// Checks for presense of OpenGL and DSp (if required) +// Inputs: checkFullscreen: true if one wants to run fullscreen (which requires DrwSprocket currently) +// Ouputs: true if OpenGL is installed (and DrawSprocket if checkFullscreen is true + +Boolean PreflightGL (Boolean checkFullscreen) +{ + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL + return false; + if (checkFullscreen && ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpStartup)) // check for existance of DSp + return false; + return true; +} + +// -------------------------------------------------------------------------- + +// BuildGL + +// Takes device and geometry request and tries to build best context and drawable +// if device does not work will walk down devices looking for first one that satisfies requirments + +// Inputs: *pnumDevice: 0 any device, # attempt that device first, then any device +// *pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *paglDraw, *paglContext and *pdspContext as allocated +// *pnumDevice to device number in list that was used +// *pcontextInfo: allocated parameters + +// if fail to allocate: paglDraw, paglContext and pdspContext will be NULL +// if error: will return error and paglDraw, paglContext and pdspContext will be NULL + +OSStatus BuildGL (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, + short* pnumDevice, pstructGLInfo pcontextInfo, AGLContext aglShareContext) +{ + OSStatus err = noErr; + GDHandle hGD = NULL; + structGLInfo contextInfoSave; + + // clear + *paglDraw = NULL; + *paglContext = 0; + *pdspContext = 0; + contextInfoSave = *pcontextInfo; // save info to reset on failures + + // if we are full screen and not on Mac OS X (which will use aglFullScreen) + if (pcontextInfo->fFullscreen) + { + NumVersion versionDSp = GetDSpVersion (); + // DSp has problems on Mac OS X with DSp version less than 1.99 + if ((!CheckMacOSX ()) || ((versionDSp.majorRev > 0x01) || ((versionDSp.majorRev == 0x01) && (versionDSp.minorAndBugRev >= 0x99))))// DSp should be supported in version after 1.98 + { + err = StartDSp (); + if (gDSpStarted) + gNeedFade = true; + else + return err; + } + } + + + //find main device + if (*pnumDevice == -1) + { + GDHandle hDevice; // check number of screens + hGD = GetMainDevice (); + if (NULL != hGD) + { + err = BuildGLonDevice (paglDraw, paglContext, pdspContext, hGD, pcontextInfo, aglShareContext); + // find device number + *pnumDevice = 0; + hDevice = DMGetFirstScreenDevice (true); + do + { + if (hDevice == hGD) + break; + hDevice = DMGetNextScreenDevice (hDevice, true); + (*pnumDevice)++; + } + while (hDevice); + if (!hDevice) + ReportError ("main device match not found"); + } + else + ReportError ("Cannot get main device"); + } + + if ((err != noErr) || (*paglContext == 0)) + { + err = noErr; + DumpCurrent (paglDraw, paglContext, pdspContext, pcontextInfo); // dump what ever partial solution we might have + *pcontextInfo = contextInfoSave; // restore info + //find target device and check this first is one exists + if (*pnumDevice) + { + short i; + hGD = DMGetFirstScreenDevice (true); + for (i = 0; i < *pnumDevice; i++) + { + GDHandle hGDNext = DMGetNextScreenDevice (hGD, true); + if (NULL == hGDNext) // ensure we did not run out of devices + break; // if no more devices drop out + else + hGD = hGDNext; // otherwise continue + } + *pnumDevice = i; // record device we actually got + err = BuildGLonDevice (paglDraw, paglContext, pdspContext, hGD, pcontextInfo, aglShareContext); + } + } + + // while we have not allocated a context or there were errors + if ((err != noErr) || (*paglContext == 0)) + { + err = noErr; + DumpCurrent (paglDraw, paglContext, pdspContext, pcontextInfo); // dump what ever partial solution we might have + *pcontextInfo = contextInfoSave; // restore info + // now look through the devices in order + hGD = DMGetFirstScreenDevice (true); + *pnumDevice = -1; + do + { + (*pnumDevice)++; + err = BuildGLonDevice (paglDraw, paglContext, pdspContext, hGD, pcontextInfo, aglShareContext); + if ((err != noErr) || (*paglDraw == NULL) || (*paglContext == 0)) // reset hGD only if we are not done + { + hGD = DMGetNextScreenDevice (hGD, true); + DumpCurrent (paglDraw, paglContext, pdspContext, pcontextInfo); // dump what ever partial solution we might have + *pcontextInfo = contextInfoSave; // restore info + } + } + while (((err != noErr) || (*paglContext == 0)) && hGD); + } + return err; +} + +// -------------------------------------------------------------------------- + +// DestroyGL + +// Destroys drawable and context +// Ouputs: *paglDraw, *paglContext and *pdspContext should be 0 on exit + +OSStatus DestroyGL (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, pstructGLInfo pcontextInfo) +{ + if ((!paglContext) || (!*paglContext)) + return paramErr; // not a valid context + glFinish (); + DumpCurrent (paglDraw, paglContext, pdspContext, pcontextInfo); + ShutdownDSp (); // safe to call anytime + return noErr; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// BuildGLFromWindow + +// Takes window in the form of an AGLDrawable and geometry request and tries to build best context + +// Inputs: aglDraw: a valid AGLDrawable (i.e., a WindowPtr) +// *pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *paglContext as allocated +// *pcontextInfo: allocated parameters + +// if fail to allocate: paglContext will be NULL +// if error: will return error and paglContext will be NULL + +OSStatus BuildGLFromWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext) +{ + if (!pWindow) + return paramErr; + return BuildGLonWindow (pWindow, paglContext, pcontextInfo, aglShareContext); +} + +// -------------------------------------------------------------------------- + +// DestroyGLFromWindow + +// Destroys context that waas allocated with BuildGLFromWindow +// Ouputs: *paglContext should be NULL on exit + +OSStatus DestroyGLFromWindow (AGLContext* paglContext, pstructGLWindowInfo pcontextInfo) +{ + OSStatus err; + + if ((!paglContext) || (!*paglContext)) + return paramErr; // not a valid context + glFinish (); + aglSetCurrentContext (NULL); + err = aglReportError (); + aglSetDrawable (*paglContext, NULL); + err = aglReportError (); + aglDestroyContext (*paglContext); + err = aglReportError (); + *paglContext = NULL; + + if (pcontextInfo->fmt) + { + aglDestroyPixelFormat (pcontextInfo->fmt); // pixel format is no longer valid + err = aglReportError (); + } + pcontextInfo->fmt = 0; + + return err; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// SuspendFullScreenGL + +// Special suspend function to ensure the the GL window is hidden + +// needs to be reviewed + +OSStatus SuspendFullScreenGL (AGLDrawable aglDraw, AGLContext aglContext) +{ + if (aglDraw && aglContext) // will only have a drawable + { + glFinish (); // must do this to ensure the queue is complete + aglSetCurrentContext (NULL); +#if TARGET_API_MAC_CARBON + HideWindow (GetWindowFromPort (aglDraw)); +#else + HideWindow ((WindowPtr) aglDraw); +#endif + return aglReportError (); + } + return noErr; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// ResumeFullScreenGL + +// Needs a special resume function to ensure the the GL window is shown + +// needs to be reviewed + +OSStatus ResumeFullScreenGL (AGLDrawable aglDraw, AGLContext aglContext) +{ + if (aglDraw && aglContext) + { +#if TARGET_API_MAC_CARBON + ShowWindow (GetWindowFromPort (aglDraw)); +#else + ShowWindow ((WindowPtr) aglDraw); +#endif + aglSetCurrentContext (aglContext); + aglUpdateContext (aglContext); + return aglReportError (); + } + return paramErr; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// PauseGL + +// Pauses gl to allow toolbox drawing + +OSStatus PauseGL (AGLContext aglContext) +{ + if (aglContext) + { + glFinish (); // must do this to ensure the queue is complete + aglSetCurrentContext (NULL); + return aglReportError (); + } + return paramErr; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// ResumeGL + +// resumes gl to allow gl drawing + +OSStatus ResumeGL (AGLContext aglContext) +{ + if (aglContext) + { + aglSetCurrentContext (aglContext); + aglUpdateContext (aglContext); + return aglReportError (); + } + return paramErr; +} + +// -------------------------------------------------------------------------- + +// FindGDHandleFromRect + +// Inputs: a global Rect + +// Outputs: the GDHandle that that Rect is mostly on + +// returns the number of devices that the Rect touches +short FindGDHandleFromRect (Rect * pRect, GDHandle * phgdOnThisDevice) +{ + Rect rectSect; + long greatestArea, sectArea; + short numDevices = 0; + GDHandle hgdNthDevice; + + if (!phgdOnThisDevice) + return NULL; + + *phgdOnThisDevice = NULL; + + hgdNthDevice = GetDeviceList (); + greatestArea = 0; + // check window against all gdRects in gDevice list and remember + // which gdRect contains largest area of window} + while (hgdNthDevice) + { + if (TestDeviceAttribute (hgdNthDevice, screenDevice)) + if (TestDeviceAttribute (hgdNthDevice, screenActive)) + { + // The SectRect routine calculates the intersection + // of the window rectangle and this gDevice + // rectangle and returns TRUE if the rectangles intersect, + // FALSE if they don't. + SectRect (pRect, &(**hgdNthDevice).gdRect, &rectSect); + // determine which screen holds greatest window area + // first, calculate area of rectangle on current device + sectArea = (long) (rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top); + if (sectArea > 0) + numDevices++; + if (sectArea > greatestArea) + { + greatestArea = sectArea; // set greatest area so far + *phgdOnThisDevice = hgdNthDevice; // set zoom device + } + hgdNthDevice = GetNextDevice(hgdNthDevice); + } + } + return numDevices; +} + +// -------------------------------------------------------------------------- + +// GetWindowDevice + +// Inputs: a valid WindowPtr + +// Outputs: the GDHandle that that window is mostly on + +// returns the number of devices that the windows content touches + +short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice) +{ + GrafPtr pgpSave; + Rect rectWind, rectSect; + long greatestArea, sectArea; + short numDevices = 0; + GDHandle hgdNthDevice; + + if (!pWindow || !phgdOnThisDevice) + return NULL; + + *phgdOnThisDevice = NULL; + + GetPort (&pgpSave); + SetPortWindowPort (pWindow); + + +#if TARGET_API_MAC_CARBON + GetWindowPortBounds (pWindow, &rectWind); +#else + rectWind = pWindow->portRect; +#endif // TARGET_API_MAC_CARBON + LocalToGlobal ((Point*)& rectWind.top); // convert to global coordinates + LocalToGlobal ((Point*)& rectWind.bottom); + hgdNthDevice = GetDeviceList (); + greatestArea = 0; + // check window against all gdRects in gDevice list and remember + // which gdRect contains largest area of window} + while (hgdNthDevice) + { + if (TestDeviceAttribute (hgdNthDevice, screenDevice)) + if (TestDeviceAttribute (hgdNthDevice, screenActive)) + { + // The SectRect routine calculates the intersection + // of the window rectangle and this gDevice + // rectangle and returns TRUE if the rectangles intersect, + // FALSE if they don't. + SectRect (&rectWind, &(**hgdNthDevice).gdRect, &rectSect); + // determine which screen holds greatest window area + // first, calculate area of rectangle on current device + sectArea = (long) (rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top); + if (sectArea > 0) + numDevices++; + if (sectArea > greatestArea) + { + greatestArea = sectArea; // set greatest area so far + *phgdOnThisDevice = hgdNthDevice; // set zoom device + } + hgdNthDevice = GetNextDevice(hgdNthDevice); + } + } + + SetPort (pgpSave); + return numDevices; +} + +//----------------------------------------------------------------------------------------------------------------------- + +// FindDeviceNumFromRect + +// returns the number of the device that the point is on (i.e., where it is in the search order) +// just a ultility to find the number of the device from a point + +short FindDeviceNumFromRect (Rect * pRect) +{ + short displayNum = 0; + GDHandle hgdNthDevice, hgdFoundDevice; + + FindGDHandleFromRect (pRect, &hgdFoundDevice); + + hgdNthDevice = DMGetFirstScreenDevice (true); + while (hgdNthDevice) + { + if (hgdFoundDevice == hgdNthDevice) + break; + hgdNthDevice = DMGetNextScreenDevice(hgdNthDevice, true); + displayNum++; + } // of WHILE + + return displayNum; +} \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Carbon_SetupGL.h b/MacGLide/Mac/SetupGL/Carbon_SetupGL.h new file mode 100755 index 0000000..57f0e67 --- /dev/null +++ b/MacGLide/Mac/SetupGL/Carbon_SetupGL.h @@ -0,0 +1,199 @@ +/* + File: SetupGL.h + + Contains: Functions to enable build and destory a GL fullscreen context + + Written by: Geoff Stahl (ggs) + + Copyright: Copyright Š 1999 Apple Computer, Inc., All Rights Reserved + + Change History (most recent first): + + <2> 3/26/01 ggs Add DSp version check and other items for full screen on X + <1> 1/19/01 ggs Initial re-add + <7> 3/21/00 ggs Added windowed mode and clean up various implementation details + <6> 1/26/00 ggs Add fade code back in, ensure NULL pointer/context/drawable + checks are in, add Preflight + <5> 1/24/00 ggs Added get device num and get gdhandle from point routines, add + support for compiling from C++ + <4> 12/18/99 ggs Fix headers + <3> 11/28/99 ggs Split out DSp and error handling. Added texture memory + considerations, assume VRAM is required if other than zero + <3> 11/12/99 ggs add pixel format and freq return + <2> 11/12/99 ggs 1.0 Interface complete + <1> 11/11/99 ggs Initial Add + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under AppleŐs + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +// Usage notes: + + + +// include control -------------------------------------------------- + +#ifndef SetupGL_h +#define SetupGL_h + + +// includes --------------------------------------------------------- + +#ifdef __APPLE_CC__ + #include + #include +#else + #include + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// structures (public) ----------------------------------------------- + +// structure for creating a fullscreen context + struct structGLInfo // storage for setup info + { + SInt16 width; // input: width of drawable (screen width in full screen mode), return: actual width allocated + SInt16 height; // input: height of drawable (screen height in full screen mode), return: actual height allocated + Boolean fSizeMust; // input: dspContext must be requested display size (ignored in window mode) + // if fSizeMust display size will not be stepped down to try to find a match, + // if display is stepped down aspect ratio will be maintained for returned size + UInt32 pixelDepth; // input: requested pixel depth + Boolean fDepthMust; // input: pixel depth must be set (if false then current depth will be used if able) + Boolean fFullscreen; // input: use DSp to get fullscreen? (or find full screen renderer) + // if fFullscreen, will search for full screen renderers first then use DSp for others + // unless a device is specified, in which case we will try there first + Boolean fAcceleratedMust; // input: must renderer be accelerated? + GLint aglAttributes[64]; // input: pixel format attributes always required (reset to what was actually allocated) + SInt32 VRAM; // input: minimum VRAM; output: actual (if successful otherwise input) + SInt32 textureRAM; // input: amount of texture RAM required on card; output: same (used in allcoation to ensure enough texture + AGLPixelFormat fmt; // input: none; output pixel format... + SInt32 freq; // input: frequency request for display; output: actual + }; + typedef struct structGLInfo structGLInfo; + typedef struct structGLInfo * pstructGLInfo; + +// structure for creating a context from a window + struct structGLWindowInfo // storage for setup info + { + Boolean fAcceleratedMust; // input: must renderer be accelerated? + GLint aglAttributes[64]; // input: pixel format attributes always required (reset to what was actually allocated) + SInt32 VRAM; // input: minimum VRAM; output: actual (if successful otherwise input) + SInt32 textureRAM; // input: amount of texture RAM required on card; output: same (used in allcoation to ensure enough texture + AGLPixelFormat fmt; // input: none; output pixel format... + Boolean fDraggable; // input: is window going to be dragable, + // if so renderer check (accel, VRAM, textureRAM) will look at all renderers vice just the current one + // if window is not dragable renderer check will either check the single device or short + // circuit to software if window spans multiple devices + // software renderer is consider to have unlimited VRAM, unlimited textureRAM and to not be accelerated + }; + typedef struct structGLWindowInfo structGLWindowInfo; + typedef struct structGLWindowInfo * pstructGLWindowInfo; + +// public function declarations ------------------------------------- + +// Runtime check to see if we are running on Mac OS X +// Inputs: None +// Returns: 0 if < Mac OS X or version number of Mac OS X (10.0 for GM) +UInt32 CheckMacOSX (void); + +// Checks for presense of OpenGL and DSp (if required) +// Inputs: checkFullscreen: true if one wants to run fullscreen (which requires DrwSprocket currently) +// Ouputs: true if OpenGL is installed (and DrawSprocket if checkFullscreen is true +Boolean PreflightGL (Boolean checkFullscreen); + +// Takes device # and geometry request and tries to build best context and drawable +// If requested device does not work, will start at first device and walk down devices +// looking for first one that satisfies requirments +// Devices are numbered in order that DMGetFirstScreenDevice/DMGetNextScreenDevice returns, +// fullscreen devices are numbered after this, but they will be searched first if fFullscreen == true, +// they will not be searched in the non-fullscreen case + +// Inputs: *pnumDevice: -1: main device, 0: any device, other #: attempt that device first, then any device +// *pcontextInfo: request and requirements for cotext and drawable + +// Outputs: *paglDraw, *paglContext and *pdspContext as allocated +// *pnumDevice to device number in list that was used +// *pcontextInfo: allocated parameters + +// If fail to build context: paglDraw, paglContext and pdspContext will be NULL +// If fatal error: will return error and paglDraw, paglContext and pdspContext will be NULL +// Note: Errors can be generated internally when a specific device fails, this is normal and these +// will not be returned is a subsequent device succeeds + +OSStatus BuildGL (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, + short* pnumDevice, pstructGLInfo pcontextInfo, AGLContext aglShareContext); + +// Destroys drawable and context +// Ouputs: *paglDraw, *paglContext and *pdspContext should be 0 on exit + +OSStatus DestroyGL (AGLDrawable* paglDraw, AGLContext* paglContext, DSpContextReference* pdspContext, pstructGLInfo pcontextInfo); + +// same as above except that it takes a window as input and attempts to build requested conext on that +OSStatus BuildGLFromWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext); + +// same as above but destorys a context that was associated with an existing window, window is left intacted +OSStatus DestroyGLFromWindow (AGLContext* paglContext, pstructGLWindowInfo pcontextInfo); + +// Special suspend function to ensure the the GL window is hidden +OSStatus SuspendFullScreenGL (AGLDrawable aglDraw, AGLContext aglContext); + +// Special resume function to ensure the the GL window is shown +OSStatus ResumeFullScreenGL (AGLDrawable aglDraw, AGLContext aglContext); + +// Pauses gl to allow toolbox drawing +OSStatus PauseGL (AGLContext aglContext); + +// resumes gl to allow gl drawing +OSStatus ResumeGL (AGLContext aglContext); + +short FindGDHandleFromRect (Rect * pRect, GDHandle * phgdOnThisDevice); + + +short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice); + +// returns the number of the device that the rect is mostly is on (i.e., where it is numerically in the search order) +short FindDeviceNumFromRect (Rect * rect); + +#ifdef __cplusplus +} +#endif + +#endif // SetupGL_h \ No newline at end of file diff --git a/MacGLide/Mac/SetupGL/Read Me b/MacGLide/Mac/SetupGL/Read Me new file mode 100755 index 0000000..2ca9c1b --- /dev/null +++ b/MacGLide/Mac/SetupGL/Read Me @@ -0,0 +1 @@ +Carbon SetupGL An OpenGL setup utility 9-26-2001 Version 1.7: Modified support for shared textures to be supplied to by the calling application. NOTE: This is an API change and requires applications o explicitly pass in the shared context or NULL. Have not updated full screen handling yet. Also supply a CW6 and CW7 project along with Project Builder project. Fully tested on Mac OS 10.1. Version 1.6: Fixed support for shared textures when original context is destroyed, recover gracefully Version 1.5: Added support for shared textures. Share all contexts by default and add menu command to toggle texturing on and off Version 1.4: Updated for Mac OS X 10.0. - DrawSprocket version < 1.99 on Mac OS X do not provide drawing surface that can be used by GL. The work around is to use aglFullScreen instead for these versions. Version 1.3: Optimized for Carbon and bug fixes. Version 1.2: Carbonized for Mac OS X. Version 1.1: Adds windowed mode that allows creation of an OpenGL context on an already existing window. Also, cleans up existing implementation of full screen mode. SetupGL still handles all aspects of GL setup on the Macintosh. Version 1.0: Added PreflightGL () function. Fixed various minor errors. Corrected fade implementation. Added a little more robustness in the application end in failure conditions, fixed problem with aglFont handling. ---- The Carbon SetupGL Test is a demonstration application which shows multi-window support with multiple OpenGL contexts using data stored in the window refcons. It shows proper handling Carbon TImers for animation, window resize (with and without buffer rects), and shared texturing among other things. Carbon SetupGL is a set of functions that can be used in new and existing applications to handle all aspects of OpenGL setup on the Macintosh under OS 9. It is designed to handle windowed or full screen set up with good error handling and fall back cases. The key to SetupGL is that it attempts to match your 3D context requests with the device that is able to handle them rather than pick a single device and hoping that it can handle the 3D requirements. A version of SetupGL is used in the "Quake III Arena" for the Macintosh by id Software. To use it one fills out the structGLInfo structure (outlined in SetupGL.h) with the requirements and request for the context desired. Then a call to BuildGL will allocate the best matching context if able. BuildGL will set through all available graphics devices attempting to allocate the requested context. If it is unable an error will be reported thought the ReportError function. Currently, ReportError is set to send a debugstr on error, applications will likely need to override this with a more appropriate error reporting method. Additionally, Carbon SetupGL now supports creation of GL contexts on existing windows. See the structGLWindowInfo structure in Carbon SetupGL.h. ---- SetupGL also has some unique features: - The texture RAM variable in the structGLInfo allows you to specify an amount of texture memory, over and above the buffer requirements, that the device must have to satisfy your requirements. This allows you to pick a maximum resolution and bit depth and allow SetupGL to find the resolution and bit depth that can actually be used while maintaining the requested amount of VRAM. This is done by setting fDepthMust and fSizeMust to false on entry, which allows SetupGL to set down in resolutions and pixel depths to get a match. - It allows specification of a screen device to try first by enumeration of the screens. -1 indicates the main screen. Other screens are enumerated in order returned by DMGetFirstScreenDevice and DMGetNextScreenDevice with 0 being the first screen returned. If allocations on the desired screen fails SetupGL will automatically check the other screens. - SetupGL provides the function BuildGLFromWindow and DestroyGLFromWindow to handle cases where you want to setup OpenGL on a preexisting window. Ensure you call the DestroyGLFromWindow to destroy the context. - PauseGL and ResumeGL are provided to allow the user control over the screen. Suppose you wish to draw a movie in the same window as OpenGL is using, just call PauseGL, play your movie and then ResumeGL when finished to start drawing your OpenGL scene again. - PreflightGL checks for existence of OpenGL and if required DrawSprocket ---- Compile time options to be aware of: Error Handler.c: kVerboseErrors: are error strings reported SetupDSp.c: kUseFades: are fades between resolution switches used kUseRAMCheck: is estimated device RAM usage done SetupGL is provided as sample code and is under constant updates. The areas where work is being done are: - better frequency support for multiple resolution step down. Need to store frequency information with resolutions to enable better step down logic. Any suggestions and/or bugs can be directed to the Apple bug reporter at: Descriptions of the operation of the major functions and the structures can be found in the SetupGL.h header file. Note: Some of the access paths will have to reset to point to the location of the OpenGL SDK on your local system and this is built using CodeWarrior 6, Universal Interfaces 3.4b5 and Carbon SDK 1.3d6. We hope this helps people get up and running with OpenGL in a quick and painless manner. ggs \ No newline at end of file diff --git a/MacGLide/MacGLide b/MacGLide/MacGLide new file mode 100644 index 0000000..6b1110a Binary files /dev/null and b/MacGLide/MacGLide differ diff --git a/MacGLide/OpenGLide/Debug.h b/MacGLide/OpenGLide/Debug.h new file mode 100644 index 0000000..6f79913 --- /dev/null +++ b/MacGLide/OpenGLide/Debug.h @@ -0,0 +1,63 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Debug switches +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +//#define OGL_DEBUG +//#define OGL_PROFILING +//#define OGL_RENDER +//#define OPENGL_DEBUG +//#define OGL_DEBUG_COORDS +//#define OGL_ALL + +//#define OGL_DONE +//#define OGL_PARTDONE +//#define OGL_NOTDONE +//#define OGL_COMBINE +//#define OGL_CRITICAL +//#define OGL_FRAMEBUFFER + +//#define OGL_UTEX +//#define OGL_UTEX_MEM +//#define OGL_OPTIMISE_DEBUG +//#define OGL_DEBUG_GLIDE_COORDS +//#define OGL_DEBUG_OPENGL_COORDS + +#ifdef OGL_DEBUG_COORDS + #define OGL_DEBUG_GLIDE_COORDS + #define OGL_DEBUG_OPENGL_COORDS +#endif + +#ifdef OGL_RENDER + #define OGL_DONE + #define OGL_PARTDONE + #define OGL_NOTDONE + #define OGL_DEBUG + #define OGL_CRITICAL + #define OGL_COMBINE + #define OGL_FRAMEBUFFER +#endif + +#ifdef OGL_ALL + #define OGL_DONE + #define OGL_PARTDONE + #define OGL_NOTDONE + #define OGL_DEBUG + #define OGL_CRITICAL + #define OPENGL_DEBUG + #define OGL_PROFILING + #define OGL_UTEX + #define OGL_COMBINE + #define OGL_FRAMEBUFFER + #define OGL_DEBUG_GLIDE_COORDS + #define OGL_DEBUG_OPENGL_COORDS +#endif + +#define OGL_STOP_ON_GL_ERROR diff --git a/MacGLide/OpenGLide/FormatConversion.cpp b/MacGLide/OpenGLide/FormatConversion.cpp new file mode 100644 index 0000000..f5b0fea --- /dev/null +++ b/MacGLide/OpenGLide/FormatConversion.cpp @@ -0,0 +1,452 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* OpenGL Extensions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "FormatConversion.h" + + +void Convert565to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ) +{ + while ( Pixels ) + { + *Buffer2++ = 0xFF000000 | // A + ( (*Buffer1) & 0x001F ) << 19 | // B + ( (*Buffer1) & 0x07E0 ) << 5 | // G + ( (*Buffer1++) & 0xF800 ) >> 8; // R + Pixels--; + } +} + +void Convert565Kto8888( FxU16 *Buffer1, FxU16 key, FxU32 *Buffer2, FxU32 Pixels ) +{ + while ( Pixels ) + { + *Buffer2++ = ( ( (*Buffer1) == key) ? 0x00000000 : 0xFF000000 ) | // A + ( (*Buffer1) & 0x001F ) << 19 | // B + ( (*Buffer1) & 0x07E0 ) << 5 | // G + ( (*Buffer1++) & 0xF800 ) >> 8; // R + Pixels--; + } +} + +// This functions processes 2 pixels at a time, there is no problem in +// passing odd numbers or a number less than 2 for the pixels, but +// the buffers should be large enough +void Convert565to5551( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ) +{ + while ( Pixels > 0 ) + { + *Buffer2++ = ( (*Buffer1) & 0xFFC0FFC0 ) | + ( ( (*Buffer1++) & 0x001F001F ) << 1 ) | + 0x00010001; + Pixels -= 2; + } +} + +// This functions processes 2 pixels at a time, there is no problem in +// passing odd numbers or a number less than 2 for the pixels, but +// the buffers should be large enough +void Convert5551to565( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ) +{ + while ( Pixels > 0 ) + { + *Buffer2++ = ( (*Buffer1) & 0xFFC0FFC0 ) | + ( ( (*Buffer1++) & 0x003E003E ) >> 1 ); + Pixels -= 2; + } +} + +// This functions processes 2 pixels at a time, there is no problem in +// passing odd numbers or a number less than 2 for the pixels, but +// the buffers should be large enough +void Convert4444to4444special( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ) +{ + while ( Pixels > 0 ) + { + *Buffer2++ = ( ( (*Buffer1) & 0x0FFF0FFF ) << 4 )| + ( ( (*Buffer1++) & 0xF000F000 ) >> 12 ); + Pixels -= 2; + } +} + +void Convert1555to5551( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ) +{ + while ( Pixels > 0 ) + { + *Buffer2++ = ( ( (*Buffer1) & 0x7FFF7FFF ) << 1 )| + ( ( (*Buffer1++) & 0x80008000 ) >> 15 ); + Pixels -= 2; + } +} + +unsigned __int64 Mask565_5551_1 = 0xFFC0FFC0FFC0FFC0; +unsigned __int64 Mask565_5551_2 = 0x001F001F001F001F; +unsigned __int64 Mask565_5551_3 = 0x0001000100010001; + +// This functions processes 4 pixels at a time, there is no problem in +// passing odd numbers or a number less than 4 for the pixels, but +// the buffers should be large enough +void MMXConvert565to5551( void *Src, void *Dst, int NumberOfPixels ) +{ + __asm + { + mov ecx, NumberOfPixels + mov eax, Src + shl ecx, 1 + mov edx, Dst + movq mm6, [Mask565_5551_3] + movq mm5, [Mask565_5551_2] + movq mm4, [Mask565_5551_1] + align 16 +copying: + movq mm0, [eax + ecx] + movq mm1, mm6 + movq mm2, mm0 + + pand mm0, mm5 + pand mm2, mm4 + psllq mm0, 1 + por mm1, mm2 + por mm0, mm1 + + movq [edx + ecx], mm0 + sub ecx, 8 + jg copying + EMMS + } +} + +// This functions processes 4 pixels at a time, there is no problem in +// passing odd numbers or a number less than 4 for the pixels, but +// the buffers should be large enough +void MMXConvert565Kto5551( void *Src, FxU32 key, void *Dst, int NumberOfPixels ) +{ + __asm + { + mov ecx, NumberOfPixels + mov eax, Src + shl ecx, 1 + mov edx, Dst + movq mm6, [Mask565_5551_3] + movq mm5, [Mask565_5551_2] + movq mm4, [Mask565_5551_1] + movd mm7, key + movq mm0, mm7 + psllq mm0, 16 + por mm7, mm0 + movq mm0, mm7 + psllq mm0, 32 + por mm7, mm0 + align 16 +copying: + movq mm3, mm7 + movq mm0, [eax + ecx] + movq mm1, mm6 + movq mm2, mm0 + + // Comparing + pcmpeqw mm3, mm0 + + pand mm0, mm5 + pand mm2, mm4 + psllq mm0, 1 + por mm1, mm2 + por mm0, mm1 + + // Applying key + pandn mm3, mm0 + + movq [edx + ecx], mm3 + sub ecx, 8 + jg copying + EMMS + } +} + +unsigned __int64 Mask5551_565_1 = 0xFFC0FFC0FFC0FFC0; +unsigned __int64 Mask5551_565_2 = 0x003E003E003E003E; + +// This functions processes 4 pixels at a time, there is no problem in +// passing odd numbers or a number less than 4 for the pixels, but +// the buffers should be large enough +void MMXConvert5551to565( void *Src, void *Dst, int NumberOfPixels ) +{ + __asm + { + mov ecx, NumberOfPixels + mov eax, Src + shl ecx, 1 + mov edx, Dst + movq mm5, [Mask5551_565_2] + movq mm4, [Mask5551_565_1] + align 16 +copying: + movq mm0, [eax + ecx] + movq mm2, mm0 + + pand mm0, mm5 + pand mm2, mm4 + psrlq mm0, 1 + por mm0, mm2 + + movq [edx + ecx], mm0 + sub ecx, 8 + jg copying + EMMS + } +} + +unsigned __int64 Mask4444_1 = 0x0FFF0FFF0FFF0FFF; +unsigned __int64 Mask4444_2 = 0xF000F000F000F000; + +// This functions processes 4 pixels at a time, there is no problem in +// passing odd numbers or a number less than 4 for the pixels, but +// the buffers should be large enough +void MMXConvert4444to4444special( void *Src, void *Dst, int NumberOfPixels ) +{ + __asm + { + mov ecx, NumberOfPixels + mov eax, Src + shl ecx, 1 + mov edx, Dst + movq mm7, [Mask4444_2] + movq mm6, [Mask4444_1] + align 16 +copying: + movq mm0, [eax + ecx] + movq mm1, mm0 + + pand mm0, mm6 + pand mm1, mm7 + psllq mm0, 4 + psrlq mm1, 12 + por mm0, mm1 + + movq [edx + ecx], mm0 + sub ecx, 8 + jg copying + EMMS + } +} + +unsigned __int64 Mask5551_1 = 0x7FFF7FFF7FFF7FFF; +unsigned __int64 Mask5551_2 = 0x8000800080008000; + +// This functions processes 4 pixels at a time, there is no problem in +// passing odd numbers or a number less than 4 for the pixels, but +// the buffers should be large enough +void MMXConvert1555to5551( void *Src, void *Dst, int NumberOfPixels ) +{ + __asm + { + mov ecx, NumberOfPixels + mov eax, Src + shl ecx, 1 + mov edx, Dst + movq mm7, [Mask4444_2] + movq mm6, [Mask4444_1] + align 16 +copying: + movq mm0, [eax + ecx] + movq mm1, mm0 + + pand mm0, mm6 + pand mm1, mm7 + psllq mm0, 1 + psrlq mm1, 15 + por mm0, mm1 + + movq [edx + ecx], mm0 + sub ecx, 8 + jg copying + EMMS + } +} + +FxU8 Mask565A[8] = { 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF }; +FxU8 Mask565B[8] = { 0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8 }; +FxU8 Mask565G[8] = { 0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07 }; +FxU8 Mask565R[8] = { 0x1F,0x00,0x1F,0x00,0x1F,0x00,0x1F,0x00 }; + +void MMXConvert565to8888( void *Src, void *Dst, FxU32 NumberOfPixels ) +{ + // FxU16 entered is ARGB + // Has to be ABGR + __asm + { + MOVQ MM7, [Mask565A] + mov ECX, NumberOfPixels + MOVQ MM6, [Mask565B] + mov EAX, Src + MOVQ MM5, [Mask565G] + MOVQ MM4, [Mask565R] + mov EDX, Dst +copying: + MOVQ MM0, [EAX] + add EAX, 8 + MOVQ MM2, MM0 + MOVQ MM1, MM0 + + PAND MM0, MM4 // Mask R + PAND MM2, MM6 // Mask B + PSLLW MM0, 11 // Shift R + PAND MM1, MM5 // Mask G + + PSRLW MM2, 8 // Shift B + + MOVQ MM3, MM1 + PSLLW MM1, 13 + POR MM0, MM2 + PSRLW MM3, 3 + POR MM1, MM3 + + POR MM1, MM7 + + MOVQ MM2, MM0 + PUNPCKHBW MM0, MM1 + PUNPCKLBW MM2, MM1 + + // Storing Unpacked + MOVQ [EDX], MM2 + add EDX, 16 + MOVQ [EDX-8], MM0 + sub ECX, 4 + jg copying + EMMS + } +} + +void ConvertA8toAP88( FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ) +{ + while ( Pixels ) + { + *Buffer2 = ( ( ( *Buffer1 ) << 8 ) | ( *Buffer1 ) ); + Buffer1++; + Buffer2++; + Pixels--; + } +} + +void Convert8332to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ) +{ + static FxU32 R, + G, + B, + A; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + A = ( ( ( *Buffer1 ) >> 8 ) & 0xFF ); + R = ( ( ( *Buffer1 ) >> 5 ) & 0x07 ) << 5; + G = ( ( ( *Buffer1 ) >> 2 ) & 0x07 ) << 5; + B = ( ( *Buffer1 ) & 0x03 ) << 6; + *Buffer2 = ( A << 24 ) | ( B << 16 ) | ( G << 8 ) | R; + Buffer1++; + Buffer2++; + } +} + +void ConvertP8to8888( FxU8 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ) +{ + while ( Pixels-- ) + { + *Buffer2++ = palette[ *Buffer1++ ]; + } +} + +void ConvertAI44toAP88( FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ) +{ + for ( FxU32 i = Pixels; i > 0; i-- ) + { + *Buffer2 = ( ( ( ( *Buffer1 ) & 0xF0 ) << 8 ) | ( ( ( *Buffer1 ) & 0x0F ) << 4 ) ); + Buffer2++; + Buffer1++; + } +} + +void ConvertAP88to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ) +{ + FxU32 RGB, + A; + for ( FxU32 i = Pixels; i > 0; i-- ) + { + RGB = ( palette[ *Buffer1 & 0x00FF ] & 0x00FFFFFF ); + A = *Buffer1 >> 8; + *Buffer2 = ( A << 24 ) | RGB; + Buffer1++; + Buffer2++; + } +} + +void ConvertYIQto8888( FxU8 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc ) +{ + LONG R; + LONG G; + LONG B; + + for ( FxU32 i = Pixels; i > 0; i-- ) + { + R = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 0 ]; + + G = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 1 ]; + + B = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 2 ]; + + R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) ); + G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) ); + B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) ); + + *out = ( R | ( G << 8 ) | ( B << 16 ) | 0xff000000 ); + + in++; + out++; + } +} + +void ConvertAYIQto8888( FxU16 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc) +{ + LONG R; + LONG G; + LONG B; + + for ( FxU32 i = Pixels; i > 0; i-- ) + { + R = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 0 ]; + + G = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 1 ]; + + B = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ] + + ncc->qRGB[ ( *in ) & 0x3 ][ 2 ]; + + R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) ); + G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) ); + B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) ); + + *out = ( R | ( G << 8 ) | ( B << 16 ) | ( 0xff000000 & ( *in << 16 ) ) ); + + in++; + out++; + } +} + +void SplitAP88( FxU16 *ap88, FxU8 *index, FxU8 *alpha, FxU32 pixels ) +{ + for ( FxU32 i = pixels; i > 0; i-- ) + { + *alpha++ = ( *ap88 >> 8 ); + *index++ = ( *ap88++ & 0xff ); + } +} diff --git a/MacGLide/OpenGLide/FormatConversion.h b/MacGLide/OpenGLide/FormatConversion.h new file mode 100644 index 0000000..bef2ded --- /dev/null +++ b/MacGLide/OpenGLide/FormatConversion.h @@ -0,0 +1,46 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* format conversion functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __FORMAT_CONVERSION_H__ +#define __FORMAT_CONVERSION_H__ + +// Introduced by MacGLide (available for Big Endian only) +void Convert565Kto5551(const FxU32* Buffer1, FxU32 key, FxU32* Buffer2, FxU32 NumberOfPixels ); +void ConvertP8Kto8888(const FxU8 *Buffer1, FxU32 Key, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ); + +// Litte Endian OpenGLide functions implemented in FormatConversion.cpp +// (Obsolete functions are commented out) +void Convert565to8888(const FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ); +void Convert565Kto8888(const FxU16 *Buffer1, FxU16 key, FxU32 *Buffer2, FxU32 Pixels ); +void Convert565to5551(const FxU32 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ); +void Convert5551to565(const FxU32 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ); +void Convert4444to4444special(const FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ); +void Convert1555to5551(const FxU32 *Buffer1, FxU32 *Buffer2, int Pixels ); +/* +void MMXConvert1555to5551(const void *Src, void *Dst, int NumberOfPixels ); +void MMXConvert565to5551(const void *Src, void *Dst, int NumberOfPixels ); +void MMXConvert565Kto5551(const void *Src, FxU32 key, void *Dst, int NumberOfPixels ); +void MMXConvert5551to565(const void *Src, void *Dst, int NumberOfPixels ); +void MMXConvert565to8888(const void *Src, void *Dst, FxU32 NumberOfPixels ); +void MMXConvert4444to4444special(const void *Src, void *Dst, int NumberOfPixels ); +*/ +void ConvertA8toAP88(const FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ); +void ConvertAI44toAP88(const FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels ); +void Convert8332to8888(const FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels ); +void ConvertP8to8888(const FxU8 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ); +void ConvertAP88to8888(const FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette ); +void ConvertYIQto8888(const FxU8 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc ); +void ConvertAYIQto8888(const FxU16 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc ); +void SplitAP88(const FxU16 *ap88, FxU8 *index, FxU8 *alpha, FxU32 pixels ); +void Convert1555Kto8888(const FxU16* Buffer1, FxU16 Key, FxU32* Buffer2, FxU32 Pixels); + +#endif diff --git a/MacGLide/OpenGLide/Framebuffer.cpp b/MacGLide/OpenGLide/Framebuffer.cpp new file mode 100644 index 0000000..eb03299 --- /dev/null +++ b/MacGLide/OpenGLide/Framebuffer.cpp @@ -0,0 +1,1003 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* framebuffer emulation +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Framebuffer.h" +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideSettings.h" +#include "GLRenderUpdateState.h" +#include "GLColorAlphaCombineEnvTables.h" + +// check if tile needs to be displayed +#define CHECK_RENDER_TILE + +// Display small dots at opposite corners of rendered framebuffer tiles +// #define DEBUG_TILE_RENDERING + +Framebuffer::Framebuffer() +: m_x_step_start(0) +, m_y_step_start(0) +, m_x_step_start_opaque(0) +, m_y_step_start_opaque(0) +, m_width(0) +, m_height(0) +, m_framebuffer(NULL) +, m_texbuffer(NULL) +, m_origin(GR_ORIGIN_UPPER_LEFT) +, m_glInternalFormat(-1) +, m_glFormat(-1) +, m_glType(-1) +, m_ChromaKey(0x0000) +, m_glDepth(1.0f) +, m_glAlpha(0x000000ff) +, m_format_valid(false) +, m_use_client_storage(false) +, m_must_clear_buffer(true) +, m_custom_tilesizes(NULL) +{ +} + +Framebuffer::~Framebuffer() +{ +} + +bool Framebuffer::initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, const tilesize* tilesizetable, bool use_client_storage) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::initialise_buffers(---, ---, %d, %d, ---, %d)\n", width, height, use_client_storage); + #endif + + m_custom_tilesizes = tilesizetable; + return initialise_buffers(framebuffer, texbuffer, width, height, 0, 0, use_client_storage); +} + +bool Framebuffer::initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, FxU32 x_tile, FxU32 y_tile, bool use_client_storage) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::initialise_buffers(---, ---, %d, %d, %d, %d, %d)\n", width, height, x_tile, y_tile, use_client_storage); + #endif + + m_framebuffer = framebuffer; + m_texbuffer = texbuffer; + m_framebuffer->WriteMode = m_texbuffer->WriteMode = GR_LFBWRITEMODE_UNUSED; + m_width = width; + m_height = height; + // find out largest texture size + GLint tile_size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tile_size); + m_x_step_start_opaque = tile_size; + m_y_step_start_opaque = tile_size; + m_x_step_start = min(tile_size, x_tile); + m_y_step_start = min(tile_size, y_tile); + m_x_step_start = max(16, m_x_step_start); + m_y_step_start = max(16, m_y_step_start); + m_use_client_storage = use_client_storage; + // The texture priority is set to minimun because + // frame buffer textures are never used a second time + GLfloat zero = 0.0f; + if (m_use_client_storage) + { + glGenTextures( m_max_client_storage_textures, &m_tex_name[0]); + for(int i = 0; i < m_max_client_storage_textures; i++) + { + glPrioritizeTextures(1, &m_tex_name[i], &zero); + } + } + else + { + glGenTextures( 1, &m_tex_name[0]); + glPrioritizeTextures(1, &m_tex_name[0], &zero); + } + for(int i = 0; i < (m_use_client_storage ? m_max_client_storage_textures : 1); i++) + { + glBindTexture(GL_TEXTURE_2D, m_tex_name[i]); + 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, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + } + // If a game has it's own tilesize table, use + // the largest tiles for opaque renderings + GLint y_step = y_tile == 0 ? m_y_step_start_opaque : m_y_step_start; + // init default/opaque tilesize table + int v = 0; + int w = 0; + for(FxU32 y = 0; y < m_height && w < MaxTiles ; y += y_step, w++) + { + while (m_height - y < y_step) + { + y_step = y_step >> 1; + } + m_tilesizes[w].y = y_step; + GLint x_step = x_tile == 0 ? m_x_step_start_opaque : m_x_step_start; + for(FxU32 x = 0, v = 0; x < m_width && v < MaxTiles; x += x_step, v++ ) + { + while (m_width - x < x_step) + { + x_step = x_step >> 1; + } + m_tilesizes[w].x[v] = x_step; + } + } + return m_width > 0 && m_height > 0 && m_x_step_start > 0 && m_y_step_start > 0 && m_format_valid; +} + +void Framebuffer::free_buffers() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::free_buffers()\n"); + #endif + + if (m_tilesizes) FreeObject(m_tilesizes); + if (m_use_client_storage) + { + glDeleteTextures( m_max_client_storage_textures, &m_tex_name[0] ); + } + else + { + glDeleteTextures( 1, &m_tex_name[0] ); + } +} + +void Framebuffer::initialise_format(GrLfbWriteMode_t writemode) +{ + #if defined(OGL_PART_DONE) || defined(OGL_FRAMEBUFFER) + GlideMsg("Framebuffer::initialise_format(0x%x)\n", writemode); + #endif + + // Enlarge buffer? + if (writemode >= GR_LFBWRITEMODE_888 && + (m_framebuffer->WriteMode < GR_LFBWRITEMODE_888 || m_framebuffer->WriteMode == GR_LFBWRITEMODE_UNUSED) && + m_framebuffer->Address) + { + // Delete existing buffer + FreeFrameBuffer(m_framebuffer->Address); + m_framebuffer->Address = NULL; + m_texbuffer->Address = NULL; + } + // Allocate 32-bit buffer (16bit buffer has been allocated in grSstWinOpen() + if (m_framebuffer->Address == NULL) + { + unsigned long openglpixels = OpenGL.WindowWidth * OpenGL.WindowHeight; + // Framebuffer can be written to with 16bit or 32bit data + unsigned long buffertypesize = (writemode >= GR_LFBWRITEMODE_888) ? sizeof(FxU32) : sizeof(FxU16); + Glide.FrameBuffer.Address = (FxU16*) AllocFrameBuffer(Glide.WindowTotalPixels * buffertypesize + openglpixels * sizeof(FxU32), 1); + Glide.TempBuffer.Address = &Glide.FrameBuffer.Address[Glide.WindowTotalPixels * buffertypesize >> 1]; + memset( Glide.FrameBuffer.Address, 0, Glide.WindowTotalPixels * buffertypesize); + memset( Glide.TempBuffer.Address, 0, openglpixels * sizeof(FxU32)); + } + m_framebuffer->WriteMode = writemode; + m_glInternalFormat = 4; + m_glFormat = GL_RGBA; + m_glType = GL_UNSIGNED_BYTE; + FxU16 chromakeyvalue; + switch (writemode) + { + case GR_LFBWRITEMODE_565: + chromakeyvalue = s_GlideApplication.GetType() == GlideApplication::Carmageddon + ? 0x1f1f : 0x07ff; + m_format_valid = true; + break; + case GR_LFBWRITEMODE_1555: + chromakeyvalue = 0x03ff; + m_format_valid = true; + break; + case GR_LFBWRITEMODE_888: + chromakeyvalue = 0x7ffdfeff; + m_format_valid = true; + break; + default: + chromakeyvalue = 0x0; + m_format_valid = false; + break; + } + // When the chromakeyvalue changes, the buffer has to be cleared + if (chromakeyvalue != m_ChromaKey) + { + m_ChromaKey = chromakeyvalue; + m_must_clear_buffer = true; + } +} + +bool Framebuffer::begin_write() +{ +#ifdef OGL_FRAMEBUFFER + GlideMsg("Framebuffer::begin_write()\n"); +#endif + + if (m_must_clear_buffer) + { + Clear(); + m_must_clear_buffer = false; + } + return true; +} + +void Framebuffer::Clear() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::Clear()\n"); + #endif + + FxU16 ChromaKey = m_ChromaKey; + FxU32 count = m_width * m_height ; + FxU16* framebuffer = m_framebuffer->Address; + for ( int i = 0; i < count; i++) + { + framebuffer[i] = ChromaKey; + } +} + +bool Framebuffer::end_write(FxU32 alpha, GLfloat depth, bool pixelpipeline) +{ +#ifdef OGL_FRAMEBUFFER + GlideMsg("Framebuffer::end_write(%d, %f, %d)\n", alpha, depth, pixelpipeline); +#endif + + m_glDepth = depth; + m_glAlpha = alpha; + // if all pixels are invisible, nothing must be rendered. + // The pixel conversion functions assume alpha is != 0 in order + // to determine if a tile contains any pixels to be rendered. + if (m_glAlpha == 0) return false; + set_gl_state(pixelpipeline); + draw(m_custom_tilesizes ? m_custom_tilesizes : m_tilesizes, pixelpipeline); + restore_gl_state(pixelpipeline); + return true; +} + +bool Framebuffer::end_write(FxU32 alpha) +{ +#ifdef OGL_DONE + GlideMsg("Framebuffer::end_write(%d)\n", alpha); +#endif + + // draw frame buffer + // @todo: Depth should OpenGL.ZNear, but that breaks overlays in Myth + FxBool result = end_write(alpha, 0.0, false); + return result; +} + +bool Framebuffer::end_write() +{ +#ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::end_write( )\n" ); +#endif + + return end_write(0x000000ff); +} + +bool Framebuffer::end_write_opaque() +{ +#ifdef OGL_FRAMEBUFFER + GlideMsg("Framebuffer::end_write_opaque()\n"); +#endif + + // @todo: Depth should OpenGL.ZNear, but that breaks overlays in Myth + return end_write(0x000000ff, 0.0, false); +} + +void Framebuffer::set_gl_state(bool pixelpipeline) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::set_gl_state(%d)\n", pixelpipeline); + #endif + + glReportErrors("Framebuffer::set_gl_state"); + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + // Disable the cull mode + glDisable(GL_CULL_FACE); + // Disable clip volume hint manually to avoid recursion + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); + } + + if (pixelpipeline) + { + if (OpenGL.ColorAlphaUnit2) + { + // Pixelpipeline support for env cobine based rendering: + // Framebuffer pixels must be routed through the coloralpha unit + // as if they were produced by the vertex iterators without an + // additional GL texture unit -> source must be changed accordingly + m_bRestoreColorCombine = false; + if (Glide.State.ColorCombineLocal == GR_COMBINE_LOCAL_ITERATED) + { + Glide.State.ColorCombineLocal = GR_COMBINE_LOCAL_PIXELPIPELINE; + m_bRestoreColorCombine = true; + } + if (Glide.State.ColorCombineOther == GR_COMBINE_OTHER_ITERATED) + { + Glide.State.ColorCombineOther = GR_COMBINE_OTHER_PIXELPIPELINE; + m_bRestoreColorCombine = true; + } + if (m_bRestoreColorCombine) SetColorCombineState(); + m_bRestoreAlphaCombine = false; + if (Glide.State.AlphaLocal == GR_COMBINE_LOCAL_ITERATED) + { + Glide.State.AlphaLocal = GR_COMBINE_LOCAL_PIXELPIPELINE; + m_bRestoreAlphaCombine = true; + } + if (Glide.State.AlphaOther == GR_COMBINE_OTHER_ITERATED) + { + Glide.State.AlphaOther = GR_COMBINE_OTHER_PIXELPIPELINE; + m_bRestoreAlphaCombine = true; + } + if (m_bRestoreAlphaCombine) SetAlphaCombineState(); + // Update the opengl state for the pixel pipeline + RenderUpdateState(); + // If the write mode doesn't provide alpha then m_glAlpha is used + // as the constant alpha value, and we can use the alpha test + // to mask out chromakey pixels + switch (m_framebuffer->WriteMode) + { + case GR_LFBWRITEMODE_565: + case GR_LFBWRITEMODE_888: + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_EQUAL, m_glAlpha * D1OVER255); + glReportError(); + break; + } + } + // Set the origin with clipping + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (m_origin == GR_ORIGIN_LOWER_LEFT) + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMinY, Glide.State.ClipMaxY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + else + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMaxY, Glide.State.ClipMinY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + // The scissor rectangle is not reset, because scissor mode + // is only enabled when clearing the buffer + glMatrixMode(GL_MODELVIEW); + glReportError(); + } + else + { + // disable blend + glDisable(GL_BLEND); + // disable depth buffer + glDepthMask(false); + // Enable colormask + glColorMask( true, true, true, false); + // Needed for displaying in-game menus + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glDisable(GL_DEPTH_TEST); + } + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0); + // @todo: use the same parameters as for chroma keying + // in order to save a state change on restore + // glAlphaFunc(GL_GEQUAL, 0.5); + glReportError(); + if (InternalConfig.EXT_secondary_color) + { + glDisable(GL_COLOR_SUM_EXT); + glReportError(); + } + // Reset the clipping window + // and set the origin + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (m_origin == GR_ORIGIN_LOWER_LEFT) + { + glOrtho(0, Glide.WindowWidth, + 0, Glide.WindowHeight, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX, + OpenGL.OriginY, + OpenGL.WindowWidth, + OpenGL.WindowHeight); + } + else + { + glOrtho(0, Glide.WindowWidth, + Glide.WindowHeight, 0, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX, + OpenGL.OriginY, + OpenGL.WindowWidth, + OpenGL.WindowHeight); + } + // The scissor rectangle is not changed, because scissor mode + // is only enabled when clearing the buffer + glMatrixMode(GL_MODELVIEW); + glReportError(); + + // Disable fog + bool disable_fog_texture_unit = OpenGL.FogTextureUnit; + if (disable_fog_texture_unit) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glDisable(GL_TEXTURE_2D); + } + if (OpenGL.Fog && + InternalConfig.FogMode != OpenGLideFogEmulation_None && + InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine) + { + glDisable(GL_FOG); + } + glReportError(); + + // enable framebuffer texture unit + if (OpenGL.ColorAlphaUnit2) + { + bool disable_coloralpha_texture_unit_2 = OpenGL.ColorAlphaUnitColorEnabledState[1] || OpenGL.ColorAlphaUnitAlphaEnabledState[1]; + if (disable_coloralpha_texture_unit_2) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit2); + glDisable(GL_TEXTURE_2D); + } + if (disable_fog_texture_unit || disable_coloralpha_texture_unit_2) glActiveTextureARB(OpenGL.ColorAlphaUnit1); + if (!OpenGL.ColorAlphaUnitColorEnabledState[0] && !OpenGL.ColorAlphaUnitAlphaEnabledState[0]) + { + glEnable(GL_TEXTURE_2D); + } + } + else + { + if (disable_fog_texture_unit) glActiveTextureARB(OpenGL.ColorAlphaUnit1); + if (OpenGL.Texture == false) glEnable(GL_TEXTURE_2D); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glReportError(); + } +} + +void Framebuffer::restore_gl_state(bool pixelpipeline) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::restore_gl_state(%d)\n", pixelpipeline); + #endif + + glReportErrors("Framebuffer::restore_gl_state"); + // Restore the cull mode + switch (Glide.State.CullMode) + { + case GR_CULL_DISABLE: + break; + case GR_CULL_NEGATIVE: + case GR_CULL_POSITIVE: + glEnable(GL_CULL_FACE); + break; + } + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); + } + + // Restore the clipping window + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if ( Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT ) + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMinY, Glide.State.ClipMaxY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + else + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMaxY, Glide.State.ClipMinY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + // The scissor rectangle is not reset, because scissor mode + // is only enabled when clearing the buffer + glMatrixMode( GL_MODELVIEW ); + glReportError(); + + if (pixelpipeline) + { + if (OpenGL.ColorAlphaUnit2) + { + // restore current values + if (m_bRestoreColorCombine) + { + if (Glide.State.ColorCombineLocal == GR_COMBINE_LOCAL_PIXELPIPELINE) Glide.State.ColorCombineLocal = GR_COMBINE_LOCAL_ITERATED; + if (Glide.State.ColorCombineOther == GR_COMBINE_OTHER_PIXELPIPELINE) Glide.State.ColorCombineOther = GR_COMBINE_OTHER_ITERATED; + SetColorCombineState(); + } + if(m_bRestoreAlphaCombine) + { + if (Glide.State.AlphaLocal == GR_COMBINE_LOCAL_PIXELPIPELINE) Glide.State.AlphaLocal = GR_COMBINE_LOCAL_ITERATED; + if (Glide.State.AlphaOther == GR_COMBINE_OTHER_PIXELPIPELINE) Glide.State.AlphaOther = GR_COMBINE_LOCAL_ITERATED; + SetAlphaCombineState(); + } + } + switch (m_framebuffer->WriteMode) + { + case GR_LFBWRITEMODE_565: + case GR_LFBWRITEMODE_888: + SetChromaKeyAndAlphaState(); + break; + } + } + else + { + // restore previous state + if (OpenGL.DepthBufferWritting ) + { + glDepthMask( true ); + } + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glEnable( GL_DEPTH_TEST ); + } + // Restore colormask + bool rgb = Glide.State.ColorMask; + glColorMask(rgb, rgb, rgb, Glide.State.AlphaMask); + + if ( OpenGL.Blend ) + { + glEnable( GL_BLEND ); + } + if ( InternalConfig.EXT_secondary_color ) + { + glEnable( GL_COLOR_SUM_EXT ); + } + glReportError(); + // Enable fog? + bool enable_fog_texture_unit = OpenGL.FogTextureUnit && + ((OpenGL.Fog && InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) || + Glide.State.ColorCombineInvert || + Glide.State.AlphaInvert); + if (enable_fog_texture_unit) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + glEnable(GL_TEXTURE_2D); + // We're not using glDrawArrays to render the frame buffer, + // but without disabling the client state the next texture drawn + // by RenderDrawTriangles would get the wrong coordinates. + // Can be observed in Carmageddon: The sky texture is rendered "too high" + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + if (OpenGL.ColorAlphaUnit2 == 0) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + } + if (OpenGL.Fog && + InternalConfig.FogMode != OpenGLideFogEmulation_None && + InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine) + { + glEnable(GL_FOG); + } + glReportError(); + + if (OpenGL.ColorAlphaUnit2) + { + bool enable_coloralpha_texture_unit_2 = OpenGL.ColorAlphaUnitColorEnabledState[1] || OpenGL.ColorAlphaUnitAlphaEnabledState[1]; + if (enable_coloralpha_texture_unit_2) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit2); + glEnable(GL_TEXTURE_2D); + } + if (enable_fog_texture_unit || enable_coloralpha_texture_unit_2) glActiveTextureARB(OpenGL.ColorAlphaUnit1); + if (!OpenGL.ColorAlphaUnitColorEnabledState[0] && !OpenGL.ColorAlphaUnitAlphaEnabledState[0]) + { + glDisable(GL_TEXTURE_2D); + } + // Restore the previous texture environment + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + } + else + { + if (OpenGL.Texture == false) + { + glDisable(GL_TEXTURE_2D); + } + // Restore the previous texture environment + SetColorCombineState(); + } + glReportError(); + // This must be a forced update because GlideState changes of ChromaKeyMode + // that don't change the corresponding GL-state are filtered out + ForceChromaKeyAndAlphaStateUpdate(); + } + + glReportError(); + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + + +bool Framebuffer::draw(const tilesize* tilesizetable, bool pixelpipeline) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "Framebuffer::draw(---, %d)\n", pixelpipeline); + #endif + + glReportErrors("Framebuffer::draw()"); + GLint x_step; + GLint y_step; + bool init_second_textureunit = pixelpipeline && OpenGL.ColorAlphaUnit2; + int texturenameindex = 0; + FxU32* texbuffer = reinterpret_cast(m_texbuffer->Address); + if (m_use_client_storage) + { + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, true); + glReportError(); + } + FxU32 x; + FxU32 y; + y = 0; + for(int w = 0; y < m_height && w < MaxTiles; w++, y += y_step) + { + y_step = tilesizetable[w].y; + x = 0; + for(int v = 0; x < m_width && v < MaxTiles; v++, x += x_step) + { + x_step = tilesizetable[w].x[v]; + if (createTextureData(texbuffer, x, y, x_step, y_step)) + { + // Obsolete, enabled before calling draw() + GLint texturename; + if (m_use_client_storage) + { + // Multiple textures are used to keep the gl pipeline busy + texturename = m_tex_name[texturenameindex]; + if (texturenameindex == m_max_client_storage_textures -1) + { + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE , false); + glReportError(); + } + else if (texturenameindex < m_max_client_storage_textures -1) + { + texturenameindex++; + } + } + else + { + // Just one texture is used to minimise memory usage + // @todo: Could be further optimised by using multiple texture names + // (Like if CLIENT_STORAGE_APPLE is present) and deleting obsolete + // textures > texturenameindex after rendering the current framebuffer. + texturename = m_tex_name[0]; + } + glBindTexture(GL_TEXTURE_2D, texturename); + #ifdef DEBUG_TILE_RENDERING + ((long*) texbuffer)[0] = 0x00ff00ff; + ((long*) texbuffer)[x_step * y_step - 1] = 0x00ff00ff; + #endif + glTexImage2D(GL_TEXTURE_2D, 0, m_glInternalFormat, x_step, y_step, 0, m_glFormat, m_glType, texbuffer); + if (init_second_textureunit) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit2); + glBindTexture(GL_TEXTURE_2D, texturename); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glReportError(); + static struct + { + const GLfloat bl[4]; + const GLfloat br[4]; + const GLfloat tr[4]; + const GLfloat tl[4]; + } + texcoords = + { + {0.0, 0.0, 1.0, 1.0}, + {1.0, 0.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + {0.0, 1.0, 1.0, 1.0} + }; + glBegin(GL_QUADS); + // counter clockwise + glColor3f(1.0, 1.0, 1.0); + glTexCoord4fv(&texcoords.bl[0]); + if (init_second_textureunit) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &texcoords.bl[0]); + } + glVertex3f(x, y, m_glDepth); + glColor3f(1.0, 1.0, 1.0); + glTexCoord4fv(&texcoords.br[0]); + if (init_second_textureunit) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &texcoords.br[0]); + } + glVertex3f(x + x_step, y, m_glDepth); + glColor3f(1.0, 1.0, 1.0); + glTexCoord4fv(&texcoords.tr[0]); + if (init_second_textureunit) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &texcoords.tr[0]); + } + glVertex3f(x + x_step, y + y_step, m_glDepth); + glColor3f(1.0, 1.0, 1.0); + glTexCoord4fv(&texcoords.tl[0]); + if (init_second_textureunit) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &texcoords.tl[0]); + } + glVertex3f(x, y + y_step , m_glDepth); + glEnd(); + glReportError(); + // use the next texbuffer location + if (m_use_client_storage && texturenameindex != m_max_client_storage_textures -1) + { + texbuffer += x_step * y_step; + } + } + } + } + if (m_use_client_storage && texturenameindex < m_max_client_storage_textures - 1) + { + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE , false); + glReportError(); + } + + s_Framebuffer.SetRenderBufferChanged(); + return y == m_height && x == m_width; +} + +inline bool Framebuffer::Convert565Kto8888(FxU16* buffer1, register FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride) +{ + // Process two pixels at once + const register unsigned long chromakey1 = m_ChromaKey << 16; + const register unsigned long chromakey2 = m_ChromaKey; + const register unsigned long chromakey12 = chromakey1 | chromakey2; + width = width >> 1; + stride = stride >> 1; + register unsigned long pixel; + register unsigned long* stop; + register unsigned jump = width + stride; + register unsigned long* src = reinterpret_cast(buffer1); + // check if tile must be processed in advance + // to avoid useless writes to main memory + // The tile should at least fit into the second level cache + // so reading it again wouldn't hurt as much as doing needless writes + register unsigned long h = height; + stop = &src[width]; + do + { + do + { + pixel = *src++; + if (pixel != chromakey12) goto create_8888_texture; + } while (src != stop); + src += stride; + stop += jump; + } while (--h); + return false; +create_8888_texture: + const register unsigned long alpha = m_glAlpha; + const register unsigned long mask_pixel1 = 0xffff0000; + const register unsigned long mask_pixel2 = 0x0000ffff; + const register unsigned long mask_pixel1_r = 0xf8000000; + const register unsigned long mask_pixel1_g = 0x07e00000; + const register unsigned long mask_pixel1_b = 0x001f0000; + const register unsigned long mask_pixel2_r = 0x0000f800; + const register unsigned long mask_pixel2_g = 0x000007e0; + const register unsigned long mask_pixel2_b = 0x0000001f; + src = reinterpret_cast(buffer1); + stop = &src[width]; + do + { + do + { + // GL_RGBA + pixel = *src; + if (pixel == chromakey12) + { + *buffer2++ = 0; + *buffer2++ = 0; + } + else + { + *src = chromakey12; + if ( (pixel & mask_pixel1) == chromakey1) + { + *buffer2++ = 0; + } + else + { + *buffer2++ = ( alpha | // A + ( pixel & mask_pixel1_b ) >> 5 | // B + ( pixel & mask_pixel1_g ) >> 3 | // G + ( pixel & mask_pixel1_r )); // R + } + if ( (pixel & mask_pixel2) == chromakey2) + { + *buffer2++ = 0; + } + else + { + *buffer2++ = ( alpha | // A + ( pixel & mask_pixel2_b ) << 11 | // B + ( pixel & mask_pixel2_g ) << 13 | // G + ( pixel & mask_pixel2_r ) << 16); // R + } + } + src++; + } while (src != stop); + src += stride; + stop += jump; + } while (--height); + return true; +} + +inline bool Framebuffer::Convert1555Kto8888(FxU16* buffer1, register FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride) +{ + // Process two pixels at once + register unsigned long pixel; + register unsigned long x; + register unsigned long* src = reinterpret_cast(buffer1); + const unsigned long null = 0x00000000; + register unsigned long dstpixel = null; + const register unsigned long chromakey1 = m_ChromaKey << 16; + const register unsigned long chromakey2 = m_ChromaKey; + const register unsigned long chromakey12 = chromakey1 | chromakey2; + const register unsigned long alpha = m_glAlpha; + const register unsigned long mask_pixel1 = 0xffff0000; + const register unsigned long mask_pixel2 = 0x0000ffff; + const register unsigned long mask_pixel1_r = 0x7c000000; + const register unsigned long mask_pixel1_g = 0x03e00000; + const register unsigned long mask_pixel1_b = 0x001f0000; + const register unsigned long mask_pixel2_r = 0x00007c00; + const register unsigned long mask_pixel2_g = 0x000003e0; + const register unsigned long mask_pixel2_b = 0x0000001f; + width >>= 1; + stride >>= 1; + do + { + x = width; + do + { + // GL_RGBA + pixel = *src; + if (pixel == chromakey12) + { + *buffer2++ = null; + *buffer2++ = null; + } + else + { + *src = chromakey12; + if ( (pixel & mask_pixel1) == chromakey1) + { + *buffer2++ = null; + } + else + { + dstpixel = ( alpha | // A + ( pixel & mask_pixel1_b ) >> 5 | // B + ( pixel & mask_pixel1_g ) >> 2 | // G + ( pixel & mask_pixel1_r ) << 1); // R + *buffer2++ = dstpixel; + } + if ( (pixel & mask_pixel2) == chromakey2) + { + *buffer2++ = null; + } + else + { + dstpixel = ( alpha | // A + ( pixel & mask_pixel2_b ) << 11 | // B + ( pixel & mask_pixel2_g ) << 14 | // G + ( pixel & mask_pixel2_r ) << 17); // R + *buffer2++ = dstpixel; + } + } + src++; + } while (--x); + src += stride; + } while (--height); + return dstpixel != null; +} + +inline bool Framebuffer::ConvertARGB8888Kto8888(FxU32* buffer1, register FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride) +{ + // Process two pixels at once + const register unsigned long chromakey = m_ChromaKey || (m_ChromaKey << 16); + register unsigned long pixel; + register unsigned long* stop; + register unsigned jump = width + stride; + register unsigned long* src = buffer1; + // check if tile must be processed in advance + // to avoid useless writes to main memory + // The tile should at least fit into the second level cache + // so reading it again wouldn't hurt as much as doing needless writes + register unsigned long h = height; + stop = &src[width]; + do + { + do + { + pixel = *src++; + if (pixel != chromakey) goto create_8888_texture; + } while (src != stop); + src += stride; + stop += jump; + } while (--h); + return false; +create_8888_texture: + const register unsigned long alpha = m_glAlpha; + src = buffer1; + stop = &src[width]; + do + { + do + { + // GL_RGBA + pixel = *src; + if (pixel == chromakey) + { + *buffer2++ = 0; + } + else + { + *src = chromakey; + *buffer2++ = (pixel << 8) | alpha; + } + src++; + } while (src != stop); + src += stride; + stop += jump; + } while (--height); + return true; +} + +inline bool Framebuffer::createTextureData(FxU32* texbuffer, FxU32 x, FxU32 y, FxU32 x_step, FxU32 y_step) +{ + FxU32 stride = (m_width - x_step); + FxU32 index = x + y * m_width; + if (m_framebuffer->WriteMode == GR_LFBWRITEMODE_565) + { + return Convert565Kto8888(&m_framebuffer->Address[index], texbuffer, x_step, y_step, stride); + } + else if (m_framebuffer->WriteMode == GR_LFBWRITEMODE_1555) + { + return Convert1555Kto8888(&m_framebuffer->Address[index], texbuffer, x_step, y_step, stride); + } + else if (m_framebuffer->WriteMode == GR_LFBWRITEMODE_888) + { + FxU32* framebuffer = &reinterpret_cast(m_framebuffer->Address)[index]; + return ConvertARGB8888Kto8888(framebuffer, texbuffer, x_step, y_step, stride); + } + else + { + return FALSE; + } +} diff --git a/MacGLide/OpenGLide/Framebuffer.h b/MacGLide/OpenGLide/Framebuffer.h new file mode 100644 index 0000000..d75a95f --- /dev/null +++ b/MacGLide/OpenGLide/Framebuffer.h @@ -0,0 +1,76 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* framebuffer emulation +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +class Framebuffer +{ +public: + Framebuffer(); + ~Framebuffer(); +/* + enum Format + { + None = -1, + USHORT_565 = GL_UNSIGNED_SHORT_5_6_5, + USHORT_5551_REV = GL_UNSIGNED_SHORT_1_5_5_5_REV, + UBYTE_8888 + }; +*/ + static const int MaxTiles = 12; + struct tilesize {GLint y; GLint x[MaxTiles];}; +public: + bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, const tilesize* tilesizetable, bool use_client_storage); + bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, FxU32 x_tile, FxU32 y_tile, bool use_client_storage); + void free_buffers(); + void initialise_format(GrLfbWriteMode_t format); + bool begin_write(); + bool end_write(); + bool end_write(FxU32 alpha); + bool end_write(FxU32 alpha, GLfloat depth, bool pixelpipeline); + bool end_write_opaque(); +protected: + void Clear(); + bool draw(const tilesize* tilesizetable, bool pixelpipeline); + void set_gl_state(bool pixelpipeline); + void restore_gl_state(bool pixelpipeline); + inline bool createTextureData(FxU32* texbuffer, FxU32 x, FxU32 y, FxU32 x_step, FxU32 y_step); + inline bool Convert565Kto8888(FxU16* buffer1, FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride); + inline bool Convert1555Kto8888(FxU16* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride); + inline bool ConvertARGB8888Kto8888(FxU32* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride); + static const int m_max_client_storage_textures = 256; + GLuint m_tex_name[m_max_client_storage_textures]; + bool m_use_client_storage; + bool m_must_clear_buffer; + GrOriginLocation_t m_origin; +// GrLfbWriteMode_t m_writemode; + GLint m_glInternalFormat; + GLint m_glFormat; + GLint m_glType; + FxU16 m_ChromaKey; + bool m_format_valid; + BufferStruct* m_framebuffer; + BufferStruct* m_texbuffer; +// FxU16* m_framebuffer; +// void* m_texbuffer; + FxU32 m_width; + FxU32 m_height; + GLint m_x_step_start; + GLint m_y_step_start; + GLint m_x_step_start_opaque; + GLint m_y_step_start_opaque; + tilesize m_tilesizes[MaxTiles]; + const tilesize* m_custom_tilesizes; + GLfloat m_glDepth; + FxU32 m_glAlpha; + // Pixelpipeline + bool m_bRestoreColorCombine; + bool m_bRestoreAlphaCombine; +}; diff --git a/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.cpp b/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.cpp new file mode 100644 index 0000000..3bc5b01 --- /dev/null +++ b/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.cpp @@ -0,0 +1,395 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Color and Alpha CombineEnv tables +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GLColorAlphaCombineEnvTables.h" + +// Additional internal combine functions for reduced terms +// Some of them are really senceless because they're clamped +// to {0.0, 1.0} anyway but they have been defined for complecity. +#define GR_COMBINE_FUNCTION_OTHER 0x11 +#define GR_COMBINE_FUNCTION_MINUS_LOCAL 0x12 +#define GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL 0x13 +#define GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA 0x14 +#define GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL 0x15 +#define GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x16 +#define GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x17 + +// GL equivalents for Glide color combine functions +const CombineFunction ColorCombineFunctionsEnvCombineARB[25] = +{ + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x00 GR_COMBINE_FUNCTION_ZERO + {{{CF_Replace ,{CFARG_Local ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x01 GR_COMBINE_FUNCTION_LOCAL + {{{CF_Replace ,{CFARG_LocalAlpha,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x02 GR_COMBINE_FUNCTION_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Other ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x03 GR_COMBINE_FUNCTION_SCALE_OTHER + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Other ,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_Local ,CFARG_None}}}}, // 0x04 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Other ,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha,CFARG_None}}}}, // 0x05 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Modulate ,{CFARG_Previous ,CFARG_Factor ,CFARG_None}}}}, // 0x06 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL + {{{CF_Blend ,{CFARG_Other ,CFARG_Local ,CFARG_Factor}},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND + + {{{CF_Substract,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Modulate ,{CFARG_Factor ,CFARG_Previous ,CFARG_None}}}}, // 0x08 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA // not correct, needs CF_ModulateAdd + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Local ,CFARG_None }},{CF_Substract ,{CFARG_Local ,CFARG_Previous ,CFARG_None}}}}, // 0x09 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL + + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0a dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0b dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0c dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0d dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0e dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0f dummy + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Local ,CFARG_None }},{CF_Substract ,{CFARG_LocalAlpha,CFARG_Previous ,CFARG_None}}}}, // 0x10 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ZERO + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ONE + {{{CF_Replace ,{CFARG_Other ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x011 GR_COMBINE_FUNCTION_OTHER + {{{CF_Substract,{CFARG_Constant ,CFARG_Constant ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Local ,CFARG_None}}}}, // 0x12 GR_COMBINE_FUNCTION_MINUS_LOCAL // clamped to 0.0 + {{{CF_Add ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x13 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL + {{{CF_Add ,{CFARG_Other ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x14 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x15 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL + {{{CF_Substract,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha,CFARG_None}}}}, // 0x16 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_LocalAlpha,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}} // 0x17 GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA +}; + +const CombineFunction ColorCombineFunctionsEnvCombine3ATI[25] = +{ + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x00 GR_COMBINE_FUNCTION_ZERO + {{{CF_Replace ,{CFARG_Local ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x01 GR_COMBINE_FUNCTION_LOCAL + {{{CF_Replace ,{CFARG_LocalAlpha,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x02 GR_COMBINE_FUNCTION_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Other ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x03 GR_COMBINE_FUNCTION_SCALE_OTHER + + {{{CF_ModulateAdd,{CFARG_Factor ,CFARG_Local ,CFARG_Other }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x04 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL + {{{CF_ModulateAdd,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_Other }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x05 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Modulate ,{CFARG_Previous ,CFARG_Factor ,CFARG_None}}}}, // 0x06 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL +// {{{CF_Blend ,{CFARG_Other ,CFARG_Local ,CFARG_Factor}},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND // psychedelic colors on G5 with ATI9600XT + {{{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None }},{CF_Blend ,{CFARG_Other ,CFARG_Local ,CFARG_Factor}}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND // works (don't ask me why) + + {{{CF_Substract ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_ModulateAdd,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_Previous}}}}, // 0x08 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Local ,CFARG_None }},{CF_Substract ,{CFARG_Local ,CFARG_Previous ,CFARG_None}}}}, // 0x09 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL + + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0a dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0b dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0c dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0d dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0e dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0f dummy + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_Local ,CFARG_None }},{CF_Substract ,{CFARG_LocalAlpha,CFARG_Previous ,CFARG_None}}}}, // 0x10 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ZERO + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ONE + {{{CF_Replace ,{CFARG_Other ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x011 GR_COMBINE_FUNCTION_OTHER + {{{CF_Substract ,{CFARG_Zero ,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x12 GR_COMBINE_FUNCTION_MINUS_LOCAL // clamped to 0.0 + {{{CF_Add ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x13 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL + {{{CF_Add ,{CFARG_Other ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x14 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x15 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL + {{{CF_Substract ,{CFARG_Other ,CFARG_Local ,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha,CFARG_None}}}}, // 0x16 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Substract ,{CFARG_LocalAlpha,CFARG_Local ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}} // 0x17 GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA +}; + +// Mapping for reducing combine functions if factor == GR_COMBINE_FACTOR_ZERO +const CombineReduceTerm ColorCombineFunctionsFactorZero[0x11] = +{ + /* GR_COMBINE_FUNCTION_ZERO */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_BLEND */ {GR_COMBINE_FUNCTION_LOCAL}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA} +}; + +// Mapping for reducing combine functions if factor == GR_COMBINE_FACTOR_ONE +const CombineReduceTerm ColorCombineFunctionsFactorOne[0x11] = +{ + /* GR_COMBINE_FUNCTION_ZERO */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER */ {GR_COMBINE_FUNCTION_OTHER}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL */ {GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL */ {GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL}, + /* GR_COMBINE_FUNCTION_BLEND */ {GR_COMBINE_FUNCTION_OTHER}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL */ {GR_COMBINE_FUNCTION_ZERO}, + + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA} +}; + +const CombineArgument ColorCombineFactors[14] = +{ + {CFARG_Constant,GL_SRC_COLOR}, // 0x00 GR_COMBINE_FACTOR_ZERO + {CFARG_Local,0}, // 0x01 GR_COMBINE_FACTOR_LOCAL + {CFARG_OtherAlpha,0}, // 0x02 GR_COMBINE_FACTOR_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x03 GR_COMBINE_FACTOR_LOCAL_ALPHA + {CFARG_Texture,GL_SRC_ALPHA}, // 0x04 GR_COMBINE_FACTOR_TEXTURE_ALPHA GR_COMBINE_FACTOR_DETAIL_FACTOR + {CFARG_Texture,GL_SRC_COLOR}, // 0x05 GR_COMBINE_FACTOR_TEXTURE_RGB GR_COMBINE_FACTOR_LOD_FRACTION (unused) + {CFARG_Local,0}, // 0x06 placeholder + {CFARG_Local,0}, // 0x07 placeholder + {CFARG_Constant,GL_SRC_COLOR}, // 0x08 GR_COMBINE_FACTOR_ONE + {CFARG_Local,0}, // 0x09 GR_COMBINE_FACTOR_ONE_MINUS_LOCAL + {CFARG_OtherAlpha,0}, // 0x0a GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x0b GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA}, // 0x0c GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA} // 0x0d GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION (unused) +}; + +const CombineArgument ColorCombineFactorsInverted[14] = +{ + {CFARG_Constant,GL_SRC_COLOR}, // 0x00 GR_COMBINE_FACTOR_ZERO + {CFARG_Local,0}, // 0x01 GR_COMBINE_FACTOR_LOCAL + {CFARG_OtherAlpha,0}, // 0x02 GR_COMBINE_FACTOR_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x03 GR_COMBINE_FACTOR_LOCAL_ALPHA + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA}, // 0x04 GR_COMBINE_FACTOR_TEXTURE_ALPHA GR_COMBINE_FACTOR_DETAIL_FACTOR + {CFARG_Texture,GL_ONE_MINUS_SRC_COLOR}, // 0x05 GR_COMBINE_FACTOR_TEXTURE_RGB GR_COMBINE_FACTOR_LOD_FRACTION (unused) + {CFARG_Local,0}, // 0x06 placeholder + {CFARG_Local,0}, // 0x07 placeholder + {CFARG_Constant,GL_SRC_COLOR}, // 0x08 GR_COMBINE_FACTOR_ONE + {CFARG_Local,0}, // 0x09 GR_COMBINE_FACTOR_ONE_MINUS_LOCAL + {CFARG_OtherAlpha,0}, // 0x0a GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x0b GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA + {CFARG_Texture,GL_SRC_ALPHA}, // 0x0c GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR + {CFARG_Texture,GL_SRC_ALPHA} // 0x0d GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION (unused) +}; + +const CombineArgument ColorCombineLocals[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_COLOR}, // 0x00 GR_COMBINE_LOCAL_ITERATED + {GL_CONSTANT_EXT,GL_SRC_COLOR}, // 0x01 GR_COMBINE_LOCAL_CONSTANT GR_COMBINE_LOCAL_NONE + {GL_CONSTANT_EXT,GL_SRC_COLOR}, // 0x02 unused + {GL_TEXTURE,GL_SRC_COLOR} // 0x03 GR_COMBINE_LOCAL_PIXELPIPELINE - needed to support the framebuffer +}; + +const CombineArgument ColorCombineOthers[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_COLOR}, // 0x00 GR_COMBINE_OTHER_ITERATED + {GL_TEXTURE,GL_SRC_COLOR}, // 0x01 GR_COMBINE_OTHER_TEXTURE + {GL_CONSTANT_EXT,GL_SRC_COLOR}, // 0x02 GR_COMBINE_OTHER_CONSTANT GR_COMBINE_OTHER_NONE + {GL_TEXTURE,GL_SRC_COLOR} // 0x03 GR_COMBINE_OTHER_PIXELPIPELINE - needed to support the framebuffer +}; + +const CombineArgument ColorCombineOthersInverted[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_COLOR}, // 0x00 GR_COMBINE_OTHER_ITERATED + {GL_TEXTURE,GL_ONE_MINUS_SRC_COLOR}, // 0x01 GR_COMBINE_OTHER_TEXTURE + {GL_CONSTANT_EXT,GL_SRC_COLOR}, // 0x02 GR_COMBINE_OTHER_CONSTANT GR_COMBINE_OTHER_NONE + {GL_TEXTURE,GL_SRC_COLOR} // 0x03 GR_COMBINE_OTHER_PIXELPIPELINE - needed to support the framebuffer +}; + +// GL equivalents for Glide alpha combine functions +const CombineFunction AlphaCombineFunctionsEnvCombineARB[25] = +{ + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x00 GR_COMBINE_FUNCTION_ZERO + {{{CF_Replace ,{CFARG_LocalAlpha ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x01 GR_COMBINE_FUNCTION_LOCAL + {{{CF_Replace ,{CFARG_LocalAlpha ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x02 GR_COMBINE_FUNCTION_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_OtherAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x03 GR_COMBINE_FUNCTION_SCALE_OTHER + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_OtherAlpha,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha ,CFARG_None}}}}, // 0x04 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL + {{{CF_Modulate ,{CFARG_Factor ,CFARG_OtherAlpha,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha ,CFARG_None}}}}, // 0x05 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Modulate ,{CFARG_Previous ,CFARG_Factor ,CFARG_None}}}}, // 0x06 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL + {{{CF_Blend ,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_Factor }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND + + {{{CF_Substract,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Modulate ,{CFARG_Factor ,CFARG_Previous ,CFARG_None}}}}, // 0x08 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA // not correct, needs CF_ModulateAdd + {{{CF_Modulate ,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_None }},{CF_Substract ,{CFARG_LocalAlpha ,CFARG_Previous ,CFARG_None}}}}, // 0x09 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL + + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0a dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0b dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0c dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0d dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0e dummy + {{{CF_Replace ,{CFARG_Constant ,CFARG_None ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_Constant ,CFARG_None}}}}, // 0x0f dummy + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_None }},{CF_Substract ,{CFARG_LocalAlpha ,CFARG_Previous ,CFARG_None}}}}, // 0x10 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ZERO + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ONE + {{{CF_Replace ,{CFARG_OtherAlpha ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x011 GR_COMBINE_FUNCTION_OTHER + {{{CF_Substract,{CFARG_Constant ,CFARG_Constant ,CFARG_None }},{CF_Substract ,{CFARG_Previous ,CFARG_LocalAlpha,CFARG_None}}}}, // 0x12 GR_COMBINE_FUNCTION_MINUS_LOCAL + {{{CF_Add ,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x13 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL + {{{CF_Add ,{CFARG_OtherAlpha ,CFARG_OtherAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x14 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x15 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL + {{{CF_Replace ,{CFARG_OtherAlpha ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x16 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_LocalAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}} // 0x17 GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA +}; + +// GL equivalents for Glide alpha combine functions +const CombineFunction AlphaCombineFunctionsEnvCombine3ATI[25] = +{ + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x00 GR_COMBINE_FUNCTION_ZERO + {{{CF_Replace ,{CFARG_LocalAlpha,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x01 GR_COMBINE_FUNCTION_LOCAL + {{{CF_Replace ,{CFARG_LocalAlpha,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x02 GR_COMBINE_FUNCTION_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_OtherAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x03 GR_COMBINE_FUNCTION_SCALE_OTHER + + {{{CF_ModulateAdd,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_OtherAlpha}},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x04 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL + {{{CF_ModulateAdd,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_OtherAlpha}},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x05 GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract ,{CFARG_OtherAlpha,CFARG_LocalAlpha,CFARG_None }},{CF_Modulate ,{CFARG_Previous ,CFARG_Factor ,CFARG_None}}}}, // 0x06 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL +// {{{CF_Blend ,{CFARG_OtherAlpha,CFARG_LocalAlpha,CFARG_Factor }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND // psychedelic colors on G5 with ATI9600XT + {{{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None }},{CF_Blend ,{CFARG_OtherAlpha ,CFARG_LocalAlpha ,CFARG_Factor }}}}, // 0x07 GR_COMBINE_FUNCTION_BLEND // works (don't ask me why) + + {{{CF_Substract ,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_ModulateAdd,{CFARG_Factor ,CFARG_LocalAlpha ,CFARG_Previous}}}}, // 0x08 GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Modulate ,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_None }},{CF_Substract,{CFARG_LocalAlpha ,CFARG_Previous ,CFARG_None}}}}, // 0x09 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL + + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0a dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0b dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0c dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0d dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0e dummy + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x0f dummy + + {{{CF_Modulate ,{CFARG_Factor ,CFARG_LocalAlpha,CFARG_None }},{CF_Substract ,{CFARG_LocalAlpha ,CFARG_Previous ,CFARG_None}}}}, // 0x10 GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ZERO + + // Additional functions for reducing the above terms if factor == GR_COMBINE_FACTOR_ONE + {{{CF_Replace ,{CFARG_OtherAlpha ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x011 GR_COMBINE_FUNCTION_OTHER + {{{CF_Substract,{CFARG_Zero ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x12 GR_COMBINE_FUNCTION_MINUS_LOCAL + {{{CF_Add ,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x13 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL + {{{CF_Add ,{CFARG_OtherAlpha ,CFARG_OtherAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x14 GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA + {{{CF_Substract,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}}, // 0x15 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL + {{{CF_Substract,{CFARG_OtherAlpha ,CFARG_LocalAlpha,CFARG_None }},{CF_Add ,{CFARG_Previous ,CFARG_LocalAlpha,CFARG_None}}}}, // 0x16 GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA + {{{CF_Replace ,{CFARG_Zero ,CFARG_None ,CFARG_None }},{CF_Unused ,{CFARG_None ,CFARG_None ,CFARG_None}}}} // 0x17 GR_COMBINE_FUNCTION_MINUS_LOCAL_ADD_LOCAL_ALPHA +}; + +// Mapping for reducing combine functions if factor == GR_COMBINE_FACTOR_ZERO +const CombineReduceTerm AlphaCombineFunctionsFactorZero[0x11] = +{ + /* GR_COMBINE_FUNCTION_ZERO */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_BLEND */ {GR_COMBINE_FUNCTION_LOCAL}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA} +}; + +// Mapping for reducing combine functions if factor == GR_COMBINE_FACTOR_ONE +const CombineReduceTerm AlphaCombineFunctionsFactorOne[0x11] = +{ + /* GR_COMBINE_FUNCTION_ZERO */ {GR_COMBINE_FUNCTION_ZERO}, + /* GR_COMBINE_FUNCTION_LOCAL */ {GR_COMBINE_FUNCTION_LOCAL}, + /* GR_COMBINE_FUNCTION_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER */ {GR_COMBINE_FUNCTION_OTHER}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL */ {GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_OTHER_ADD_LOCAL_ALPHA}, + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL */ {GR_COMBINE_FUNCTION_OTHER_MINUS_LOCAL}, + /* GR_COMBINE_FUNCTION_BLEND */ {GR_COMBINE_FUNCTION_OTHER}, + + /* GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_OTHER}, + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL */ {GR_COMBINE_FUNCTION_ZERO}, + + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + /* dummy */ {GR_COMBINE_FUNCTION_ZERO}, + + /* GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA */ {GR_COMBINE_FUNCTION_ZERO} +}; + +const CombineArgument AlphaCombineFactors[14] = +{ + {CFARG_Constant,GL_SRC_ALPHA}, // 0x00 GR_COMBINE_FACTOR_ZERO + {CFARG_LocalAlpha,0}, // 0x01 GR_COMBINE_FACTOR_LOCAL + {CFARG_OtherAlpha,0}, // 0x02 GR_COMBINE_FACTOR_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x03 GR_COMBINE_FACTOR_LOCAL_ALPHA + {CFARG_Texture,GL_SRC_ALPHA}, // 0x04 GR_COMBINE_FACTOR_TEXTURE_ALPHA GR_COMBINE_FACTOR_DETAIL_FACTOR + {CFARG_Texture,GL_SRC_COLOR}, // 0x05 GR_COMBINE_FACTOR_TEXTURE_RGB GR_COMBINE_FACTOR_LOD_FRACTION (unused) + {CFARG_LocalAlpha,0}, // 0x06 placeholder + {CFARG_LocalAlpha,0}, // 0x07 placeholder + {CFARG_Constant,GL_SRC_ALPHA}, // 0x08 GR_COMBINE_FACTOR_ONE + {CFARG_LocalAlpha,0}, // 0x09 GR_COMBINE_FACTOR_ONE_MINUS_LOCAL + {CFARG_OtherAlpha,0}, // 0x0a GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x0b GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA}, // 0x0c GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA} // 0x0d GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION (unused) +}; + +const CombineArgument AlphaCombineFactorsInverted[14] = +{ + {CFARG_Constant,GL_SRC_ALPHA}, // 0x00 GR_COMBINE_FACTOR_ZERO + {CFARG_LocalAlpha,0}, // 0x01 GR_COMBINE_FACTOR_LOCAL + {CFARG_OtherAlpha,0}, // 0x02 GR_COMBINE_FACTOR_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x03 GR_COMBINE_FACTOR_LOCAL_ALPHA + {CFARG_Texture,GL_ONE_MINUS_SRC_ALPHA}, // 0x04 GR_COMBINE_FACTOR_TEXTURE_ALPHA GR_COMBINE_FACTOR_DETAIL_FACTOR + {CFARG_Texture,GL_ONE_MINUS_SRC_COLOR}, // 0x05 GR_COMBINE_FACTOR_TEXTURE_RGB GR_COMBINE_FACTOR_LOD_FRACTION (unused) + {CFARG_LocalAlpha,0}, // 0x06 placeholder + {CFARG_LocalAlpha,0}, // 0x07 placeholder + {CFARG_Constant,GL_SRC_ALPHA}, // 0x08 GR_COMBINE_FACTOR_ONE + {CFARG_LocalAlpha,0}, // 0x09 GR_COMBINE_FACTOR_ONE_MINUS_LOCAL + {CFARG_OtherAlpha,0}, // 0x0a GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + {CFARG_LocalAlpha,0}, // 0x0b GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA + {CFARG_Texture,GL_SRC_ALPHA}, // 0x0c GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR + {CFARG_Texture,GL_SRC_ALPHA} // 0x0d GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION (unused) +}; + +const CombineArgument AlphaCombineLocals[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_ALPHA}, // 0x00 GR_COMBINE_LOCAL_ITERATED + {GL_CONSTANT_EXT,GL_SRC_ALPHA}, // 0x01 GR_COMBINE_LOCAL_CONSTANT GR_COMBINE_LOCAL_NONE + {GL_PRIMARY_COLOR_EXT,GL_SRC_ALPHA}, // 0x02 GR_COMBINE_LOCAL_DEPTH + {GL_TEXTURE,GL_SRC_ALPHA} // 0x03 GR_COMBINE_LOCAL_PIXELPIPELINE - needed to support the framebuffer +}; + +const CombineArgument AlphaCombineOthers[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_ALPHA}, // 0x00 GR_COMBINE_OTHER_ITERATED + {GL_TEXTURE,GL_SRC_ALPHA}, // 0x01 GR_COMBINE_OTHER_TEXTURE + {GL_CONSTANT_EXT,GL_SRC_ALPHA}, // 0x02 GR_COMBINE_OTHER_CONSTANT GR_COMBINE_OTHER_NONE + {GL_TEXTURE,GL_SRC_ALPHA} // 0x03 GR_COMBINE_OTHER_PIXELPIPELINE - needed to support the framebuffer +}; + +const CombineArgument AlphaCombineOthersInverted[4] = +{ + {GL_PRIMARY_COLOR_EXT,GL_SRC_ALPHA}, // 0x00 GR_COMBINE_OTHER_ITERATED + {GL_TEXTURE,GL_ONE_MINUS_SRC_ALPHA}, // 0x01 GR_COMBINE_OTHER_TEXTURE + {GL_CONSTANT_EXT,GL_SRC_ALPHA}, // 0x02 GR_COMBINE_OTHER_CONSTANT GR_COMBINE_OTHER_NONE + {GL_TEXTURE,GL_SRC_ALPHA} // 0x03 GR_COMBINE_OTHER_PIXELPIPELINE - needed to support the framebuffer +}; diff --git a/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.h b/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.h new file mode 100644 index 0000000..0f621dc --- /dev/null +++ b/MacGLide/OpenGLide/GLColorAlphaCombineEnvTables.h @@ -0,0 +1,84 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Color and Alpha CombineEnv tables +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +enum CombineFunctionValue +{ + CF_Unused = 0, + CF_Replace = GL_REPLACE, + CF_Modulate = GL_MODULATE, + CF_Add = GL_ADD, + CF_Substract = GL_SUBTRACT_ARB, + CF_Blend = GL_INTERPOLATE_EXT, + CF_ModulateAdd = GL_MODULATE_ADD_ATI +}; + +struct CombineArgument +{ + GLint Source; + GLint Operand; +}; + +enum CombineFunctionColorAlphaArg +{ + CFARG_Local = 0, + CFARG_Other = 1, + CFARG_LocalAlpha = 2, + CFARG_OtherAlpha = 3, + CFARG_Factor = 4, + CFARG_None = 5, + CFARG_Constant = GL_CONSTANT_EXT, + CFARG_Previous = GL_PREVIOUS_EXT, + CFARG_Texture = GL_TEXTURE, + CFARG_PrimaryColor = GL_PRIMARY_COLOR_EXT, + CFARG_Zero = GL_ZERO, + CFARG_One = GL_ONE +}; + +struct CombineFunctionGLTextureUnit +{ + CombineFunctionValue Function; + CombineFunctionColorAlphaArg CombineArg[3]; +}; + +struct CombineFunction +{ + CombineFunctionGLTextureUnit ColorAlphaUnit[2]; +}; + +struct CombineReduceTerm +{ + GrCombineFunction_t ReducedTerm; +}; + +extern const CombineFunction ColorCombineFunctionsEnvCombineARB[25]; +extern const CombineFunction ColorCombineFunctionsEnvCombine3ATI[25]; +extern const CombineReduceTerm ColorCombineFunctionsFactorZero[0x11]; +extern const CombineReduceTerm ColorCombineFunctionsFactorOne[0x11]; +extern const CombineFunction AlphaCombineFunctionsEnvCombineARB[25]; +extern const CombineFunction AlphaCombineFunctionsEnvCombine3ATI[25]; +extern const CombineReduceTerm AlphaCombineFunctionsFactorZero[0x11]; +extern const CombineReduceTerm AlphaCombineFunctionsFactorOne[0x11]; +extern const CombineArgument ColorCombineFactors[14]; +extern const CombineArgument AlphaCombineFactors[14]; +extern const CombineArgument ColorCombineFactorsInverted[14]; +extern const CombineArgument AlphaCombineFactorsInverted[14]; +extern const CombineArgument ColorCombineLocals[4]; +extern const CombineArgument ColorCombineOthers[4]; +extern const CombineArgument ColorCombineLocalsInverted[4]; +extern const CombineArgument ColorCombineOthersInverted[4]; +extern const CombineArgument AlphaCombineLocals[4]; +extern const CombineArgument AlphaCombineOthers[4]; +extern const CombineArgument AlphaCombineLocalsInverted[4]; +extern const CombineArgument AlphaCombineOthersInverted[4]; + +#define GR_COMBINE_LOCAL_PIXELPIPELINE 0x03 +#define GR_COMBINE_OTHER_PIXELPIPELINE 0x03 diff --git a/MacGLide/OpenGLide/GLExtensions.cpp b/MacGLide/OpenGLide/GLExtensions.cpp new file mode 100644 index 0000000..83548f2 --- /dev/null +++ b/MacGLide/OpenGLide/GLExtensions.cpp @@ -0,0 +1,653 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* OpenGL Extensions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideSettings.h" +#include "GLColorAlphaCombineEnvTables.h" +#include "GLextensions.h" +#include "GLRender.h" +#include "GLutil.h" + +#include + + +enum enExtensionType +{ + OGL_EXT_UNUSED = 0, + OGL_EXT_REQUIRED, + OGL_EXT_DESIRED +}; + +struct stExtensionSupport +{ + char * name; + enExtensionType type; + bool * userVar; + bool * internalVar; +}; + +// Running in Classic ? +#ifdef OPENGLIDE_HOST_MAC +bool RunningInClassic = false; +#endif + +// It is important that dummyExtVariable retains the value true, so +// we pass dummyExtVariable2 in places where the value may be altered. +bool dummyExtVariable = true; +bool dummyExtVariable2 = true; + +// Env Combine fog data +static GLuint fogtexturename = 0; +static FxU8* fogalpharamp = NULL; +static GLint dummytexture = 0x00000000; + +stExtensionSupport glNecessaryExt[] = +{ + // new + { "GL_EXT_abgr", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 }, + { "GL_EXT_bgra", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 }, + { "GL_EXT_secondary_color", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_secondary_color }, + { "GL_ARB_multitexture", OGL_EXT_DESIRED, &UserConfig.ARB_multitexture, &InternalConfig.ARB_multitexture }, + { "GL_ARB_texture_env_add", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_env_add }, + { "GL_ARB_texture_env_combine", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_env_combine }, + { "GL_ATI_texture_env_combine3", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.ATI_texture_env_combine3 }, + { "GL_EXT_texture_lod_bias", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_lod_bias }, + { "GL_SGIS_generate_mipmap", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_SGIS_generate_mipmap }, + { "GL_SGIS_texture_edge_clamp", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_SGIS_texture_edge_clamp }, + { "GL_EXT_paletted_texture", OGL_EXT_DESIRED, &UserConfig.EXT_paletted_texture, &InternalConfig.EXT_paletted_texture }, + { "GL_APPLE_packed_pixels", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 }, + { "GL_APPLE_client_storage", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_Client_Storage }, + { "GL_EXT_compiled_vertex_array", OGL_EXT_DESIRED, &UserConfig.EXT_compiled_vertex_array,&InternalConfig.EXT_compiled_vertex_array }, +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + { "GL_EXT_fog_coord", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_fog_coord }, +#endif +#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE + { "GL_EXT_blend_func_separate", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_blend_func_separate }, +#endif + { "GL_EXT_texture_filter_anisotropic",OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_filter_anisotropic }, + { "GL_ARB_multisample", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.ARB_multisample }, + { "GL_NV_multisample_filter_hint", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.NV_multisample_filter_hint }, + { "GL_EXT_clip_volume_hint", OGL_EXT_DESIRED, &UserConfig.EXT_clip_volume_hint, &InternalConfig.EXT_clip_volume_hint }, + { "GL_APPLE_transform_hint", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.APPLE_transform_hint }, + { "", OGL_EXT_UNUSED, &dummyExtVariable, &dummyExtVariable2 } +}; + +// check to see if Extension is Supported +// code by Mark J. Kilgard of NVidia modified by Fabio Barros +bool OGLIsExtensionSupported( const char * extension ) +{ + const char * extensions; + const char * start; + char * where, + * terminator; + + where = (char *) strchr( extension, ' ' ); + if ( where || ( *extension == '\0' ) ) + { + return false; + } + + extensions = (char*)glGetString( GL_EXTENSIONS ); + + start = extensions; + + if ( *start == '\0' ) + { + GlideError( "No OpenGL extension supported, using all emulated.\n" ); + return false; + } + + while ( true ) + { + where = (char *)strstr( start, extension ); + if ( !where ) + { + break; + } + terminator = where + strlen( extension ); + if ( ( where == start ) || ( *( where - 1 ) == ' ' ) ) + { + if ( ( *terminator == ' ' ) || ( *terminator == '\0' ) ) + { + return true; + } + } + start = terminator; + } + + // fix for Rage 128 OpenGL Engine 1.1.ATI-5.99 + // (See apple techote TN2014) + if (strcmp(extension, "GL_APPLE_packed_pixels") == 0) + { + return OGLIsExtensionSupported("GL_APPLE_packed_pixel"); + } + // fix for Rage 128 OpenGL Engine 1.1.ATI-5.99 + // support for GL_EXT_texture_env_combine + else if (strcmp(extension, "GL_ARB_texture_env_combine") == 0) + { + return OGLIsExtensionSupported("GL_EXT_texture_env_combine"); + } + // also support the older GL_EXT_texture_env_add + else if (strcmp(extension, "GL_ARB_texture_env_add") == 0) + { + return OGLIsExtensionSupported("GL_EXT_texture_env_add"); + } + else + { + return false; + } +} + +void ValidateUserConfig( void ) +{ + glReportErrors("ValidateUserConfig"); + + // Copy config + InternalConfig = UserConfig; + + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "** OpenGL Information **\n" ); + const unsigned char* renderer = glGetString( GL_RENDERER ); + if (renderer == NULL || strlen(reinterpret_cast(renderer)) == 0) + { + GlideError("The OpenGL driver failed to report its version/vendor/renderer.\nThis may be caused by beta drivers located in thge game directory.\nThese drivers should be deleted.\n"); + } + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "Vendor: %s\n", glGetString( GL_VENDOR ) ); + GlideMsg( "Renderer: %s\n", glGetString( GL_RENDERER ) ); + GlideMsg( "Version: %s\n", glGetString( GL_VERSION ) ); + // Extension string is too long for the temp buffer, so we don't use GlideMsg() + UserConfig.write_log("Available Extensions: "); + UserConfig.write_log(reinterpret_cast(glGetString(GL_EXTENSIONS))); + UserConfig.write_log("\n"); + + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "OpenGL Extensions:\n" ); + GlideMsg( OGL_LOG_SEPARATE ); + int index = 0; + while ( strlen( glNecessaryExt[ index ].name ) > 0 ) + { + *glNecessaryExt[ index ].internalVar = false; + switch ( glNecessaryExt[ index ].type ) + { + case OGL_EXT_REQUIRED: + if ( ! OGLIsExtensionSupported( glNecessaryExt[ index ].name ) ) + { + char buffer[StringBufferSize]; + sprintf(buffer, "Severe Problem: OpenGL %s extension is required for %s!", + glNecessaryExt[ index ].name, OpenGLideProductName); + GlideError(buffer); + } + break; + + case OGL_EXT_DESIRED: + if ( ! OGLIsExtensionSupported( glNecessaryExt[ index ].name ) ) + { + char buffer[StringBufferSize]; + sprintf(buffer, "Note: OpenGL %s extension is not supported, emulating behavior.\n", + glNecessaryExt[ index ].name ); + GlideMsg(buffer); + } + else + { + if ( *glNecessaryExt[ index ].userVar ) + { + *glNecessaryExt[ index ].internalVar = true; + GlideMsg( "Extension %s is present and ENABLED\n", glNecessaryExt[ index ].name ); + } + else + { + char buffer[StringBufferSize]; + sprintf(buffer, "Note: OpenGL %s extension is supported but disabled by user\n", + glNecessaryExt[ index ].name ); + GlideMsg(buffer); + } + } + break; + + case OGL_EXT_UNUSED: + break; + } + ++index; + } + GlideMsg( OGL_LOG_SEPARATE ); + GLExtensions( ); + + // Rendering quality seems to be better when this is left enabled for depth buffer size < 24 bits only + // (Try spinning around at the portal in the first level of Tomb Raider Gold) + GLint depthbufferbits; + glGetIntegerv(GL_DEPTH_BITS, &depthbufferbits); + glReportError(); + if (depthbufferbits >= 24 && InternalConfig.PrecisionFix == 1) + { + GlideMsg("Actual number of depthbuffer bits is %d - precision fix can safely be disabled\n", depthbufferbits); + InternalConfig.PrecisionFix = 0; + } +} + +void GLExtensions(void) +{ + glReportErrors("GLExtensions"); + float one = 1.0f; + + #ifdef OPENGLIDE_HOST_MAC + RunningInClassic = strstr(reinterpret_cast(glGetString(GL_EXTENSIONS)), "GL_EXT_fog_coord") != NULL; + #endif + + // query the actual buffer size + GLint size; + glGetIntegerv(GL_DEPTH_BITS, &size); + GlideMsg("Depthbuffer size = %d\n", size); + if (UserConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + glGetIntegerv(GL_STENCIL_BITS, &size); + GlideMsg("Stencilbuffer size = %d\n", size); + } + GLint MaxAnisotropyLevel; + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropyLevel); + GlideMsg("Maximum level of anisotropy = %d\n", MaxAnisotropyLevel); + + if (InternalConfig.EXT_texture_filter_anisotropic) + { + GLint MaxAnisotropyLevel; + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropyLevel); + if (UserConfig.AnisotropylLevel > MaxAnisotropyLevel) + { + InternalConfig.AnisotropylLevel = MaxAnisotropyLevel; + } + else + { + InternalConfig.AnisotropylLevel = UserConfig.AnisotropylLevel; + } + } + else + { + InternalConfig.AnisotropylLevel = 1; + } + + if (InternalConfig.ARB_multisample == false) + { + InternalConfig.FullSceneAntiAliasing = 0; + } + else if (InternalConfig.FullSceneAntiAliasing > 0) + { + // Thanks to Frank Condello for posting this trick at + // http://support.realsoftware.com/listarchives/realbasic-games/2004-09/msg00273.html + aglSetInteger(pWindowInfo->aglContext, AGL_ATI_FSAA_LEVEL, reinterpret_cast(&InternalConfig.FullSceneAntiAliasing)); + GLenum err = aglGetError(); + if (AGL_NO_ERROR != err) + { + GlideError("Couldn't set ATI FSAA level: %s\n", reinterpret_cast(aglErrorString(err))); + } + // Initially enable multisampling + glEnable(GL_MULTISAMPLE_ARB); + glReportError(); + } + if (InternalConfig.FullSceneAntiAliasing > 0 + && InternalConfig.NV_multisample_filter_hint) + { + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); + glReportError(); + } + +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + if (InternalConfig.EXT_fog_coord == false && InternalConfig.FogMode > OpenGLideFogEmulation_EnvCombine) + { + InternalConfig.FogMode = OpenGLideFogEmulation_EnvCombine; + } +#endif + + // FogCoord extension not supported on MacOS9 +#ifdef OPENGLIDE_SYSTEM_DOESN_T_HAVE_FOGCOORD + if (InternalConfig.FogMode > OpenGLideFogEmulation_EnvCombine) + { + InternalConfig.FogMode = OpenGLideFogEmulation_EnvCombine; + } +#endif + + // check for other extensions needed by fog emulation + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine + && InternalConfig.EXT_texture_env_combine == false) + { + GlideMsg( "Enhanced fog emulation disabled because GL_ARB_texture_env_combine is missing or disabled\n"); + InternalConfig.FogMode = OpenGLideFogEmulation_Simple; + } + else if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine + && InternalConfig.ARB_multitexture == false) + { + GlideMsg( "Enhanced fog emulation disabled because GL_ARB_multitexture is missing or disabled\n"); + InternalConfig.FogMode = OpenGLideFogEmulation_Simple; + } + + // Setup texture units + if (InternalConfig.GlideTextureUnits > 1) + { + GlideMsg( "Only one texure unit is currently supported. Additional units are ignored.\n"); + } + if (InternalConfig.ARB_multitexture) + { + GLint number_of_texture_units = 1; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &number_of_texture_units); + GlideMsg("MultiTexture Units = %x\n", number_of_texture_units); + if (InternalConfig.ColorAlphaRenderMode >= OpenGLideColorAlphaRenderMode_Unknown) + { + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Automatic; + } + if (InternalConfig.ColorAlphaRenderMode > OpenGLideColorAlphaRenderMode_Simple + && InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine + && number_of_texture_units <= 2) + { + GlideMsg( "Coloralpha render mode reset to simple in favour of enhanced fog emulation\n"); + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple; + } + // Setup coloralpha texture units + OpenGL.ColorAlphaUnit1 = GL_TEXTURE0_ARB; + if ((number_of_texture_units > 2 && InternalConfig.EXT_texture_env_combine + || number_of_texture_units == 2 && InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine) + && (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_Automatic + || InternalConfig.ColorAlphaRenderMode > OpenGLideColorAlphaRenderMode_Simple)) + { + OpenGL.ColorAlphaUnit2 = GL_TEXTURE1_ARB; + OpenGL.FogTextureUnit = GL_TEXTURE2_ARB; + // All texture units are enabled all the time + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glEnable(GL_TEXTURE_2D); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glActiveTextureARB(OpenGL.ColorAlphaUnit2); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glReportError(); + // Secondary color not neded in the enhanced color alpha rendering model + InternalConfig.EXT_secondary_color = false; + if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_Automatic) + { + if (InternalConfig.ATI_texture_env_combine3) + { + // With GL_ATI_texture_env_combine3, more combine functions can be modeled as + // exactly as the original combine functions. They can also be rendered more + // often with one texture unit, which leaves more space for correct rendering + // of textures that use both chromakeying and alpha blending together. + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_EnvCombine3_ATI; + OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombine3ATI; + OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombine3ATI; + } + else if (InternalConfig.EXT_texture_env_combine) + { + // Standard setup, works with most graphics cards and provides accurate + // results in most cases + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_EnvCombine_ARB; + OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombineARB; + OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombineARB; + } + } + if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_EnvCombine3_ATI) + { + OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombine3ATI; + OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombine3ATI; + } + else if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_EnvCombine_ARB) + { + OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombineARB; + OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombineARB; + } + } + else + { + OpenGL.ColorAlphaUnit2 = 0; + OpenGL.FogTextureUnit = number_of_texture_units > 2 ? GL_TEXTURE2_ARB : GL_TEXTURE1_ARB; + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple; + } + } + else + { + OpenGL.ColorAlphaUnit1 = GL_TEXTURE0_ARB; + OpenGL.ColorAlphaUnit2 = 0; + OpenGL.FogTextureUnit = 0; + InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple; + } + + // Print out coloralpha render mode + char* coloralpharendermodename; + switch (InternalConfig.ColorAlphaRenderMode) + { + case OpenGLideColorAlphaRenderMode_Simple: + coloralpharendermodename = "MultiTextureSimple"; + break; + case OpenGLideColorAlphaRenderMode_EnvCombine_ARB: + coloralpharendermodename = "EnvironmentCombineARB"; + break; + case OpenGLideColorAlphaRenderMode_EnvCombine3_ATI: + coloralpharendermodename = "EnvironmentCombine3ATI"; + break; + default: + assert(false); + break; + } + GlideMsg( "Coloralpha rendermode = %s\n", coloralpharendermodename); + + if (OpenGL.FogTextureUnit == 0 && InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + InternalConfig.FogMode = OpenGLideFogEmulation_Simple; + } + + if (InternalConfig.EXT_secondary_color && OpenGL.ColorAlphaUnit2 == 0) + { + glEnable(GL_COLOR_SUM_EXT); + glReportError(); + } + + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + fogalpharamp = static_cast (AllocBuffer(256, 1)); + if (fogalpharamp) + { + for(unsigned int i = 0; i < 256; i++) + { + fogalpharamp[i] = 255 - i; + } + } + else + { + InternalConfig.FogMode = OpenGLideFogEmulation_Simple; + } + } + + if (OpenGL.ColorAlphaUnit2 || InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine) + { + glGenTextures(1, &OpenGL.DummyTextureName); + glPrioritizeTextures(1, &OpenGL.DummyTextureName, &one); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // GL_REPEAT would cause randomly + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // fogged triangles in the foreground + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (InternalConfig.AnisotropylLevel >= 2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &dummytexture); + glReportError(); + } + +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); + glFogf(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_START, 0.0f); + glFogf(GL_FOG_END, 1.0f); + glReportError(); + } + else +#endif + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + GrFog_t fogtable[GR_FOG_TABLE_SIZE]; + guFogGenerateLinear(fogtable, 0.0f, 1.0f); + grFogTable(fogtable); + GlideMsg( "Using env-combine fog emulation\n"); + // Setup fog texture unit + glActiveTextureARB(OpenGL.FogTextureUnit); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + // The color part is used for the fog function (see RenderUpdateState.cpp) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); + // The alpha is not blended with the fog alpha because this + // would also fog otherwise invisible parts of the texture + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glGenTextures(1, &fogtexturename); + glPrioritizeTextures(1, &fogtexturename, &one); + glBindTexture(GL_TEXTURE_2D, fogtexturename); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // GL_REPEAT would cause randomly + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // fogged triangles in the foreground + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (InternalConfig.AnisotropylLevel >= 2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 256, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, fogalpharamp); + glReportError(); + } + else if (InternalConfig.FogMode == OpenGLideFogEmulation_Simple) + { + // Provide a reasonable default for application that use fog, + // but don't set the fog table (like Carmageddon) + // Adjusted to camageddon Main Street Track (compared with Race Track Preview image) + // and to Coastal Carnage Track so that objects become colored right after they pop up + // when popup distance option is far (fog is set to black in this level) + + // This doesn't seem to work with MacOS9 OpenGL drivers (beasue of version < 1.3 ?). + // The whole scene is too dark. However, it works well in the Classic environment + // (which actually uses the OpenGL driver provided by MacOS X) + + // When the fog table is not set as below, the whole scene seems to be a little to dark, + // whereas when it's set, the foreground looks as brighht as in the software rendrerer. + + GrFog_t fogtable[GR_FOG_TABLE_SIZE]; + // The values below come from comparing screenshots between GeForce 2mx + // (MacOS X OpenGL 1.3 driver) and the software renderer version of Carmageddon + guFogGenerateLinear(fogtable, 0.9985f, 1.0f); + grFogTable(fogtable); + GlideMsg( "Using simple fog emulation\n"); + } + else + { + InternalConfig.FogMode = OpenGLideFogEmulation_None; + // These default values must be provied even if fog is + // disabled or the shadows in Carmageddon Splatpack, + // Meltdown Alley level will have the fog color + // (occures on MacOS 9, Nvidia OpenGL 1.22) + glFogf( GL_FOG_MODE, GL_LINEAR ); + glReportError(); + glFogf( GL_FOG_START, 1.0f ); + glReportError(); + glFogf( GL_FOG_END, 0.0f ); + glReportError(); + glDisable(GL_FOG); + GlideMsg( "Fog emulation disabled\n"); + } + + if (InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine && OpenGL.DummyTextureName && OpenGL.FogTextureUnit) + { + // Setup fog texture unit as inverter (for inverting the color alpha output) + glActiveTextureARB(OpenGL.FogTextureUnit); + glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName); + glEnable(GL_TEXTURE_2D); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + OpenGL.FogTextureUnitEnabledState = true; + } + else + { + OpenGL.FogTextureUnitEnabledState = false; + } + // End of texture unit setup + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + + if (InternalConfig.EXT_paletted_texture) + { + GlideMsg( "Using Palette Extension\n" ); + } + +#ifdef OPENGLIDE_HOST_MAC + if (InternalConfig.EXT_compiled_vertex_array) + { + // Compiled vertex array crashes on MacOS9 (at least on my system) + // so if anybody who would like to investigate this... + if (!RunningInClassic) + { + InternalConfig.EXT_compiled_vertex_array = false; + GlideMsg( "Compiled vertex arrays have been disabled (works in Classic only)\n" ); + } + } +#endif + + if (InternalConfig.TextureSmoothing) + { + OpenGL.MinFilterMode = InternalConfig.Mipmapping ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR; + OpenGL.MagFilterMode = GL_LINEAR; + } + + if (InternalConfig.EXT_clip_volume_hint) + { + GlideMsg("Using clip volume hint\n"); + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); + OpenGL.ClipVerticesEnabledState = false; + } + + if (InternalConfig.APPLE_transform_hint) + { + GlideMsg("Using apple transform hint\n"); + glHint(GL_TRANSFORM_HINT_APPLE, GL_NICEST); + } + + if (InternalConfig.EXT_SGIS_generate_mipmap) + { + GlideMsg("Using SGIS mipmap generation hint\n"); + glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +void GLExtensionsCleanup() +{ + // cleanup fog texture + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + if (fogalpharamp) + { + FreeBuffer(fogalpharamp); + glReportErrors("RenderFree"); + glDeleteTextures(1, &fogtexturename); + glReportError(); + } + } + if (OpenGL.DummyTextureName) + { + glDeleteTextures(1, &OpenGL.DummyTextureName); + } +} diff --git a/MacGLide/OpenGLide/GLRender.cpp b/MacGLide/OpenGLide/GLRender.cpp new file mode 100644 index 0000000..03e3f0e --- /dev/null +++ b/MacGLide/OpenGLide/GLRender.cpp @@ -0,0 +1,2631 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* implementation of the GLRender class +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideSettings.h" +#include "GLextensions.h" +#include "GLRender.h" +#include "GLRenderUpdateState.h" +#include "PGTexture.h" + + +// The functions for the color combine +ALPHAFACTORFUNCPROC AlphaFactorFunc; +COLORFACTORFUNCPROC ColorFactor3Func; +COLORFUNCTIONPROC ColorFunctionFunc; + +// Snapping constant +static const float vertex_snap_compare = 4096.0f; +static const float vertex_snap = float( 3L << 18 ); + +#define DEBUG_MIN_MAX( var, maxvar, minvar ) \ + if ( var > maxvar ) maxvar = var; \ + if ( var < minvar ) minvar = var; + +// Standard structs for the render +RenderStruct OGLRender; + +// Variables for the AddXXX functions +static TColorStruct Local, + Other, + CFactor; + +#ifdef OGL_DEBUG_GLIDE_COORDS + void GlideMsg(const GrVertex* v, float maxoow) + { + GlideMsg("vertex(x=%g,y=%g,ooz=%g,oow=%g)", v->x, v->y, v->ooz, v->oow); + GlideMsg(",tmu0(sow=%g,tow=%g,oow=%g)\n", v->tmuvtx[0].sow * maxoow, v->tmuvtx[0].tow * maxoow, v->tmuvtx[0].oow); + } +#endif + +#ifdef OGL_DEBUG_OPENGL_COORDS + void GlideMsg(TVertexStruct* v, TTextureStruct* t) + { + GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->ax, v->ay, v->az); + GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->as, t->at, t->aq, t->aoow); + GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->bx, v->by, v->bz); + GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->bs, t->bt, t->bq, t->boow); + GlideMsg(" glVertex(x=%g,y=%g,z=%g)", v->cx, v->cy, v->cz); + GlideMsg(", glTexture(s=%g,t=%g,q=%g,w=%g)\n", t->cs, t->ct, t->cq, t->coow); + } +#endif + +inline GLfloat precision_fix(GLfloat oow) +{ + const GLfloat w = 1.0f / oow; + return 8.9375f - (GLfloat( ( (*(FxU32 *)&w >> 11) & 0xFFFFF ) * D1OVER65536) ); +} + +void RenderInitialize( void ) +{ +#ifdef OGL_ALL + GlideMsg( "RenderInitialize()\n"); +#endif + glReportErrors("RenderInitialize"); + // initialise triagle buffers + OGLRender.NumberOfTriangles = 0; + OGLRender.TColor = (TColorStruct*) AllocBuffer( MAXTRIANGLES + 1, sizeof(TColorStruct)); + if (OpenGL.ColorAlphaUnit2 == 0) + { + // This must be initialiased even if the secondary color extension is absent + // (Because there are no additional checks later on) + OGLRender.TColor2 = (TColorStruct*) AllocBuffer( MAXTRIANGLES + 1, sizeof(TColorStruct)); + } + else + { + OGLRender.TColor2 = NULL; + } + OGLRender.TTexture = (TTextureStruct*) AllocBuffer( MAXTRIANGLES + 1, sizeof(TTextureStruct)); + OGLRender.TVertex = (TVertexStruct*) AllocBuffer( MAXTRIANGLES + 1, sizeof(TVertexStruct)); + OGLRender.TFog = (TFogStruct*) AllocBuffer( MAXTRIANGLES + 1, sizeof(TFogStruct)); + // Initialise compiled vertex arrays + OGLRender.BufferLocked = false; + OGLRender.BufferStart = 0; + OGLRender.BufferLockedStart = MAXTRIANGLES; + // fog is initially turned off + OGLRender.UseEnvCombineFog = false; + if (InternalConfig.EXT_compiled_vertex_array) + { + // Initialise to start at the first element of the buffer + glVertexPointer(3, GL_FLOAT, 4 * sizeof( GLfloat ), &OGLRender.TVertex[0]); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_FLOAT, 0, &OGLRender.TColor[0]); + glEnableClientState( GL_COLOR_ARRAY ); + glReportError(); + if (InternalConfig.EXT_secondary_color && OpenGL.ColorAlphaUnit2 == NULL) + { + glEnableClientState( GL_SECONDARY_COLOR_ARRAY_EXT ); + glSecondaryColorPointerEXT(3, GL_FLOAT, 4 * sizeof(GLfloat), &OGLRender.TColor2[0]); + glReportError(); + } + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, 0, &OGLRender.TTexture[0]); + glReportError(); + if (InternalConfig.ARB_multitexture + && (InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine + || OpenGL.FogTextureUnit > GL_TEXTURE1_ARB)) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, 0, &OGLRender.TTexture[0]); + // @todo: if uncommented causes alpha blended + // smoke in Carmaegeddon to disappear + // glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glReportError(); + } + // Setup as inverter only + if (InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + glActiveTextureARB(OpenGL.FogTextureUnit); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_FLOAT, 0, &OGLRender.TFog[0]); + glReportError(); + } +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordPointerEXT(1, GL_FLOAT, &OGLRender.TFog[0]); + glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT); + glReportError(); + } +#endif + if ( InternalConfig.ARB_multitexture || InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + } + +#ifdef OGL_DEBUG + OGLRender.FrameTriangles = 0; + OGLRender.MaxTriangles = 0; + OGLRender.MaxSequencedTriangles = 0; + OGLRender.OverallTriangles = 0; + OGLRender.OverallRenderTriangleCalls = 0; + OGLRender.OverallLines = 0; + OGLRender.OverallPoints = 0; + OGLRender.MinX = OGLRender.MinY = OGLRender.MinZ = OGLRender.MinW = 99999999.0f; + OGLRender.MaxX = OGLRender.MaxY = OGLRender.MaxZ = OGLRender.MaxW = -99999999.0f; + OGLRender.MinS = OGLRender.MinT = OGLRender.MinF = 99999999.0f; + OGLRender.MaxS = OGLRender.MaxT = OGLRender.MaxF = -99999999.0f; + + OGLRender.MinR = OGLRender.MinG = OGLRender.MinB = OGLRender.MinA = 99999999.0f; + OGLRender.MaxR = OGLRender.MaxG = OGLRender.MaxB = OGLRender.MaxA = -99999999.0f; +#endif +} + +// Shuts down the renderer and frees memory +void RenderFree( void ) +{ +#ifdef OGL_ALL + GlideMsg("RenderFree()\n"); +#endif + + // free triangle buffers + FreeBuffer(OGLRender.TColor); + if (OGLRender.TColor2) FreeBuffer(OGLRender.TColor2); + FreeBuffer(OGLRender.TTexture); + FreeBuffer(OGLRender.TVertex); + FreeBuffer(OGLRender.TFog); +} + +inline void RenderUnlockArrays() +{ + glReportErrors("RenderUnlockArrays"); + + if (OGLRender.BufferLocked) + { + glUnlockArraysEXT(); + glReportError(); + OGLRender.BufferLocked = false; + } +} + +void RenderDrawTriangles_ImmediateMode(bool use_two_tex) +{ + glReportErrors("RenderDrawTriangles_ImmediateMode"); + + if(!OpenGL.Blend && OpenGL.ChromaKey) + { + // Render only the color, not the alpha + glBegin( GL_TRIANGLES ); + int count = OGLRender.BufferStart + OGLRender.NumberOfTriangles; + for (int i = OGLRender.BufferStart; i < count; i++ ) + { + glColor3fv( &OGLRender.TColor[ i ].ar ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].ar ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &OGLRender.TTexture[ i ].as ); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].as); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].af); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].af ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].ax ); + + glColor3fv( &OGLRender.TColor[ i ].br ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].br ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &OGLRender.TTexture[ i ].bs ); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].bs); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].bf); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].bf ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].bx ); + + glColor3fv( &OGLRender.TColor[ i ].cr ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].cr ); + } + if (OpenGL.Texture) + { + glTexCoord4fv(&OGLRender.TTexture[ i ].cs); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB(OpenGL.ColorAlphaUnit2, &OGLRender.TTexture[ i ].cs); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB(OpenGL.FogTextureUnit, OGLRender.TFog[ i ].cf); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].cf ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].cx ); + } + glEnd( ); + glReportError(); + } + else + { + glBegin( GL_TRIANGLES ); + int count = OGLRender.BufferStart + OGLRender.NumberOfTriangles; + for (int i = OGLRender.BufferStart; i < count; i++ ) + { + glColor4fv( &OGLRender.TColor[ i ].ar ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].ar ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &OGLRender.TTexture[ i ].as ); + if (OpenGL.ColorAlphaUnit2 || use_two_tex ) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].as ); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].af ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].af ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].ax ); + + glColor4fv( &OGLRender.TColor[ i ].br ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].br ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &OGLRender.TTexture[ i ].bs ); + if (OpenGL.ColorAlphaUnit2 || use_two_tex ) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].bs ); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].bf ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].bf ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].bx ); + + glColor4fv( &OGLRender.TColor[ i ].cr ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &OGLRender.TColor2[ i ].cr ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &OGLRender.TTexture[ i ].cs ); + if (OpenGL.ColorAlphaUnit2 || use_two_tex ) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit1 + 1, &OGLRender.TTexture[ i ].cs ); + } + } + if (OpenGL.Fog) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, OGLRender.TFog[ i ].cf ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( OGLRender.TFog[ i ].cf ); + } + #endif + } + glVertex3fv( &OGLRender.TVertex[ i ].cx ); + } + glEnd( ); + glReportError(); + } +} + +inline GLfloat dist(GLfloat ax, GLfloat ay, GLfloat bx, GLfloat by) +{ + GLfloat ad = ax - bx; + GLfloat bd = ay - by; + return sqrt(ad * ad + bd * bd); +} + +inline void GapFix(const TVertexStruct* u, TVertexStruct* v, GLfloat p) +{ + // Enlarge the triangle by enlarging the incircle of the triangle by p. + // The enlarged triangle will close background pixel-gaps between landscape tiles + // as seen in TR1 & TR2. + // For p = 1.0, horizontal and vertical one-pixel wide gaps can be closed + // by drawing just lines, whereas for p > 1 the whole triangle must be repainted. + // (preperably with disabling zbuffer writes and drawing behind the original + // triangle with z=OpenGL.ZMin) + // Background: http://de.wikipedia.org/wiki/Inkreis + // Many thanks to Yves Edel for providing the mathematical background + // + // The incircle: + // let r=sqrt({(s-a)(s-b)(s-c)}/s) + // with + // s = (a+b+c)/2 + // Centre of the incircle: + // M = (aA+bB+cC) / (a+b+c) + // (with barycentric coordinates) + // New vertices of the triangle + // A' = A+(A-M)* p / r. + GLfloat a = dist(u->bx, u->by, u->cx, u->cy); + GLfloat b = dist(u->ax, u->ay, u->cx, u->cy); + GLfloat c = dist(u->ax, u->ay, u->bx, u->by); + GLfloat abc = a + b + c; + GLfloat s = abc / 2; + GLfloat r = sqrt( (s-a)*(s-b)*(s-c) / s ); + // Enlarge the radius by a factor derived from the avarage vertex depth + // As a result, triangles in the foreground must have a larger incircle than + // the ones in the background in order to apply the gapfix. + GLfloat zr; + if (InternalConfig.GapFix & OpenGLideGapFixFlag_DepthFactor) + { + GLfloat z; + if (InternalConfig.PrecisionFix == false && OpenGL.DepthBufferType == 0) + { + z = (precision_fix(u->az) + + precision_fix(u->bz) + + precision_fix(u->cz)) / 3.0f; + } + else + { + z= (u->az + u->bz + u->cz) / 3.0f; + } + // Now z is [0...1] and the precision fix has been applied in all cases, + // and the average z in TR1 is about 0.34 + // (and we can use the same depth factor regardless of the precision fix state) + zr = InternalConfig.GapFixDepthFactor * z; + } + else + { + zr = 1.0f; + } + // Filter artecfacts when rendering geometry in front of "holes", which means + // all fragments produced by glClear() and not painted over by other geometry + GLfloat r1 = InternalConfig.GapFixParam1; + GLfloat gs = InternalConfig.GapFixParam2; + GLfloat r2 = InternalConfig.GapFixParam3; + // Apply the gapfix: + // smaller z values allow smaller triangles to pass the gapfix test + OpenGLideGapFixFlags g = InternalConfig.GapFix; + if ( + ((g & OpenGLideGapFixFlag_IncircleOr) && + (r > r1 * zr || abc < gs * r)) + || ((g & OpenGLideGapFixFlag_IncircleAnd) && + (r > r1 * zr && abc < gs * r)) + // r1 > r2 or the formula will degenerate to r > r2 + || ((g & OpenGLideGapFixFlag_IncircleSecondRadius) && + ((r > r1 * zr || abc < gs * r) && r > r2 * zr)) + || ((g & OpenGLideGapFixFlag_VertexLengthSecondRadius) && + ((r > r1 * zr || max(a, max(b, c)) > gs) && r > r2 * zr)) + ) + { + GLfloat Mx = (a * u->ax + b * u->bx + c * u->cx) / abc; + GLfloat My = (a * u->ay + b * u->by + c * u->cy) / abc; + // Transform coordinates to fill the gaps + v->ax = u->ax + (u->ax - Mx) * p / r; + v->ay = u->ay + (u->ay - My) * p / r; + v->bx = u->bx + (u->bx - Mx) * p / r; + v->by = u->by + (u->by - My) * p / r; + v->cx = u->cx + (u->cx - Mx) * p / r; + v->cy = u->cy + (u->cy - My) * p / r; + } + else if (u != v) + { + *v = *u; + } +} + +void RenderDrawTriangles( void ) +{ + if ( ! OGLRender.NumberOfTriangles ) + { + return; + } + + glReportErrors("RenderDrawTriangles"); + #ifdef OGL_OPTIMISE_DEBUG + GlideMsg("RenderDrawTriangles(): %d\n", OGLRender.NumberOfTriangles); + #else + #ifdef OGL_ALL + GlideMsg( "RenderDrawTriangles()\n"); + #endif + #endif + + // Finish rendering + RenderUnlockArrays(); + s_Framebuffer.OnRenderDrawTriangles(); + // Update the state after processing the frame buffer because + // the framebuffer class might request state changes as well + // in order to restore the previous state + RenderUpdateState(); + bool use_two_tex = false; + if (OpenGL.Texture) + { + use_two_tex = Textures->MakeReady(&OGLRender.TTexture[OGLRender.BufferStart], OGLRender.NumberOfTriangles); + if (use_two_tex) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + } + + if (OGLRender.UseEnvCombineFog && OpenGL.Fog == false) + { + // Provide dummy coordinates when fog is turned off but + // the texture unit is on because of color/alpha inversion + int buffer_end = OGLRender.BufferStart + OGLRender.NumberOfTriangles; + for (int index = OGLRender.BufferStart; index < buffer_end; index++) + { + OGLRender.TFog[index].af = 0.0f; + OGLRender.TFog[index].bf = 0.0f; + OGLRender.TFog[index].cf = 0.0f; + } + } + + // Render the triangles + bool use_compiled_vertex_arrays = InternalConfig.EXT_compiled_vertex_array + // && OGLRender.NumberOfTriangles > 1 // Might be more optimal + ; + if (use_compiled_vertex_arrays) + { + // Remember the position of the currently locked buffer + OGLRender.BufferLockedStart = OGLRender.BufferStart; + // Continue rendering in next buffer + OGLRender.BufferStart += OGLRender.NumberOfTriangles; + // choose the largest buffer + if (OGLRender.BufferStart > MAXTRIANGLES / 2 + || OGLRender.BufferStart >= MAXTRIANGLES -1) + { + OGLRender.BufferStart = 0; + } + glLockArraysEXT(OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); + OGLRender.BufferLocked = true; + + GLint primitive; + // Test code to track down the parameters of rendered triangles + /* + if (true) + { + // Dust clouds in Carma (when breaking) + //if (OpenGL.ChromaKey && OpenGL.Blend) + // Sunglasses in Deux Ex + if (Glide.State.ColorCombineInvert) + { + primitive = GL_LINE_LOOP; + } + else + { + primitive = GL_TRIANGLES; + } + } + else */ + { + primitive = GL_TRIANGLES; + } + glDrawArrays(primitive, OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); + } + else + { + RenderDrawTriangles_ImmediateMode(use_two_tex); + } + + // Fill gaps? + if ((InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) && !OpenGL.Blend) + { + // Only in 3D scenery + if (OpenGL.DepthBufferWritting) + { + if (use_compiled_vertex_arrays) + { + RenderUnlockArrays(); + } + // Enlarge triangles to fill the gaps between tiles in TR1 & TR2 + int buffer_end = OGLRender.BufferLockedStart + OGLRender.NumberOfTriangles; + for (int index = OGLRender.BufferLockedStart; index < buffer_end; index++) + { + TVertexStruct* t = &OGLRender.TVertex[index]; + const GLfloat p = 1.0; + GapFix(t, t, p); + } + // Turn off z-buffer writes + // disable depth buffer because although the stencil buffer is used, + // gapfix striangles may be rendered first and end up in front of + // regular triangles + glDepthMask(false); + glDepthFunc(GL_EQUAL); + glDisable(GL_DEPTH_TEST); + glStencilFunc(GL_NOTEQUAL, 0x02, 0x03); + glStencilOp(GL_KEEP, GL_INCR, GL_INCR); + glReportError(); + if (use_compiled_vertex_arrays) + { + glLockArraysEXT(OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); + OGLRender.BufferLocked = true; + GLint primitive; + primitive = GL_TRIANGLES; + glDrawArrays(primitive, OGLRender.BufferLockedStart * 3, OGLRender.NumberOfTriangles * 3); + glReportError(); + } + else + { + RenderDrawTriangles_ImmediateMode(use_two_tex); + } + // restore previous state + glDepthMask(OpenGL.DepthBufferWritting); + glDepthFunc(OpenGL.DepthFunction); + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glEnable(GL_DEPTH_TEST); + } + glStencilFunc(GL_ALWAYS, 0x02, 0x03); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glReportError(); + } + } + + if ( use_two_tex ) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glDisable( GL_TEXTURE_2D ); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + +#ifdef OGL_DEBUG + if ( OGLRender.NumberOfTriangles > OGLRender.MaxSequencedTriangles ) + { + OGLRender.MaxSequencedTriangles = OGLRender.NumberOfTriangles; + } + OGLRender.OverallTriangles += OGLRender.NumberOfTriangles; + OGLRender.OverallRenderTriangleCalls++; +#endif + + OGLRender.NumberOfTriangles = 0; + s_Framebuffer.SetRenderBufferChanged(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +void RenderAddLine( const GrVertex *a, const GrVertex *b, bool unsnap ) +{ +#ifdef OGL_DEBUG + OGLRender.OverallLines++; +#endif +#ifdef OGL_ALL + GlideMsg( "RenderAddLine()\n"); +#endif + + glReportErrors("RenderAddLine"); + + // Peek to avoid updating the render state twice + if (OGLRender.NumberOfTriangles) + { + RenderDrawTriangles(); + } + else + { + // Finish rendering of last render buffer + RenderUnlockArrays(); + s_Framebuffer.OnRenderDrawTriangles(); + // Update the state after processing the frame buffer because + // the framebuffer class might request state changes as well + // in order to restore the previous state + RenderUpdateState(); + } + + TColorStruct* pC = &OGLRender.TColor[ MAXTRIANGLES ]; + TColorStruct* pC2; + if (OpenGL.ColorAlphaUnit2) + { + { + // Color + pC->ar = a->r * D1OVER255; + pC->ag = a->g * D1OVER255; + pC->ab = a->b * D1OVER255; + pC->br = b->r * D1OVER255; + pC->bg = b->g * D1OVER255; + pC->bb = b->b * D1OVER255; + } + // Alpha + if (Glide.State.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) + { + // @todo: find out whether z has to be divided by 255 or by 65535 + pC->aa = a->z * D1OVER255; + pC->ba = b->z * D1OVER255; + } + else + { + pC->aa = a->a * D1OVER255; + pC->ba = b->a * D1OVER255; + } + } + else + { + pC2 = &OGLRender.TColor2[ MAXTRIANGLES ]; + memset( pC2, 0, sizeof( TColorStruct ) ); + // Color Stuff, need to optimize it + if ( Glide.ALocal ) + { + switch ( Glide.State.AlphaLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.aa = a->a * D1OVER255; + Local.ba = b->a * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + Local.aa = Local.ba = OpenGL.ConstantColor[3]; + break; + + case GR_COMBINE_LOCAL_DEPTH: + Local.aa = a->z; + Local.ba = b->z; + break; + } + } + + if ( Glide.AOther ) + { + switch ( Glide.State.AlphaOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.aa = a->a * D1OVER255; + Other.ba = b->a * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + Other.aa = Other.ba = OpenGL.ConstantColor[3]; + break; + + case GR_COMBINE_OTHER_TEXTURE: + Other.aa = Other.ba = 1.0f; + break; + } + } + + if ( Glide.CLocal ) + { + switch ( Glide.State.ColorCombineLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.ar = a->r * D1OVER255; + Local.ag = a->g * D1OVER255; + Local.ab = a->b * D1OVER255; + Local.br = b->r * D1OVER255; + Local.bg = b->g * D1OVER255; + Local.bb = b->b * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Local.ar = Local.br = color[0]; + Local.ag = Local.bg = color[1]; + Local.ab = Local.bb = color[2]; + } + break; + } + } + + if ( Glide.COther ) + { + switch ( Glide.State.ColorCombineOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.ar = a->r * D1OVER255; + Other.ag = a->g * D1OVER255; + Other.ab = a->b * D1OVER255; + Other.br = b->r * D1OVER255; + Other.bg = b->g * D1OVER255; + Other.bb = b->b * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Other.ar = Other.br = color[0]; + Other.ag = Other.bg = color[1]; + Other.ab = Other.bb = color[2]; + } + break; + + case GR_COMBINE_OTHER_TEXTURE: + Other.ar = Other.ag = Other.ab = 1.0f; + Other.br = Other.bg = Other.bb = 1.0f; + break; + } + } + + switch ( Glide.State.ColorCombineFunction ) + { + case GR_COMBINE_FUNCTION_ZERO: + pC->ar = pC->ag = pC->ab = 0.0f; + pC->br = pC->bg = pC->bb = 0.0f; + break; + + case GR_COMBINE_FUNCTION_LOCAL: + pC->ar = Local.ar; + pC->ag = Local.ag; + pC->ab = Local.ab; + pC->br = Local.br; + pC->bg = Local.bg; + pC->bb = Local.bb; + break; + + case GR_COMBINE_FUNCTION_LOCAL_ALPHA: + pC->ar = pC->ag = pC->ab = Local.aa; + pC->br = pC->bg = pC->bb = Local.ba; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + pC->br = CFactor.br * Other.br; + pC->bg = CFactor.bg * Other.bg; + pC->bb = CFactor.bb * Other.bb; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + pC->br = CFactor.br * Other.br; + pC->bg = CFactor.bg * Other.bg; + pC->bb = CFactor.bb * Other.bb; + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + pC2->br = Local.br; + pC2->bg = Local.bg; + pC2->bb = Local.bb; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + pC->br = CFactor.br * Other.br; + pC->bg = CFactor.bg * Other.bg; + pC->bb = CFactor.bb * Other.bb; + pC2->ar = pC2->ag = pC2->ab = Local.aa; + pC2->br = pC2->bg = pC2->bb = Local.ba; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + pC->br = CFactor.br * (Other.br - Local.br); + pC->bg = CFactor.bg * (Other.bg - Local.bg); + pC->bb = CFactor.bb * (Other.bb - Local.bb); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = Local.ar; + pC->ag = Local.ag; + pC->ab = Local.ab; + pC->br = Local.br; + pC->bg = Local.bg; + pC->bb = Local.bb; + } + else + { + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + pC->br = CFactor.br * (Other.br - Local.br); + pC->bg = CFactor.bg * (Other.bg - Local.bg); + pC->bb = CFactor.bb * (Other.bb - Local.bb); + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + pC2->br = Local.br; + pC2->bg = Local.bg; + pC2->bb = Local.bb; + } + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = pC->ag = pC->ab = Local.aa; + pC->br = pC->bg = pC->bb = Local.ba; + } + else + { + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + pC->br = CFactor.br * (Other.br - Local.br); + pC->bg = CFactor.bg * (Other.bg - Local.bg); + pC->bb = CFactor.bb * (Other.bb - Local.bb); + pC2->ar = pC2->ag = pC2->ab = Local.aa; + pC2->br = pC2->bg = pC2->bb = Local.ba; + } + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = ( 1.0f - CFactor.ar ) * Local.ar; + pC->ag = ( 1.0f - CFactor.ag ) * Local.ag; + pC->ab = ( 1.0f - CFactor.ab ) * Local.ab; + pC->br = ( 1.0f - CFactor.br ) * Local.br; + pC->bg = ( 1.0f - CFactor.bg ) * Local.bg; + pC->bb = ( 1.0f - CFactor.bb ) * Local.bb; + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + pC2->br = Local.br; + pC2->bg = Local.bg; + pC2->bb = Local.bb; + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * -Local.ar; + pC->ag = CFactor.ag * -Local.ag; + pC->ab = CFactor.ab * -Local.ab; + pC->br = CFactor.br * -Local.br; + pC->bg = CFactor.bg * -Local.bg; + pC->bb = CFactor.bb * -Local.bb; + pC2->ar = pC2->ag = pC2->ab = Local.aa; + pC2->br = pC2->bg = pC2->bb = Local.ba; + break; + } + + switch ( Glide.State.AlphaFunction ) + { + case GR_COMBINE_FUNCTION_ZERO: + pC->aa = pC->ba = 0.0f; + break; + + case GR_COMBINE_FUNCTION_LOCAL: + case GR_COMBINE_FUNCTION_LOCAL_ALPHA: + pC->aa = Local.aa; + pC->ba = Local.ba; + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = ((1.0f - AlphaFactorFunc( Local.aa, Other.aa )) * Local.aa); + pC->ba = ((1.0f - AlphaFactorFunc( Local.ba, Other.ba )) * Local.ba); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa); + pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa); + pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba + Local.ba); + // pC2->aa = Local.aa; + // pC2->ba = Local.ba; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa )); + pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba )); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa); + pC->ba = (AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ) + Local.ba); + // pC2->aa = Local.aa; + // pC2->ba = Local.ba; + break; + } + + if (OpenGL.FogTextureUnit == 0) + { + if ( Glide.State.ColorCombineInvert ) + { + pC->ar = 1.0f - pC->ar - pC2->ar; + pC->ag = 1.0f - pC->ag - pC2->ag; + pC->ab = 1.0f - pC->ab - pC2->ab; + pC->br = 1.0f - pC->br - pC2->br; + pC->bg = 1.0f - pC->bg - pC2->bg; + pC->bb = 1.0f - pC->bb - pC2->bb; + pC2->ar = pC2->ag = pC2->ab = 0.0f; + pC2->br = pC2->bg = pC2->bb = 0.0f; + } + + if ( Glide.State.AlphaInvert ) + { + pC->aa = 1.0f - pC->aa - pC2->aa; + pC->ba = 1.0f - pC->ba - pC2->ba; + pC2->aa = pC2->ba = 0.0f; + } + } + } + + TVertexStruct* pV = &OGLRender.TVertex[ MAXTRIANGLES ]; + // Z-Buffering + if ( ( Glide.State.DepthBufferMode == GR_DEPTHBUFFER_DISABLE ) || + ( Glide.State.DepthBufferMode == GR_CMP_ALWAYS ) ) + { + pV->az = 0.0f; + pV->bz = 0.0f; + } + else + if ( OpenGL.DepthBufferType ) + { + pV->az = a->ooz * D1OVER65536; + pV->bz = b->ooz * D1OVER65536; + } + else + { + /* + * For silly values of oow, depth buffering doesn't + * seem to work, so map them to a sensible z. When + * games use these silly values, they probably don't + * use z buffering anyway. + */ + if ( a->oow > 1.0 ) + { + pV->az = pV->bz = 0.9f; + } + else + if ( InternalConfig.PrecisionFix ) + { + pV->az = precision_fix(a->oow); + pV->bz = precision_fix(b->oow); + } + else + { + pV->az = a->oow; + pV->bz = b->oow; + } + } + + if ( ( unsnap ) && + ( a->x > vertex_snap_compare ) ) + { + pV->ax = a->x - vertex_snap; + pV->ay = a->y - vertex_snap; + pV->bx = b->x - vertex_snap; + pV->by = b->y - vertex_snap; + } + else + { + pV->ax = a->x; + pV->ay = a->y; + pV->bx = b->x; + pV->by = b->y; + } + + TTextureStruct* pTS; + pTS = &OGLRender.TTexture[MAXTRIANGLES]; + if ( OpenGL.Texture ) + { + float hAspect = Textures->GetHAspect(); + float wAspect = Textures->GetWAspect(); + pTS->as = a->tmuvtx[0].sow * wAspect; + pTS->at = a->tmuvtx[0].tow * hAspect; + pTS->bs = b->tmuvtx[0].sow * wAspect; + pTS->bt = b->tmuvtx[0].tow * hAspect; + pTS->aq = 0.0f; + pTS->bq = 0.0f; + float register atmuoow; + float register btmuoow; + if ( ( Glide.State.STWHint & GR_STWHINT_W_DIFF_TMU0 ) == 0 ) + { + atmuoow = a->oow; + btmuoow = b->oow; + } + else + { + atmuoow = a->tmuvtx[ 0 ].oow; + btmuoow = b->tmuvtx[ 0 ].oow; + } + pTS->aoow = atmuoow; + pTS->boow = btmuoow; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, atmuoow); + GlideMsg(b, btmuoow); +#endif + } + else + { + // @todo: only for complex color alpha model (or at all?) + // Does a dummy texture target need texture coords + // if env combine doesn't select a texture source? + // (See also fog code below) + pTS->as = 0.0f; + pTS->at = 0.0f; + pTS->bs = 0.0f; + pTS->bt = 0.0f; + pTS->aq = 0.0f; + pTS->bq = 0.0f; + pTS->aoow = 1.0; + pTS->boow = 1.0; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, 1.0f); + GlideMsg(b, 1.0f); +#endif + } + + TFogStruct* pF; + pF = &OGLRender.TFog[MAXTRIANGLES]; + if (Glide.State.FogMode) + { + float af, bf; + if (Glide.State.FogMode & GR_FOG_WITH_TABLE) + { + af = (float)OpenGL.FogTable[ (FxU16)(1.0f / a->oow) ] * D1OVER255; + bf = (float)OpenGL.FogTable[ (FxU16)(1.0f / b->oow) ] * D1OVER255; + } + else + { + af = a->a * D1OVER255; + bf = b->a * D1OVER255; + } + /* + if ( Glide.State.FogMode & GR_FOG_ADD2 ) + { + pF->af = 1.0f - af; + pF->bf = 1.0f - bf; + } + else + */ + { + pF->af = af; + pF->bf = bf; + } + +#ifdef OGL_DEBUG + DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); + DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); +#endif + } + else if (OGLRender.UseEnvCombineFog) + { + // Must provide dummy coords if fog is turned off but + // the texture unit is active because of inveting color/alpha + pF->af = pF->bf = 0.0; + } + +#ifdef OGL_DEBUG + DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); + DEBUG_MIN_MAX( pC->br, OGLRender.MaxR, OGLRender.MinR ); + + DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); + DEBUG_MIN_MAX( pC->bg, OGLRender.MaxG, OGLRender.MinG ); + + DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); + DEBUG_MIN_MAX( pC->bb, OGLRender.MaxB, OGLRender.MinB ); + + DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); + DEBUG_MIN_MAX( pC->ba, OGLRender.MaxA, OGLRender.MinA ); + + DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); + DEBUG_MIN_MAX( pV->bz, OGLRender.MaxZ, OGLRender.MinZ ); + + DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); + DEBUG_MIN_MAX( pV->bx, OGLRender.MaxX, OGLRender.MinX ); + + DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); + DEBUG_MIN_MAX( pV->by, OGLRender.MaxY, OGLRender.MinY ); + + if (OpenGL.Texture) + { + DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); + DEBUG_MIN_MAX( pTS->bs, OGLRender.MaxS, OGLRender.MinS ); + + DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); + DEBUG_MIN_MAX( pTS->bt, OGLRender.MaxT, OGLRender.MinT ); + } +#endif + +#ifdef OGL_DEBUG_OPENGL_COORDS + GlideMsg(pV, pTS); +#endif + + RenderUpdateState(); + if (OpenGL.Texture) + { + Textures->MakeReady(); + } + + glBegin( GL_LINES ); + OpenGL.ChromaKey ? glColor3fv( &pC->ar ) : glColor4fv( &pC->ar ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &pC2->ar ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &pTS->as ); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->as ); + } + } + if (Glide.State.FogMode) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->af ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( pF->af ); + } + #endif + } + glVertex3fv( &pV->ax ); + + OpenGL.ChromaKey ? glColor3fv( &pC->br ) : glColor4fv( &pC->br ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &pC2->br ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &pTS->bs ); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->bs ); + } + } + if (Glide.State.FogMode) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->bf ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( pF->bf ); + } + #endif + } + glVertex3fv( &pV->bx ); + glEnd(); + glReportError(); + + s_Framebuffer.SetRenderBufferChanged(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +void RenderAddTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c, bool unsnap ) +{ + glReportErrors("RenderAddTriangle"); +#ifdef OGL_DEBUG + OGLRender.OverallTriangles++; +#endif + + int TriangleIndex = OGLRender.BufferStart + OGLRender.NumberOfTriangles ; + +#ifdef OGL_ALL + GlideMsg( "RenderAddTriangle(%d)\n", TriangleIndex); +#endif + + TColorStruct* pC = &OGLRender.TColor[TriangleIndex]; + TColorStruct* pC2; + if (OpenGL.ColorAlphaUnit2) + { + { + // Color + pC->ar = a->r * D1OVER255; + pC->ag = a->g * D1OVER255; + pC->ab = a->b * D1OVER255; + pC->br = b->r * D1OVER255; + pC->bg = b->g * D1OVER255; + pC->bb = b->b * D1OVER255; + pC->cr = c->r * D1OVER255; + pC->cg = c->g * D1OVER255; + pC->cb = c->b * D1OVER255; + } + // Alpha + if (Glide.State.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) + { + // @todo: find out whether z has to be divided by 255 or by 65535 + pC->aa = a->z * D1OVER255; + pC->ba = b->z * D1OVER255; + pC->ca = c->z * D1OVER255; + } + else + { + pC->aa = a->a * D1OVER255; + pC->ba = b->a * D1OVER255; + pC->ca = c->a * D1OVER255; + } + } + else + { + pC2 = &OGLRender.TColor2[ TriangleIndex ]; + memset( pC2, 0, sizeof( TColorStruct ) ); + if ( Glide.ALocal ) + { + switch ( Glide.State.AlphaLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.aa = a->a * D1OVER255; + Local.ba = b->a * D1OVER255; + Local.ca = c->a * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + Local.aa = Local.ba = Local.ca = OpenGL.ConstantColor[ 3 ]; + break; + + case GR_COMBINE_LOCAL_DEPTH: + Local.aa = a->z * D1OVER255; + Local.ba = b->z * D1OVER255; + Local.ca = c->z * D1OVER255; + break; + } + } + + if ( Glide.AOther ) + { + switch ( Glide.State.AlphaOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.aa = a->a * D1OVER255; + Other.ba = b->a * D1OVER255; + Other.ca = c->a * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + Other.aa = Other.ba = Other.ca = OpenGL.ConstantColor[ 3 ]; + break; + + case GR_COMBINE_OTHER_TEXTURE: + if ( OpenGL.Texture ) + { + Other.aa = Other.ba = Other.ca = 1.0f; + } + else + { + Other.aa = Other.ba = Other.ca = 0.0f; + } + break; + } + } + + if ( Glide.CLocal ) + { + switch ( Glide.State.ColorCombineLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.ar = a->r * D1OVER255; + Local.ag = a->g * D1OVER255; + Local.ab = a->b * D1OVER255; + Local.br = b->r * D1OVER255; + Local.bg = b->g * D1OVER255; + Local.bb = b->b * D1OVER255; + Local.cr = c->r * D1OVER255; + Local.cg = c->g * D1OVER255; + Local.cb = c->b * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Local.ar = Local.br = Local.cr = color[0]; + Local.ag = Local.bg = Local.cg = color[1]; + Local.ab = Local.bb = Local.cb = color[2]; + } + break; + } + } + + if ( Glide.COther ) + { + switch ( Glide.State.ColorCombineOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.ar = a->r * D1OVER255; + Other.ag = a->g * D1OVER255; + Other.ab = a->b * D1OVER255; + Other.br = b->r * D1OVER255; + Other.bg = b->g * D1OVER255; + Other.bb = b->b * D1OVER255; + Other.cr = c->r * D1OVER255; + Other.cg = c->g * D1OVER255; + Other.cb = c->b * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Other.ar = Other.br = Other.cr = color[0]; + Other.ag = Other.bg = Other.cg = color[1]; + Other.ab = Other.bb = Other.cb = color[2]; + } + break; + + case GR_COMBINE_OTHER_TEXTURE: + if ( OpenGL.Texture ) + { + Other.ar = Other.ag = Other.ab = 1.0f; + Other.br = Other.bg = Other.bb = 1.0f; + Other.cr = Other.cg = Other.cb = 1.0f; + } + else + { + Other.ar = Other.ag = Other.ab = 0.0f; + Other.br = Other.bg = Other.bb = 0.0f; + Other.cr = Other.cg = Other.cb = 0.0f; + } + break; + } + } + + ColorFunctionFunc( pC, pC2, &Local, &Other ); + + switch ( Glide.State.AlphaFunction ) + { + case GR_COMBINE_FUNCTION_ZERO: + pC->aa = pC->ba = pC->ca = 0.0f; + break; + + case GR_COMBINE_FUNCTION_LOCAL: + case GR_COMBINE_FUNCTION_LOCAL_ALPHA: + pC->aa = Local.aa; + pC->ba = Local.ba; + pC->ca = Local.ca; + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = ( 1.0f - AlphaFactorFunc( Local.aa, Other.aa ) ) * Local.aa; + pC->ba = ( 1.0f - AlphaFactorFunc( Local.ba, Other.ba ) ) * Local.ba; + pC->ca = ( 1.0f - AlphaFactorFunc( Local.ca, Other.ca ) ) * Local.ca; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa; + pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba; + pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * Other.ca; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa; + pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * Other.ba + Local.ba; + pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * Other.ca + Local.ca; + // pC2->aa = Local.aa; + // pC2->ba = Local.ba; + // pC2->ca = Local.ca; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ); + pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ); + pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * ( Other.ca - Local.ca ); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa; + pC->ba = AlphaFactorFunc( Local.ba, Other.ba ) * ( Other.ba - Local.ba ) + Local.ba; + pC->ca = AlphaFactorFunc( Local.ca, Other.ca ) * ( Other.ca - Local.ca ) + Local.ca; + // pC2->aa = Local.aa; + // pC2->ba = Local.ba; + // pC2->ca = Local.ca; + break; + } + + if (OpenGL.FogTextureUnit == 0) + { + if ( Glide.State.ColorCombineInvert ) + { + pC->ar = 1.0f - pC->ar - pC2->ar; + pC->ag = 1.0f - pC->ag - pC2->ag; + pC->ab = 1.0f - pC->ab - pC2->ab; + pC->br = 1.0f - pC->br - pC2->br; + pC->bg = 1.0f - pC->bg - pC2->bg; + pC->bb = 1.0f - pC->bb - pC2->bb; + pC->cr = 1.0f - pC->cr - pC2->cr; + pC->cg = 1.0f - pC->cg - pC2->cg; + pC->cb = 1.0f - pC->cb - pC2->cb; + pC2->ar = pC2->ag = pC2->ab = 0.0f; + pC2->br = pC2->bg = pC2->bb = 0.0f; + pC2->cr = pC2->cg = pC2->cb = 0.0f; + } + + if ( Glide.State.AlphaInvert ) + { + pC->aa = 1.0f - pC->aa - pC2->aa; + pC->ba = 1.0f - pC->ba - pC2->ba; + pC->ca = 1.0f - pC->ca - pC2->ca; + pC2->aa = pC2->ba = pC2->ca = 0.0f; + } + } + } + + TVertexStruct* pV = &OGLRender.TVertex[ TriangleIndex ]; + // Z-Buffering + if ( ( Glide.State.DepthBufferMode == GR_DEPTHBUFFER_DISABLE ) || + ( Glide.State.DepthFunction == GR_CMP_ALWAYS ) ) + { + pV->az = 0.0f; + pV->bz = 0.0f; + pV->cz = 0.0f; + } + else + if ( OpenGL.DepthBufferType ) + { + pV->az = a->ooz * D1OVER65536; + pV->bz = b->ooz * D1OVER65536; + pV->cz = c->ooz * D1OVER65536; + } + else + { + // + // For silly values of oow, depth buffering doesn't + // seem to work, so map them to a sensible z. When + // games use these silly values, they probably don't + // use z buffering anyway. + // + if ( a->oow > 1.0 ) + { + pV->az = pV->bz = pV->cz = 0.9f; + } + else + if ( InternalConfig.PrecisionFix ) + { + pV->az = precision_fix(a->oow); + pV->bz = precision_fix(b->oow); + pV->cz = precision_fix(c->oow); + } + else + { + pV->az = a->oow; + pV->bz = b->oow; + pV->cz = c->oow; + } + } + + if ( ( unsnap ) && + ( a->x > vertex_snap_compare ) ) + { + pV->ax = a->x - vertex_snap; + pV->ay = a->y - vertex_snap; + pV->bx = b->x - vertex_snap; + pV->by = b->y - vertex_snap; + pV->cx = c->x - vertex_snap; + pV->cy = c->y - vertex_snap; + } + else + { + pV->ax = a->x; + pV->ay = a->y; + pV->bx = b->x; + pV->by = b->y; + pV->cx = c->x; + pV->cy = c->y; + } + + TTextureStruct* pTS; + pTS = &OGLRender.TTexture[ TriangleIndex ]; + bool generate_subtextures; + if (OpenGL.Texture) + { + float atmuoow; + float btmuoow; + float ctmuoow; + if ( ( Glide.State.STWHint & GR_STWHINT_W_DIFF_TMU0 ) == 0 ) + { + atmuoow = a->oow; + btmuoow = b->oow; + ctmuoow = c->oow; + } + else + { + atmuoow = a->tmuvtx[ 0 ].oow; + btmuoow = b->tmuvtx[ 0 ].oow; + ctmuoow = c->tmuvtx[ 0 ].oow; + } + float maxoow = 1.0f / max( atmuoow, max( btmuoow, ctmuoow ) ); + generate_subtextures = InternalConfig.GenerateSubTextures && + OpenGL.SClampMode != GL_REPEAT && + OpenGL.TClampMode != GL_REPEAT; + if (generate_subtextures) + { + pTS->as = a->tmuvtx[ 0 ].sow / atmuoow; + pTS->at = a->tmuvtx[ 0 ].tow / atmuoow; + pTS->bs = b->tmuvtx[ 0 ].sow / btmuoow; + pTS->bt = b->tmuvtx[ 0 ].tow / btmuoow; + pTS->cs = c->tmuvtx[ 0 ].sow / ctmuoow; + pTS->ct = c->tmuvtx[ 0 ].tow / ctmuoow; + } + else + { + GLfloat hAspect = Textures->GetHAspect(); + GLfloat wAspect = Textures->GetWAspect(); + pTS->as = a->tmuvtx[ 0 ].sow * wAspect * maxoow; + pTS->at = a->tmuvtx[ 0 ].tow * hAspect * maxoow; + pTS->bs = b->tmuvtx[ 0 ].sow * wAspect * maxoow; + pTS->bt = b->tmuvtx[ 0 ].tow * hAspect * maxoow; + pTS->cs = c->tmuvtx[ 0 ].sow * wAspect * maxoow; + pTS->ct = c->tmuvtx[ 0 ].tow * hAspect * maxoow; + } + pTS->aq = 0.0f; + pTS->bq = 0.0f; + pTS->cq = 0.0f; + pTS->aoow = atmuoow * maxoow; + pTS->boow = btmuoow * maxoow; + pTS->coow = ctmuoow * maxoow; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, maxoow); + GlideMsg(b, maxoow); + GlideMsg(c, maxoow); +#endif + } + else + { + // @todo: only for complex color alpha model (or at all?) + // Does a dummy texture target need texture coords + // if env combine doesn't select a texture source? + // (See also fog code below) + pTS->as = 0.0f; + pTS->at = 0.0f; + pTS->bs = 0.0f; + pTS->bt = 0.0f; + pTS->cs = 0.0f; + pTS->ct = 0.0f; + pTS->aq = 0.0f; + pTS->bq = 0.0f; + pTS->cq = 0.0f; + pTS->aoow = 1.0; + pTS->boow = 1.0; + pTS->coow = 1.0; + generate_subtextures = false; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, 1.0f); + GlideMsg(b, 1.0f); + GlideMsg(c, 1.0f); +#endif + } + + TFogStruct* pF; + pF = &OGLRender.TFog[TriangleIndex]; + if(Glide.State.FogMode) + { + float af, bf, cf; + if (Glide.State.FogMode & GR_FOG_WITH_TABLE) + { + af = (float)OpenGL.FogTable[ (FxU16)(1.0f / a->oow) ] * D1OVER255; + bf = (float)OpenGL.FogTable[ (FxU16)(1.0f / b->oow) ] * D1OVER255; + cf = (float)OpenGL.FogTable[ (FxU16)(1.0f / c->oow) ] * D1OVER255; + } + else + { + af = a->a * D1OVER255; + bf = b->a * D1OVER255; + cf = c->a * D1OVER255; + } + /* + if ( Glide.State.FogMode & GR_FOG_ADD2 ) + { + pF->af = 1.0f - af; + pF->bf = 1.0f - bf; + pF->cf = 1.0f - cf; + } + else + */ + { + pF->af = af; + pF->bf = bf; + pF->cf = cf; + } + +#ifdef OGL_DEBUG + DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); + DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); + DEBUG_MIN_MAX( pF->bf, OGLRender.MaxF, OGLRender.MinF ); +#endif + } + +#ifdef OGL_DEBUG + DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); + DEBUG_MIN_MAX( pC->br, OGLRender.MaxR, OGLRender.MinR ); + DEBUG_MIN_MAX( pC->cr, OGLRender.MaxR, OGLRender.MinR ); + + DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); + DEBUG_MIN_MAX( pC->bg, OGLRender.MaxG, OGLRender.MinG ); + DEBUG_MIN_MAX( pC->cg, OGLRender.MaxG, OGLRender.MinG ); + + DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); + DEBUG_MIN_MAX( pC->bb, OGLRender.MaxB, OGLRender.MinB ); + DEBUG_MIN_MAX( pC->cb, OGLRender.MaxB, OGLRender.MinB ); + + DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); + DEBUG_MIN_MAX( pC->ba, OGLRender.MaxA, OGLRender.MinA ); + DEBUG_MIN_MAX( pC->ca, OGLRender.MaxA, OGLRender.MinA ); + + DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); + DEBUG_MIN_MAX( pV->bz, OGLRender.MaxZ, OGLRender.MinZ ); + DEBUG_MIN_MAX( pV->cz, OGLRender.MaxZ, OGLRender.MinZ ); + + DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); + DEBUG_MIN_MAX( pV->bx, OGLRender.MaxX, OGLRender.MinX ); + DEBUG_MIN_MAX( pV->cx, OGLRender.MaxX, OGLRender.MinX ); + + DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); + DEBUG_MIN_MAX( pV->by, OGLRender.MaxY, OGLRender.MinY ); + DEBUG_MIN_MAX( pV->cy, OGLRender.MaxY, OGLRender.MinY ); + + if (OpenGL.Texture) + { + DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); + DEBUG_MIN_MAX( pTS->bs, OGLRender.MaxS, OGLRender.MinS ); + DEBUG_MIN_MAX( pTS->cs, OGLRender.MaxS, OGLRender.MinS ); + + DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); + DEBUG_MIN_MAX( pTS->bt, OGLRender.MaxT, OGLRender.MinT ); + DEBUG_MIN_MAX( pTS->ct, OGLRender.MaxT, OGLRender.MinT ); + } + OGLRender.FrameTriangles++; +#endif + +#ifdef OGL_DEBUG_OPENGL_COORDS + GlideMsg(pV, pTS); +#endif + + OGLRender.NumberOfTriangles++; + if (generate_subtextures) + { + RenderDrawTriangles(); + } + else + { + // Check whether the current buffer is before the currently rendered buffer + if (OGLRender.BufferLocked + && OGLRender.BufferStart == 0 + && OGLRender.NumberOfTriangles >= OGLRender.BufferLockedStart) + { + // Finish drawing of current render buffer + RenderUnlockArrays(); + OGLRender.BufferLocked = false; + OGLRender.BufferLockedStart = MAXTRIANGLES; + // Continue filling the buffer + } + else if (OGLRender.BufferStart + OGLRender.NumberOfTriangles >= MAXTRIANGLES - 1) + { + RenderDrawTriangles(); + } + } +} + +void RenderAddPoint( const GrVertex *a, bool unsnap ) +{ +#ifdef OGL_DEBUG + OGLRender.OverallPoints++; +#endif +#ifdef OGL_ALL + GlideMsg( "RenderAddPoint()\n"); +#endif + + glReportErrors("RenderAddPoint"); + + // Peek to avoid updating the render state twice + if (OGLRender.NumberOfTriangles) + { + RenderDrawTriangles(); + } + else + { + // Finish rendering of last render buffer + RenderUnlockArrays(); + s_Framebuffer.OnRenderDrawTriangles(); + // Update the state after processing the frame buffer because + // the framebuffer class might request state changes as well + // in order to restore the previous state + RenderUpdateState(); + } + + TColorStruct* pC = &OGLRender.TColor[ MAXTRIANGLES ]; + TColorStruct* pC2; + if (OpenGL.ColorAlphaUnit2) + { + { + // Color + pC->ar = a->r * D1OVER255; + pC->ag = a->g * D1OVER255; + pC->ab = a->b * D1OVER255; + } + // Alpha + if (Glide.State.AlphaLocal == GR_COMBINE_LOCAL_DEPTH) + { + // @todo: find out whether z has to be divided by 255 or by 65535 + pC->aa = a->z * D1OVER255; + } + else + { + pC->aa = a->a * D1OVER255; + } + } + else + { + pC2 = &OGLRender.TColor2[ MAXTRIANGLES ]; + memset( pC2, 0, sizeof( TColorStruct ) ); + // Color Stuff, need to optimize it + if ( Glide.ALocal ) + { + switch ( Glide.State.AlphaLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.aa = a->a * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + Local.aa = OpenGL.ConstantColor[3]; + break; + + case GR_COMBINE_LOCAL_DEPTH: + Local.aa = a->z; + break; + } + } + + if ( Glide.AOther ) + { + switch ( Glide.State.AlphaOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.aa = a->a * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + Other.aa = OpenGL.ConstantColor[3]; + break; + + case GR_COMBINE_OTHER_TEXTURE: + Other.aa = 1.0f; + break; + } + } + + if ( Glide.CLocal ) + { + switch ( Glide.State.ColorCombineLocal ) + { + case GR_COMBINE_LOCAL_ITERATED: + Local.ar = a->r * D1OVER255; + Local.ag = a->g * D1OVER255; + Local.ab = a->b * D1OVER255; + break; + + case GR_COMBINE_LOCAL_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Local.ar = color[0]; + Local.ag = color[1]; + Local.ab = color[2]; + } + break; + } + } + + if ( Glide.COther ) + { + switch ( Glide.State.ColorCombineOther ) + { + case GR_COMBINE_OTHER_ITERATED: + Other.ar = a->r * D1OVER255; + Other.ag = a->g * D1OVER255; + Other.ab = a->b * D1OVER255; + break; + + case GR_COMBINE_OTHER_CONSTANT: + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + } + else + { + color = &OpenGL.ConstantColor[0]; + } + Other.ar = color[0]; + Other.ag = color[1]; + Other.ab = color[2]; + } + break; + + case GR_COMBINE_OTHER_TEXTURE: + Other.ar = Other.ag = Other.ab = 1.0f; + break; + } + } + + switch ( Glide.State.ColorCombineFunction ) + { + case GR_COMBINE_FUNCTION_ZERO: + pC->ar = pC->ag = pC->ab = 0.0f; + break; + + case GR_COMBINE_FUNCTION_LOCAL: + pC->ar = Local.ar; + pC->ag = Local.ag; + pC->ab = Local.ab; + break; + + case GR_COMBINE_FUNCTION_LOCAL_ALPHA: + pC->ar = pC->ag = pC->ab = Local.aa; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * Other.ar; + pC->ag = CFactor.ag * Other.ag; + pC->ab = CFactor.ab * Other.ab; + pC2->ar = pC2->ag = pC2->ab = Local.aa; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = Local.ar; + pC->ag = Local.ag; + pC->ab = Local.ab; + } + else + { + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + } + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = pC->ag = pC->ab = Local.aa; + } + else + { + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * (Other.ar - Local.ar); + pC->ag = CFactor.ag * (Other.ag - Local.ag); + pC->ab = CFactor.ab * (Other.ab - Local.ab); + pC2->ar = pC2->ag = pC2->ab = Local.aa; + } + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = ( 1.0f - CFactor.ar ) * Local.ar; + pC->ag = ( 1.0f - CFactor.ag ) * Local.ag; + pC->ab = ( 1.0f - CFactor.ab ) * Local.ab; + pC2->ar = Local.ar; + pC2->ag = Local.ag; + pC2->ab = Local.ab; + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: + ColorFactor3Func( &CFactor, &Local, &Other ); + pC->ar = CFactor.ar * -Local.ar; + pC->ag = CFactor.ag * -Local.ag; + pC->ab = CFactor.ab * -Local.ab; + pC2->ar = pC2->ag = pC2->ab = Local.aa; + break; + } + + switch ( Glide.State.AlphaFunction ) + { + case GR_COMBINE_FUNCTION_ZERO: + pC->aa = 0.0f; + break; + + case GR_COMBINE_FUNCTION_LOCAL: + case GR_COMBINE_FUNCTION_LOCAL_ALPHA: + pC->aa = Local.aa; + break; + + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = ((1.0f - AlphaFactorFunc( Local.aa, Other.aa )) * Local.aa); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * Other.aa + Local.aa; +// pC2->aa = Local.aa; + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: + pC->aa = (AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa )); + break; + + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: + case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: + pC->aa = AlphaFactorFunc( Local.aa, Other.aa ) * ( Other.aa - Local.aa ) + Local.aa; +// pC2->aa = Local.aa; + break; + } + + if (OpenGL.FogTextureUnit == 0) + { + if ( Glide.State.ColorCombineInvert ) + { + pC->ar = 1.0f - pC->ar - pC2->ar; + pC->ag = 1.0f - pC->ag - pC2->ag; + pC->ab = 1.0f - pC->ab - pC2->ab; + pC2->ar = pC2->ag = pC2->ab = 0.0f; + } + + if ( Glide.State.AlphaInvert ) + { + pC->aa = 1.0f - pC->aa - pC2->aa; + pC2->aa = 0.0f; + } + } + } + + TVertexStruct* pV = &OGLRender.TVertex[ MAXTRIANGLES ]; + // Z-Buffering + if ( ( Glide.State.DepthBufferMode == GR_DEPTHBUFFER_DISABLE ) || + ( Glide.State.DepthBufferMode == GR_CMP_ALWAYS ) ) + { + pV->az = 0.0f; + } + else + if ( OpenGL.DepthBufferType ) + { + pV->az = a->ooz * D1OVER65536; + } + else + { + // + // For silly values of oow, depth buffering doesn't + // seem to work, so map them to a sensible z. When + // games use these silly values, they probably don't + // use z buffering anyway. + // + if ( a->oow > 1.0 ) + { + pV->az = 0.9f; + } + else + if ( InternalConfig.PrecisionFix ) + { + pV->az = precision_fix(a->oow); + } + else + { + pV->az = a->oow; + } + } + + if ( ( unsnap ) && + ( a->x > vertex_snap_compare ) ) + { + pV->ax = a->x - vertex_snap; + pV->ay = a->y - vertex_snap; + } + else + { + pV->ax = a->x; + pV->ay = a->y; + } + + TTextureStruct* pTS; + pTS = &OGLRender.TTexture[MAXTRIANGLES]; + if ( OpenGL.Texture ) + { + pTS->as = a->tmuvtx[0].sow * Textures->GetWAspect(); + pTS->at = a->tmuvtx[0].tow * Textures->GetHAspect(); + pTS->aq = 0.0f; + pTS->aoow = a->oow; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, a->oow); +#endif + } + else + { + // @todo: only for complex color alpha model (or at all?) + // Does a dummy texture target need texture coords + // if env combine doesn't select a texture source? + // (See also fog code below) + pTS->as = 0.0f; + pTS->at = 0.0f; + pTS->aq = 0.0f; + pTS->aoow = 1.0; + +#ifdef OGL_DEBUG_GLIDE_COORDS + GlideMsg(a, 1.0f); +#endif + } + + TFogStruct* pF; + pF = &OGLRender.TFog[ MAXTRIANGLES ]; + if(Glide.State.FogMode) + { + float af; + if (Glide.State.FogMode & GR_FOG_WITH_TABLE) + { + af = (float)OpenGL.FogTable[ (FxU16)(1.0f / a->oow) ] * D1OVER255; + } + else + { + af = a->a * D1OVER255; + } + /* + if ( Glide.State.FogMode & GR_FOG_ADD2 ) + { + pF->af = 1.0f - af; + } + else + */ + { + pF->af = af; + } + + #ifdef OGL_DEBUG + DEBUG_MIN_MAX( pF->af, OGLRender.MaxF, OGLRender.MinF ); + #endif + } + else if (OGLRender.UseEnvCombineFog) + { + // Must provide dummy coords if fog is turned off but + // the texture unit is active because of inveting color/alpha + pF->af = 0.0; + } + +#ifdef OGL_DEBUG + DEBUG_MIN_MAX( pC->ar, OGLRender.MaxR, OGLRender.MinR ); + + DEBUG_MIN_MAX( pC->ag, OGLRender.MaxG, OGLRender.MinG ); + + DEBUG_MIN_MAX( pC->ab, OGLRender.MaxB, OGLRender.MinB ); + + DEBUG_MIN_MAX( pC->aa, OGLRender.MaxA, OGLRender.MinA ); + + DEBUG_MIN_MAX( pV->az, OGLRender.MaxZ, OGLRender.MinZ ); + + DEBUG_MIN_MAX( pV->ax, OGLRender.MaxX, OGLRender.MinX ); + + DEBUG_MIN_MAX( pV->ay, OGLRender.MaxY, OGLRender.MinY ); + + if (OpenGL.Texture) + { + DEBUG_MIN_MAX( pTS->as, OGLRender.MaxS, OGLRender.MinS ); + + DEBUG_MIN_MAX( pTS->at, OGLRender.MaxT, OGLRender.MinT ); + } +#endif + +#ifdef OGL_DEBUG_OPENGL_COORDS + GlideMsg(pV, pTS); +#endif + + RenderUpdateState(); + if (OpenGL.Texture) + { + Textures->MakeReady(); + } + + glBegin( GL_POINTS ); + OpenGL.ChromaKey ? glColor3fv( &pC->ar ) : glColor4fv( &pC->ar ); + if (InternalConfig.EXT_secondary_color) + { + glSecondaryColor3fvEXT( &pC2->ar ); + } + if (OpenGL.Texture) + { + glTexCoord4fv( &pTS->as ); + if (OpenGL.ColorAlphaUnit2) + { + glMultiTexCoord4fvARB( OpenGL.ColorAlphaUnit2, &pTS->as ); + } + } + if (Glide.State.FogMode) + { + if (OGLRender.UseEnvCombineFog) + { + glMultiTexCoord1fARB( OpenGL.FogTextureUnit, pF->af ); + } + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + else if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord) + { + glFogCoordfEXT( pF->af ); + } + #endif + } + glVertex3fv( &pV->ax ); + glEnd(); + glReportError(); + + s_Framebuffer.SetRenderBufferChanged(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +// Color Factor functions + +void __fastcall ColorFactor3Zero( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = 0.0f; + Result->br = Result->bg = Result->bb = 0.0f; + Result->cr = Result->cg = Result->cb = 0.0f; +} + +void __fastcall ColorFactor3Local( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = ColorComponent->ar; + Result->ag = ColorComponent->ag; + Result->ab = ColorComponent->ab; + Result->br = ColorComponent->br; + Result->bg = ColorComponent->bg; + Result->bb = ColorComponent->bb; + Result->cr = ColorComponent->cr; + Result->cg = ColorComponent->cg; + Result->cb = ColorComponent->cb; +} + +void __fastcall ColorFactor3OtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = OtherAlpha->aa; + Result->br = Result->bg = Result->bb = OtherAlpha->ba; + Result->cr = Result->cg = Result->cb = OtherAlpha->ca; +} + +void __fastcall ColorFactor3LocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = ColorComponent->aa; + Result->br = Result->bg = Result->bb = ColorComponent->ba; + Result->cr = Result->cg = Result->cb = ColorComponent->ca; +} + +void __fastcall ColorFactor3OneMinusLocal( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = 1.0f - ColorComponent->ar; + Result->ag = 1.0f - ColorComponent->ag; + Result->ab = 1.0f - ColorComponent->ab; + Result->br = 1.0f - ColorComponent->br; + Result->bg = 1.0f - ColorComponent->bg; + Result->bb = 1.0f - ColorComponent->bb; + Result->cr = 1.0f - ColorComponent->cr; + Result->cg = 1.0f - ColorComponent->cg; + Result->cb = 1.0f - ColorComponent->cb; +} + +void __fastcall ColorFactor3OneMinusOtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = 1.0f - OtherAlpha->aa; + Result->br = Result->bg = Result->bb = 1.0f - OtherAlpha->ba; + Result->cr = Result->cg = Result->cb = 1.0f - OtherAlpha->ca; +} + +void __fastcall ColorFactor3OneMinusLocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = 1.0f - ColorComponent->aa; + Result->br = Result->bg = Result->bb = 1.0f - ColorComponent->ba; + Result->cr = Result->cg = Result->cb = 1.0f - ColorComponent->ca; +} + +void __fastcall ColorFactor3One( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ) +{ + Result->ar = Result->ag = Result->ab = 1.0f; + Result->br = Result->bg = Result->bb = 1.0f; + Result->cr = Result->cg = Result->cb = 1.0f; +} + +// Alpha Factor functions + +float AlphaFactorZero( float LocalAlpha, float OtherAlpha ) +{ + return 0.0f; +} + +float AlphaFactorLocal( float LocalAlpha, float OtherAlpha ) +{ + return LocalAlpha; +} + +float AlphaFactorOther( float LocalAlpha, float OtherAlpha ) +{ + return OtherAlpha; +} + +float AlphaFactorOneMinusLocal( float LocalAlpha, float OtherAlpha ) +{ + return 1.0f - LocalAlpha; +} + +float AlphaFactorOneMinusOther( float LocalAlpha, float OtherAlpha ) +{ + return 1.0f - OtherAlpha; +} + +float AlphaFactorOne( float LocalAlpha, float OtherAlpha ) +{ + return 1.0f; +} + +// Color functions + +void ColorFunctionZero( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + pC->ar = pC->ag = pC->ab = 0.0f; + pC->br = pC->bg = pC->bb = 0.0f; + pC->cr = pC->cg = pC->cb = 0.0f; +} + +void ColorFunctionLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + pC->ar = Local->ar; + pC->ag = Local->ag; + pC->ab = Local->ab; + pC->br = Local->br; + pC->bg = Local->bg; + pC->bb = Local->bb; + pC->cr = Local->cr; + pC->cg = Local->cg; + pC->cb = Local->cb; +} + +void ColorFunctionLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + pC->ar = pC->ag = pC->ab = Local->aa; + pC->br = pC->bg = pC->bb = Local->ba; + pC->cr = pC->cg = pC->cb = Local->ca; +} + +void ColorFunctionScaleOther( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * Other->ar; + pC->ag = CFactor.ag * Other->ag; + pC->ab = CFactor.ab * Other->ab; + pC->br = CFactor.br * Other->br; + pC->bg = CFactor.bg * Other->bg; + pC->bb = CFactor.bb * Other->bb; + pC->cr = CFactor.cr * Other->cr; + pC->cg = CFactor.cg * Other->cg; + pC->cb = CFactor.cb * Other->cb; +} + +void ColorFunctionScaleOtherAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * Other->ar; + pC->ag = CFactor.ag * Other->ag; + pC->ab = CFactor.ab * Other->ab; + pC->br = CFactor.br * Other->br; + pC->bg = CFactor.bg * Other->bg; + pC->bb = CFactor.bb * Other->bb; + pC->cr = CFactor.cr * Other->cr; + pC->cg = CFactor.cg * Other->cg; + pC->cb = CFactor.cb * Other->cb; + pC2->ar = Local->ar; + pC2->ag = Local->ag; + pC2->ab = Local->ab; + pC2->br = Local->br; + pC2->bg = Local->bg; + pC2->bb = Local->bb; + pC2->cr = Local->cr; + pC2->cg = Local->cg; + pC2->cb = Local->cb; +} + +void ColorFunctionScaleOtherAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * Other->ar; + pC->ag = CFactor.ag * Other->ag; + pC->ab = CFactor.ab * Other->ab; + pC->br = CFactor.br * Other->br; + pC->bg = CFactor.bg * Other->bg; + pC->bb = CFactor.bb * Other->bb; + pC->cr = CFactor.cr * Other->cr; + pC->cg = CFactor.cg * Other->cg; + pC->cb = CFactor.cb * Other->cb; + pC2->ar = pC2->ag = pC2->ab = Local->aa; + pC2->br = pC2->bg = pC2->bb = Local->ba; + pC2->cr = pC2->cg = pC2->cb = Local->ca; +} + +void ColorFunctionScaleOtherMinusLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * (Other->ar - Local->ar); + pC->ag = CFactor.ag * (Other->ag - Local->ag); + pC->ab = CFactor.ab * (Other->ab - Local->ab); + pC->br = CFactor.br * (Other->br - Local->br); + pC->bg = CFactor.bg * (Other->bg - Local->bg); + pC->bb = CFactor.bb * (Other->bb - Local->bb); + pC->cr = CFactor.cr * (Other->cr - Local->cr); + pC->cg = CFactor.cg * (Other->cg - Local->cg); + pC->cb = CFactor.cb * (Other->cb - Local->cb); +} + +void ColorFunctionScaleOtherMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = Local->ar; + pC->ag = Local->ag; + pC->ab = Local->ab; + pC->br = Local->br; + pC->bg = Local->bg; + pC->bb = Local->bb; + pC->cr = Local->cr; + pC->cg = Local->cg; + pC->cb = Local->cb; + } + else + { + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * (Other->ar - Local->ar); + pC->ag = CFactor.ag * (Other->ag - Local->ag); + pC->ab = CFactor.ab * (Other->ab - Local->ab); + pC->br = CFactor.br * (Other->br - Local->br); + pC->bg = CFactor.bg * (Other->bg - Local->bg); + pC->bb = CFactor.bb * (Other->bb - Local->bb); + pC->cr = CFactor.cr * (Other->cr - Local->cr); + pC->cg = CFactor.cg * (Other->cg - Local->cg); + pC->cb = CFactor.cb * (Other->cb - Local->cb); + pC2->ar = Local->ar; + pC2->ag = Local->ag; + pC2->ab = Local->ab; + pC2->br = Local->br; + pC2->bg = Local->bg; + pC2->bb = Local->bb; + pC2->cr = Local->cr; + pC2->cg = Local->cg; + pC2->cb = Local->cb; + } +} + +void ColorFunctionScaleOtherMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + if ((( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) || + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB )) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + pC->ar = pC->ag = pC->ab = Local->aa; + pC->br = pC->bg = pC->bb = Local->ba; + pC->cr = pC->cg = pC->cb = Local->ca; + } + else + { + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * (Other->ar - Local->ar); + pC->ag = CFactor.ag * (Other->ag - Local->ag); + pC->ab = CFactor.ab * (Other->ab - Local->ab); + pC->br = CFactor.br * (Other->br - Local->br); + pC->bg = CFactor.bg * (Other->bg - Local->bg); + pC->bb = CFactor.bb * (Other->bb - Local->bb); + pC->cr = CFactor.cr * (Other->cr - Local->cr); + pC->cg = CFactor.cg * (Other->cg - Local->cg); + pC->cb = CFactor.cb * (Other->cb - Local->cb); + pC2->ar = pC2->ag = pC2->ab = Local->aa; + pC2->br = pC2->bg = pC2->bb = Local->ba; + pC2->cr = pC2->cg = pC2->cb = Local->ca; + } +} + +void ColorFunctionMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = ( 1.0f - CFactor.ar ) * Local->ar; + pC->ag = ( 1.0f - CFactor.ag ) * Local->ag; + pC->ab = ( 1.0f - CFactor.ab ) * Local->ab; + pC->br = ( 1.0f - CFactor.br ) * Local->br; + pC->bg = ( 1.0f - CFactor.bg ) * Local->bg; + pC->bb = ( 1.0f - CFactor.bb ) * Local->bb; + pC->cr = ( 1.0f - CFactor.cr ) * Local->cr; + pC->cg = ( 1.0f - CFactor.cg ) * Local->cg; + pC->cb = ( 1.0f - CFactor.cb ) * Local->cb; + pC2->ar = Local->ar; + pC2->ag = Local->ag; + pC2->ab = Local->ab; + pC2->br = Local->br; + pC2->bg = Local->bg; + pC2->bb = Local->bb; + pC2->cr = Local->cr; + pC2->cg = Local->cg; + pC2->cb = Local->cb; +} + +void ColorFunctionMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ) +{ + ColorFactor3Func( &CFactor, Local, Other ); + pC->ar = CFactor.ar * -Local->ar; + pC->ag = CFactor.ag * -Local->ag; + pC->ab = CFactor.ab * -Local->ab; + pC->br = CFactor.br * -Local->br; + pC->bg = CFactor.bg * -Local->bg; + pC->bb = CFactor.bb * -Local->bb; + pC->cr = CFactor.cr * -Local->cr; + pC->cg = CFactor.cg * -Local->cg; + pC->cb = CFactor.cb * -Local->cb; + pC2->ar = pC2->ag = pC2->ab = Local->aa; + pC2->br = pC2->bg = pC2->bb = Local->ba; + pC2->cr = pC2->cg = pC2->cb = Local->ca; +} diff --git a/MacGLide/OpenGLide/GLRender.h b/MacGLide/OpenGLide/GLRender.h new file mode 100644 index 0000000..35f9403 --- /dev/null +++ b/MacGLide/OpenGLide/GLRender.h @@ -0,0 +1,159 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Render Header +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __GLRENDER_H__ +#define __GLRENDER_H__ + +//************************************************************** +// Defines +//************************************************************** + +#define MAXTRIANGLES 500 + + +//************************************************************** +// Structs +//************************************************************** + +struct GlVertex +{ + GLfloat x, y, z; + GLfloat s, t, q, oow; + GLfloat r, g, b, a; + GLfloat r2, g2, b2, a2; + GLfloat f; +}; + +struct Triangle +{ + GlVertex a, b, c; +}; + +struct ColorStruct +{ + GLfloat r, g, b, a; +}; + +struct TColorStruct +{ + GLfloat ar, ag, ab, aa; + GLfloat br, bg, bb, ba; + GLfloat cr, cg, cb, ca; +}; + +struct TVertexStruct +{ + GLfloat ax, ay, az, aw; + GLfloat bx, by, bz, bw; + GLfloat cx, cy, cz, cw; +}; + +struct TTextureStruct +{ + GLfloat as, at, aq, aoow; + GLfloat bs, bt, bq, boow; + GLfloat cs, ct, cq, coow; +}; + +struct TFogStruct +{ + GLfloat af; + GLfloat bf; + GLfloat cf; +}; + +struct RenderStruct +{ + TColorStruct *TColor; + TColorStruct *TColor2; + TVertexStruct *TVertex; + TTextureStruct *TTexture; + TFogStruct *TFog; + long NumberOfTriangles; + bool UseEnvCombineFog; + bool BufferLocked; + FxU32 BufferLockedStart; + FxU32 BufferStart; +#ifdef OGL_DEBUG + float MinX, MinY, MinZ, MinW; + float MaxX, MaxY, MaxZ, MaxW; + float MinS, MinT, MaxS, MaxT; + float MinR, MinG, MinB, MinA; + float MaxR, MaxG, MaxB, MaxA; + float MaxF, MinF; + unsigned long FrameTriangles, MaxTriangles, MaxSequencedTriangles; + unsigned long OverallTriangles, OverallRenderTriangleCalls; + unsigned long OverallLines; + unsigned long OverallPoints; + unsigned long OverallQuads; + unsigned long OverallPolygons; +#endif +}; + +typedef float (*ALPHAFACTORFUNCPROC)( float LocalAlpha, float OtherAlpha ); +typedef void (*COLORFACTORFUNCPROC)( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +typedef void (*COLORFUNCTIONPROC)( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); + +//************************************************************** +// Function Prototypes +//************************************************************** + +// Main Render functions +void RenderInitialize( void ); +void RenderFree( void ); +void RenderAddTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c, bool unsnap ); +void RenderAddLine( const GrVertex *a, const GrVertex *b, bool unsnap ); +void RenderAddPoint( const GrVertex *a, bool unsnap ); +void RenderDrawTriangles( void ); + +extern RenderStruct OGLRender; + +void RenderInitialize( void ); +void RenderFree( void ); + + +// Main Render variables +// extern RenderStruct OGLRender; +extern ALPHAFACTORFUNCPROC AlphaFactorFunc; +extern COLORFACTORFUNCPROC ColorFactor3Func; +extern COLORFUNCTIONPROC ColorFunctionFunc; + +// Prototypes for the color combining +float AlphaFactorZero( float LocalAlpha, float OtherAlpha ); +float AlphaFactorLocal( float LocalAlpha, float OtherAlpha ); +float AlphaFactorOther( float LocalAlpha, float OtherAlpha ); +float AlphaFactorOneMinusLocal( float LocalAlpha, float OtherAlpha ); +float AlphaFactorOneMinusOther( float LocalAlpha, float OtherAlpha ); +float AlphaFactorOne( float LocalAlpha, float OtherAlpha ); + +void ColorFactor3Zero( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3Local( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3LocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3OneMinusLocal( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3OneMinusLocalAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3OtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3OneMinusOtherAlpha( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); +void ColorFactor3One( TColorStruct *Result, const TColorStruct *ColorComponent, const TColorStruct *OtherAlpha ); + +void ColorFunctionZero( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOther( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOtherAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOtherAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOtherMinusLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOtherMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionScaleOtherMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionMinusLocalAddLocal( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); +void ColorFunctionMinusLocalAddLocalAlpha( TColorStruct * pC, TColorStruct * pC2, const TColorStruct * Local, const TColorStruct * Other ); + +#endif \ No newline at end of file diff --git a/MacGLide/OpenGLide/GLRenderUpdateState.cpp b/MacGLide/OpenGLide/GLRenderUpdateState.cpp new file mode 100644 index 0000000..06f2446 --- /dev/null +++ b/MacGLide/OpenGLide/GLRenderUpdateState.cpp @@ -0,0 +1,1592 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* update the GL state before rendering vertices +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideSettings.h" +#include "GLColorAlphaCombineEnvTables.h" +#include "GLRender.h" +#include "GLRenderUpdateState.h" + +struct +{ + GrChromakeyMode_t ChromaKeyMode; +} OldGlideState = +{ + GR_CHROMAKEY_DISABLE, +}; + +bool s_bUpdateTextureState = false; +bool s_bUpdateFogModeState = false; +bool s_bUpdateFogColorState = false; +bool s_bUpdateBlendState = false; +bool s_bUpdateChromaKeyAndAlphaState = false; +bool s_bUpdateColorCombineState = false; +bool s_bUpdateAlphaCombineState = false; +bool s_bUpdateColorInvertState = false; +bool s_bUpdateAlphaInvertState = false; +bool s_bUpdateConstantColorValueState = false; +bool s_bUpdateConstantColorValue4State = false; + +bool s_bForceChromaKeyAndAlphaStateUpdate = false; + +/* +inline void SetTextureState_update() +{ + glReportErrors("SetTextureState_update"); + + if (OpenGL.ColorAlphaUnit2 == 0) + { + if (OpenGL.Texture) + { + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + else + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + glDisable(GL_TEXTURE_2D); + } + glReportError(); + } + else + { + // If no texture is used, TMU0 provides 0 + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + if (OpenGL.Texture == false) + { + glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName); + glReportError(); + } + if (OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]) + { + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + glReportError(); + } + else + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + glDisable(GL_TEXTURE_2D); + glReportError(); + } + } +#ifdef OPENGL_DEBUG + for(long unit_index = 0; unit_index < 2; unit_index++) + { + GlideMsg( "OpenGL.ColorAlphaUnitColorEnabledState[%d] = %d\n", unit_index, OpenGL.ColorAlphaUnitColorEnabledState[unit_index]); + GlideMsg( "OpenGL.ColorAlphaUnitAlphaEnabledState[%d] = %d\n", unit_index, OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]); + GlideMsg("Texture unit GL_TEXTURE%d_ARB ", unit_index, GL_TEXTURE0_ARB + unit_index); + if (OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]) + { + GlideMsg("enabled\n"); + } + else + { + GlideMsg("disabled\n"); + } + } +#endif + } +} +*/ + +/* +// Setup color combine for extended color alpha model +inline void SetColorCombineState_update() +{ + glReportErrors("SetColorCombine_update"); + + GrCombineFunction_t function = Glide.State.ColorCombineFunction; + GrCombineFactor_t factor = Glide.State.ColorCombineFactor; + GrCombineLocal_t local = Glide.State.ColorCombineLocal; + GrCombineOther_t other = Glide.State.ColorCombineOther; + + if (OpenGL.ColorAlphaUnit2 == 0) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + if ( ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); + } + else + if ( ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); + } + else + if (InternalConfig.EXT_texture_env_add && + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_ONE ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) && + ( ( Glide.State.ColorCombineFunction == GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA ) || + ( Glide.State.ColorCombineFunction == GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL ) ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); + } + else + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } + glReportError(); + } + else + { + // Reduce function for constant factors? + if (factor == GR_COMBINE_FACTOR_ZERO) + { + function = ColorCombineFunctionsFactorZero[function].ReducedTerm; + } + else if (factor == GR_COMBINE_FACTOR_ONE) + { + function = ColorCombineFunctionsFactorOne[function].ReducedTerm; + } + const CombineArgument** combine_argument = &OpenGL.ColorCombineArguments[0]; + combine_argument[CFARG_Local] = &ColorCombineLocals[local]; + combine_argument[CFARG_Other] = Glide.State.TextureCombineRGBInvert ? &ColorCombineOthersInverted[other] : &ColorCombineOthers[other]; + combine_argument[CFARG_LocalAlpha] = &AlphaCombineLocals[Glide.State.AlphaLocal]; + combine_argument[CFARG_OtherAlpha] = Glide.State.TextureCombineAInvert ? &AlphaCombineOthersInverted[Glide.State.AlphaOther] : &AlphaCombineOthers[Glide.State.AlphaOther]; + combine_argument[CFARG_Factor] = Glide.State.TextureCombineRGBInvert ? &ColorCombineFactorsInverted[factor] : &ColorCombineFactors[factor]; + GLint source; + GLint operand; + CombineFunctionColorAlphaArg arg; + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + // unit 2 has to be the next one after unit 1 + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + const CombineFunctionGLTextureUnit& unit = OpenGL.ColorCombineFunctions[function].ColorAlphaUnit[unit_index]; + if (unit.Function == CF_Unused) + { + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + glReportError(); + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = false; + } + else + { + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = true; + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, unit.Function); + glReportError(); + for(unsigned long arg_index = 0; arg_index < 3; arg_index++) + { + arg = unit.CombineArg[arg_index]; + if (arg < CFARG_None) + { + if (arg == CFARG_Factor); // || arg == CFARG_FactorAlpha) + { + if (combine_argument[arg]->Source < CFARG_None) + { + // Resolve factor to local/other: + // The factor source references to the local/other, + // which can be retrieved via the combine_argument[] array + source = combine_argument[combine_argument[arg]->Source]->Source; + // but the operand of the factor specifies already the + // correct component of the pixel (rgb or alpha) to be used. + // Example: if factor == GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + // then the other alpha in AlphaCombineOthers is GL_SRC_ALPHA + // but the factor operand is correctly GL_ONE_MINUS_SRC_ALPHA. + operand = combine_argument[arg]->Operand; + // operand = combine_argument[combine_argument[arg]->Source]->Operand; // No + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else + { + // combinearg = local or other (alpha) + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else if (arg > CFARG_None) + { + source = unit.CombineArg[arg_index]; + operand = GL_SRC_COLOR; + } + else + { + // arg == CFARG_None -> argument not used + continue; + } + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + arg_index, source); + glReportError(); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + arg_index, operand); + glReportError(); + } + } + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/* +// Setup alpha combine for extended color alpha model +inline void SetAlphaCombineState_update() +{ + glReportErrors("SetAlphaCombine_update"); + + if (OpenGL.ColorAlphaUnit2 == 0) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + else + { + // Handle chromakey special case + if (OpenGL.ChromaKey && OpenGL.Texture && !OpenGL.Blend) + { + // need to disable alpha combining until an additional + // texture unit can be used to mask out the chroma key color. + // Note that the second unit must be setup because the + // texture unit might be turned on due to the color setup. + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + OpenGL.ColorAlphaUnitAlphaEnabledState[0] = true; + OpenGL.ColorAlphaUnitAlphaEnabledState[1] = false; + } + else + { + GrCombineFunction_t function = Glide.State.AlphaFunction; + GrCombineFactor_t factor = Glide.State.AlphaFactor; + GrCombineLocal_t local = Glide.State.AlphaLocal; + GrCombineOther_t other = Glide.State.AlphaOther; + // Reduce function for constant factors? + if (factor == GR_COMBINE_FACTOR_ZERO) + { + function = AlphaCombineFunctionsFactorZero[function].ReducedTerm; + } + else if (factor == GR_COMBINE_FACTOR_ONE) + { + function = AlphaCombineFunctionsFactorOne[function].ReducedTerm; + } + const CombineArgument** combine_argument = &OpenGL.AlphaCombineArguments[0]; + // @todo: colors are unused, aren't they? + combine_argument[CFARG_Local] = &ColorCombineLocals[local]; + combine_argument[CFARG_Other] = Glide.State.TextureCombineAInvert ? &ColorCombineOthersInverted[other] : &ColorCombineOthers[other]; + combine_argument[CFARG_LocalAlpha] = &AlphaCombineLocals[local]; + combine_argument[CFARG_OtherAlpha] = Glide.State.TextureCombineAInvert ? &AlphaCombineOthersInverted[other] : &AlphaCombineOthers[other]; + combine_argument[CFARG_Factor] = Glide.State.TextureCombineAInvert ? &AlphaCombineFactorsInverted[factor] : &AlphaCombineFactors[factor]; + GLint source; + GLint operand; + CombineFunctionColorAlphaArg arg; + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + // unit 2 must be the next one after unit 1 + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + CombineFunctionGLTextureUnit unit = OpenGL.AlphaCombineFunctions[function].ColorAlphaUnit[unit_index]; + if (unit.Function == CF_Unused) + { + if (OpenGL.ChromaKey && OpenGL.Texture && OpenGL.Blend) + { + // Modulate the alpha mask with the output of the previous unit + // to make chromakey-colored pixels invisible (so they wouldn't pass the alpha test) + // (chromakey-colored pixels have an alpha value of 0.0, the others 1.0) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + } + else + { + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; + } + } + else + { + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, unit.Function); + glReportError(); + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + for(unsigned long arg_index = 0; arg_index < 3; arg_index++) + { + arg = unit.CombineArg[arg_index]; + if (arg < CFARG_None) + { + if (arg == CFARG_Factor); // Alpha) + { + if (combine_argument[arg]->Source < CFARG_None) + { + // Resolve factor to local/other: + // The factor source references to local/other, + // which can be retrieved via the combine_argument[] array. + source = combine_argument[combine_argument[arg]->Source]->Source; + // but the operand of the factor specifies already which + // component of the pixel and how it should be used. + // Example: if factor == GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + // then the other alpha in AlphaCombineOthers is GL_SRC_ALPHA + // but the factor operand is correctly GL_ONE_MINUS_SRC_ALPHA. + operand = combine_argument[arg]->Operand; + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else if (arg > CFARG_None) + { + source = unit.CombineArg[arg_index]; + operand = GL_SRC_ALPHA; + } + else + { + // arg == CFARG_None -> argument not used + continue; + } + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + arg_index, source); + glReportError(); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + arg_index, operand); + glReportError(); + } + } + } + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/************************************************* + * Avoid setting blending, alpha and chromakeying + * each time triangles are rendered, May cause + * some overhead when the state is changed more + * than once but the effect is reduced by using + * the CHECK_STATE_CHANGED macro + ************************************************/ +inline void SetChromaKeyAndAlphaState_update() +{ + glReportErrors("SetChromaKeyAndAlpha_update"); + + // Setup alpha and chrma keying + // Chromakeying really works for textures only, and chroma keying + // without textures doesn't make sense anyway. + if(!OpenGL.Blend && OpenGL.ChromaKey && OpenGL.Texture) + { +#ifdef OPENGL_DEBUG + GlideMsg("Changing Chromakeymode state to enabled\n"); +#endif + // setup chroma keying + glAlphaFunc(GL_GEQUAL, 0.5); + glEnable(GL_ALPHA_TEST); + if (InternalConfig.EXT_compiled_vertex_array) + { + glColorPointer(3, GL_FLOAT, 4 * sizeof(GLfloat), &OGLRender.TColor[0]); + } + glReportError(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Changing Chromakeymode state to disabled\n"); +#endif + // Alpha Fix + // (todo: find out why this is a fix) + if (Glide.State.AlphaOther != GR_COMBINE_OTHER_TEXTURE) + { + glDisable(GL_ALPHA_TEST); + } + else + { + if ( Glide.State.AlphaTestFunction != GR_CMP_ALWAYS ) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(OpenGL.AlphaTestFunction, OpenGL.AlphaReferenceValue); + } + else + { + glDisable(GL_ALPHA_TEST); + } + } + if (InternalConfig.EXT_compiled_vertex_array) + { + glColorPointer(4, GL_FLOAT, 0, &OGLRender.TColor[0]); + } + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +/* +static const GLfloat ZeroColor[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; +inline void SetFogModeState_update() +{ + glReportErrors("SetFogMode_update"); + + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + glReportError(); + } + glActiveTextureARB(OpenGL.FogTextureUnit); + glReportError(); + if (Glide.State.FogMode & (GR_FOG_WITH_ITERATED_ALPHA | GR_FOG_WITH_TABLE)) + { + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_FLOAT, 0, &OGLRender.TFog[0]); + glReportError(); + } + OGLRender.UseEnvCombineFog = true; + // Now set the fog function + GrFogMode_t modeAdd = Glide.State.FogMode & (GR_FOG_MULT2 | GR_FOG_ADD2); + switch (modeAdd) + { + case GR_FOG_ADD2: + // Cout = (1 - f) * Cin + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR); + break; + case GR_FOG_MULT2: + // Cout = f * Cfog + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + break; + default: + // The usual blending + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); + break; + } + glReportError(); + } + else if (Glide.State.ColorCombineInvert || Glide.State.AlphaInvert) + { + // If the texture unit is turned on to invert color or alpha then we need to supply + // fog coords anyway and the combine function can still be GL_INTERPOLATE_EXT + // because the minimal fog value is chosen. However, choosing replace might + // save some vram memory access cycles + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_FLOAT, 0, &OGLRender.TFog[0]); + glReportError(); + } + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glReportError(); + OGLRender.UseEnvCombineFog = true; + } + else + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + // On MacOS9 (Classic?) the texcoord pointer needs to be reset + // to the default value when glLockArrays/glUnlockArrays is used + glTexCoordPointer( 4, GL_FLOAT, 0, NULL ); + glReportError(); + } + glDisable(GL_TEXTURE_2D); + // If the texture unit is disabled, the combine env function doesn't matter + OGLRender.UseEnvCombineFog = false; + } + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + else if (InternalConfig.FogMode != OpenGLideFogEmulation_None) + { + if (Glide.State.FogMode & (GR_FOG_WITH_ITERATED_ALPHA | GR_FOG_WITH_TABLE)) + { + glEnable(GL_FOG); + } + else + { + glDisable(GL_FOG); + } + glReportError(); + // Change the fog color in order to emulate the correct fog equation + // (Imperfect emulation) + GrFogMode_t modeAdd = Glide.State.FogMode & (GR_FOG_MULT2 | GR_FOG_ADD2); + switch (modeAdd) + { + case GR_FOG_MULT2: + case GR_FOG_ADD2: + glFogfv( GL_FOG_COLOR, &ZeroColor[0]); + glReportError(); + break; + default: + SetFogColorState(); + break; + } + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/* +inline void SetFogColorState_update() +{ + glReportErrors("SetFogColor_update"); + + if (Glide.State.FogMode < GR_FOG_MULT2) + { + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &OpenGL.FogColor[0]); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + else if (InternalConfig.FogMode != OpenGLideFogEmulation_None ) + { + glFogfv( GL_FOG_COLOR, &OpenGL.FogColor[0] ); + glReportError(); + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +inline void SetBlendState_update() +{ + glReportErrors("SetBlendState_update"); + +#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE + if (!InternalConfig.EXT_blend_func_separate) + { + glBlendFuncSeparateEXT(OpenGL.SrcBlend, OpenGL.DstBlend, + OpenGL.SrcAlphaBlend, OpenGL.DstAlphaBlend); + } + else + { +#endif + glBlendFunc(OpenGL.SrcBlend, OpenGL.DstBlend); +#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE + } +#endif + + if ( OpenGL.Blend ) + { +#ifdef OPENGL_DEBUG + GlideMsg("Changing Blend state to enabled\n"); +#endif + glEnable(GL_BLEND); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Changing Blend state to disabled\n"); +#endif + glDisable(GL_BLEND); + } + glReportError(); + + // I'd like to see this in the Set*() function, + // but it's more optimal placed here + #ifdef OPTIMISE_OPENGL_STATE_CHANGES + if (OpenGL.ChromaKey && OpenGL.Texture) + { + #endif + SetChromaKeyAndAlphaState(); + #ifdef OPTIMISE_OPENGL_STATE_CHANGES + } + else + { + SetAlphaCombineState(); + } + #endif + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +/* +void SetColorInvertState_update() +{ + glReportErrors("SetColorInvert_update"); + + // Setup color inversion on fog texture unit + if (OpenGL.FogTextureUnit) + { + FxBool invert = Glide.State.ColorCombineInvert; + glActiveTextureARB(OpenGL.FogTextureUnit); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, invert ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/* +void SetAlphaInvertState_update() +{ + glReportErrors("SetAlphaInvert_update"); + + // Setup alpha inversion on fog texture unit + if (OpenGL.FogTextureUnit) + { + FxBool invert = Glide.State.AlphaInvert; + glActiveTextureARB(OpenGL.FogTextureUnit); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, invert ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/* +void SetConstantColorValueState_update() +{ + glReportErrors("SetConstantColorState_update"); + + GLfloat* color; + if (Glide.State.Delta0Mode) + { + color = &OpenGL.Delta0Color[0]; + s_bUpdateConstantColorValue4State = false; + } + else + { + color = &OpenGL.ConstantColor[0]; + s_bUpdateConstantColorValueState = false; + } + +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL.ConstantColor=(%g, %g, %g, %g)\n", + color[0], + color[1], + color[2], + color[3]); +#endif + + if (OpenGL.ColorAlphaUnit2) + { + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color[0]); + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} +*/ + +/* +void RenderUpdateState_old() +{ + glReportErrors("RenderUpdateState"); + + // This filters out a few state changes in Carmageddon + // (changing chromakey mode is expensive) + if (OldGlideState.ChromaKeyMode != Glide.State.ChromaKeyMode) + { + OldGlideState.ChromaKeyMode = Glide.State.ChromaKeyMode; +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + if (!OpenGL.Blend) +#endif + SetChromaKeyAndAlphaState(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg( "Calls to grChromakeyMode() didn't change ChromaKeyAndAlphaState\n"); +#endif + } + + // Triggered by the frambuffer + if (s_bForceChromaKeyAndAlphaStateUpdate) + { + s_bForceChromaKeyAndAlphaStateUpdate = false; + SetChromaKeyAndAlphaState(); + } + + if (s_bUpdateFogModeState) + { + s_bUpdateFogModeState = false; + SetFogModeState_update(); + } + + if (s_bUpdateFogColorState) + { + s_bUpdateFogColorState = false; + SetFogColorState_update(); + } + + if (s_bUpdateBlendState) + { + s_bUpdateBlendState = false; + SetBlendState_update(); + } + + if (s_bUpdateChromaKeyAndAlphaState) + { + s_bUpdateChromaKeyAndAlphaState = false; + SetChromaKeyAndAlphaState_update(); + } + + if (s_bUpdateAlphaCombineState) + { + s_bUpdateAlphaCombineState = false; + SetAlphaCombineState_update(); + } + + if (s_bUpdateColorCombineState) + { + s_bUpdateColorCombineState = false; + SetColorCombineState_update(); + } + + if (s_bUpdateColorInvertState) + { + s_bUpdateColorInvertState = false; + SetColorInvertState_update(); + } + + if (s_bUpdateAlphaInvertState) + { + s_bUpdateAlphaInvertState = false; + SetAlphaInvertState_update(); + } + + if (s_bUpdateTextureState) + { + s_bUpdateTextureState = false; + SetTextureState_update(); + } + + if (s_bUpdateConstantColorValueState || s_bUpdateConstantColorValue4State) + { + SetConstantColorValueState_update(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); +} +*/ + +void RenderUpdateState() +{ + glReportErrors("RenderUpdateState"); + + // This filters out a few state changes in Carmageddon + // (changing chromakey mode is expensive) + if (OldGlideState.ChromaKeyMode != Glide.State.ChromaKeyMode) + { + OldGlideState.ChromaKeyMode = Glide.State.ChromaKeyMode; +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + if (!OpenGL.Blend) +#endif + SetChromaKeyAndAlphaState(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg( "Calls to grChromakeyMode() didn't change ChromaKeyAndAlphaState\n"); +#endif + } + + // Triggered by the framebuffer + if (s_bForceChromaKeyAndAlphaStateUpdate) + { + s_bForceChromaKeyAndAlphaStateUpdate = false; + SetChromaKeyAndAlphaState(); + } + + if (s_bUpdateBlendState) + { + s_bUpdateBlendState = false; + SetBlendState_update(); + } + + if (s_bUpdateChromaKeyAndAlphaState) + { + s_bUpdateChromaKeyAndAlphaState = false; + SetChromaKeyAndAlphaState_update(); + } + + bool active_texture_unit_not_coloralpha1 = false; + bool active_texture_unit_client_state_not_coloralpha1 = false; + if (s_bUpdateFogModeState || + s_bUpdateFogColorState || + s_bUpdateColorInvertState || + s_bUpdateAlphaInvertState) + { + if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine) + { + if (s_bUpdateFogModeState || s_bUpdateFogColorState) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + active_texture_unit_client_state_not_coloralpha1 = true; + } + active_texture_unit_not_coloralpha1 = true; + glReportError(); + } + + if (s_bUpdateFogModeState) + { + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.FogTextureUnit); + + s_bUpdateFogModeState = false; + if (Glide.State.FogMode & (GR_FOG_WITH_ITERATED_ALPHA | GR_FOG_WITH_TABLE)) + { + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_FLOAT, 0, &OGLRender.TFog[0]); + glReportError(); + } + OGLRender.UseEnvCombineFog = true; + // Now set the fog function + GrFogMode_t modeAdd = Glide.State.FogMode & (GR_FOG_MULT2 | GR_FOG_ADD2); + switch (modeAdd) + { + case GR_FOG_ADD2: + // Cout = (1 - f) * Cin + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR); + break; + case GR_FOG_MULT2: + // Cout = f * Cfog + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + break; + default: + // The usual blending + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); + break; + } + glReportError(); + } + else if (Glide.State.ColorCombineInvert || Glide.State.AlphaInvert) + { + // If the texture unit is turned on to invert color or alpha then we need to supply + // fog coords anyway and the combine function can still be GL_INTERPOLATE_EXT + // because the minimal fog value is chosen. However, choosing replace might + // save some vram memory access cycles + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(1, GL_FLOAT, 0, &OGLRender.TFog[0]); + glReportError(); + } + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glReportError(); + OGLRender.UseEnvCombineFog = true; + } + else + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + // On MacOS9 (Classic?) the texcoord pointer needs to be reset + // to the default value when glLockArrays/glUnlockArrays is used + glTexCoordPointer( 4, GL_FLOAT, 0, NULL ); + glReportError(); + } + glDisable(GL_TEXTURE_2D); + // If the texture unit is disabled, the combine env function doesn't matter + OGLRender.UseEnvCombineFog = false; + } + } + + // Fog Color + if (s_bUpdateFogColorState) + { + s_bUpdateFogColorState = false; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &OpenGL.FogColor[0]); + glReportError(); + } + } + else if (InternalConfig.FogMode != OpenGLideFogEmulation_None) + { + if (s_bUpdateFogModeState) + { + s_bUpdateFogModeState = false; + if (Glide.State.FogMode & (GR_FOG_WITH_ITERATED_ALPHA | GR_FOG_WITH_TABLE)) + { + glEnable(GL_FOG); + } + else + { + glDisable(GL_FOG); + } + glReportError(); + // Change the fog color in order to emulate the correct fog equation + // (Imperfect emulation) + static const GLfloat ZeroColor[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; + GrFogMode_t modeAdd = Glide.State.FogMode & (GR_FOG_MULT2 | GR_FOG_ADD2); + switch (modeAdd) + { + case GR_FOG_MULT2: + case GR_FOG_ADD2: + glFogfv( GL_FOG_COLOR, &ZeroColor[0]); + glReportError(); + break; + default: + SetFogColorState(); + break; + } + glReportError(); + } + + if (s_bUpdateFogColorState) + { + s_bUpdateFogColorState = false; + glFogfv(GL_FOG_COLOR, &OpenGL.FogColor[0]); + glReportError(); + } + } + + if (active_texture_unit_not_coloralpha1 == false && + (s_bUpdateColorInvertState || s_bUpdateAlphaInvertState)) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + active_texture_unit_client_state_not_coloralpha1 = true; + } + glReportError(); + active_texture_unit_not_coloralpha1 = true; + } + + if (s_bUpdateColorInvertState) + { + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.FogTextureUnit); + + s_bUpdateColorInvertState = false; + FxBool invert = Glide.State.ColorCombineInvert; + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, invert ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR); + } + + if (s_bUpdateAlphaInvertState) + { + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.FogTextureUnit); + + s_bUpdateAlphaInvertState = false; + FxBool invert = Glide.State.AlphaInvert; + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, invert ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA); + } + } + + // Coloralpha state changes + if (s_bUpdateTextureState || + s_bUpdateAlphaCombineState || + s_bUpdateColorCombineState || + s_bUpdateConstantColorValueState || + s_bUpdateConstantColorValue4State) + { + // Find out which texture units need to be setup + if (OpenGL.ColorAlphaUnit2) + { + // Reduce alpha combine function for constant factors + GrCombineFunction_t a_function = Glide.State.AlphaFunction; + const GrCombineFactor_t a_factor = Glide.State.AlphaFactor; + if (a_factor == GR_COMBINE_FACTOR_ZERO) + { + a_function = AlphaCombineFunctionsFactorZero[a_function].ReducedTerm; + } + else if (a_factor == GR_COMBINE_FACTOR_ONE) + { + a_function = AlphaCombineFunctionsFactorOne[a_function].ReducedTerm; + } + // Color + GrCombineFunction_t c_function = Glide.State.ColorCombineFunction; + const GrCombineFactor_t c_factor = Glide.State.ColorCombineFactor; + // Reduce color combine function for constant factors + if (c_factor == GR_COMBINE_FACTOR_ZERO) + { + c_function = ColorCombineFunctionsFactorZero[c_function].ReducedTerm; + } + else if (c_factor == GR_COMBINE_FACTOR_ONE) + { + c_function = ColorCombineFunctionsFactorOne[c_function].ReducedTerm; + } + // Determine which texture units must be enabled + bool enable_texture_unit[2]; + bool previously_enabled_texture_unit[2]; + // ColorCombine + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + // Remember last state because if a unit gets enabled, we have to update it's whole state + previously_enabled_texture_unit[unit_index] = OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]; + if (OpenGL.ColorCombineFunctions[c_function].ColorAlphaUnit[unit_index].Function == CF_Unused) + { + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = false; + } + else + { + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = true; + } + // AlphaCombine + if (OpenGL.ChromaKey && OpenGL.Texture && !OpenGL.Blend) + { + // OpenGL.ColorAlphaUnitAlphaEnabledState[0] = true; + // OpenGL.ColorAlphaUnitAlphaEnabledState[1] = false; + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = (unit_index == 0) ? true : false; + } + else + { + if (OpenGL.AlphaCombineFunctions[a_function].ColorAlphaUnit[unit_index].Function == CF_Unused) + { + if (OpenGL.ChromaKey && OpenGL.Texture && OpenGL.Blend) + { + // Modulate the alpha mask with the output of the previous unit + // to make chromakey-colored pixels invisible (so they wouldn't pass the alpha test) + // (chromakey-colored pixels have an alpha value of 0.0, the others 1.0) + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + } + else + { + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; + } + } + else + { + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + } + } + enable_texture_unit[unit_index] = OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]; + } +#ifdef OPENGL_DEBUG + for(long unit_index = 0; unit_index < 2; unit_index++) + { + GlideMsg( "OpenGL.ColorAlphaUnitColorEnabledState[%d] = %d\n", unit_index, OpenGL.ColorAlphaUnitColorEnabledState[unit_index]); + GlideMsg( "OpenGL.ColorAlphaUnitAlphaEnabledState[%d] = %d\n", unit_index, OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index]); + const char* enabled = OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] + ? "enabled" : "disabled"; + GlideMsg("Texture unit GL_TEXTURE%d_ARB = %s\n", unit_index, enabled); + } +#endif + // Loop through the texture units and set some state + // but reset the state change flags on the last iteration only + // (nothing is setup if both units are disabled, but then the + // state has to be set later on anyway) + bool reset_state = false; + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + if (!enable_texture_unit[unit_index]) + { + if (s_bUpdateTextureState) + { + if (reset_state) s_bUpdateTextureState = false; + // Update texture unit that has just been enabled? + if (!enable_texture_unit[unit_index] && previously_enabled_texture_unit[unit_index]) + { +#ifdef OPENGL_DEBUG + GlideMsg("Disabling unused texture unit GL_TEXTURE%d_ARB\n", unit_index); +#endif + // Save state changes if fog state hasn't been changed + // and only coloralpha texture unit 0 is used + const bool set_active_texture_unit = active_texture_unit_not_coloralpha1 || unit_index != 0; + if (set_active_texture_unit) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + if (InternalConfig.EXT_compiled_vertex_array) + { + if (set_active_texture_unit) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + active_texture_unit_client_state_not_coloralpha1 = (unit_index != 0); + } + active_texture_unit_not_coloralpha1 = (unit_index != 0); + glReportError(); + } + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1 + unit_index); + + glDisable(GL_TEXTURE_2D); + glReportError(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Unused texture unit GL_TEXTURE%d_ARB already disabled\n", unit_index); +#endif + } + } + } + else + { + // Save state changes if fog state hasn't been changed + // and only coloralpha texture unit 0 is used + const bool set_active_texture_unit = active_texture_unit_not_coloralpha1 || unit_index != 0; + if (set_active_texture_unit) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glReportError(); + active_texture_unit_not_coloralpha1 = (unit_index != 0); + } + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1 + unit_index); + + // Texture state + if (s_bUpdateTextureState) + { + if (reset_state) s_bUpdateTextureState = false; + // Update texture unit that has just been enabled? + if (enable_texture_unit[unit_index] && !previously_enabled_texture_unit[unit_index]) + { +#ifdef OPENGL_DEBUG + GlideMsg("Enabling texture unit GL_TEXTURE%d_ARB\n", unit_index); +#endif + // Enable the texture unit + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array && set_active_texture_unit) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + active_texture_unit_client_state_not_coloralpha1 = (unit_index != 0); + } + glReportError(); + // Update the texture unit + SetColorCombineState(); + SetAlphaCombineState(); + if (Glide.State.Delta0Mode) SetConstantColorValue4State(); + else SetConstantColorValueState(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Texture unit GL_TEXTURE%d_ARB already enabled\n", unit_index); +#endif + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1 + unit_index); + + // ColorCombineState + if (s_bUpdateColorCombineState) + { + if (reset_state) s_bUpdateColorCombineState = false; + const CombineFunctionGLTextureUnit& unit = OpenGL.ColorCombineFunctions[c_function].ColorAlphaUnit[unit_index]; + if (unit.Function == CF_Unused) + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL ColorCombine unit %d = unused\n", unit_index); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + glReportError(); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL ColorCombine Function for unit %d = 0x%x\n", unit_index, unit.Function); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, unit.Function); + glReportError(); + CombineFunctionColorAlphaArg arg; + GLint source; + GLint operand; + const GrCombineLocal_t c_local = Glide.State.ColorCombineLocal; + const GrCombineOther_t c_other = Glide.State.ColorCombineOther; + const GrCombineLocal_t a_local = Glide.State.AlphaLocal; + const GrCombineOther_t a_other = Glide.State.AlphaOther; + const CombineArgument** combine_argument = &OpenGL.ColorCombineArguments[0]; + combine_argument[CFARG_Local] = &ColorCombineLocals[c_local]; + combine_argument[CFARG_Other] = Glide.State.TextureCombineRGBInvert ? &ColorCombineOthersInverted[c_other] : &ColorCombineOthers[c_other]; + combine_argument[CFARG_LocalAlpha] = &AlphaCombineLocals[a_local]; + combine_argument[CFARG_OtherAlpha] = Glide.State.TextureCombineAInvert ? &AlphaCombineOthersInverted[a_other] : &AlphaCombineOthers[a_other]; + combine_argument[CFARG_Factor] = Glide.State.TextureCombineRGBInvert ? &ColorCombineFactorsInverted[c_factor] : &ColorCombineFactors[c_factor]; + for(unsigned long arg_index = 0; arg_index < 3; arg_index++) + { + arg = unit.CombineArg[arg_index]; + if (arg < CFARG_None) + { + if (arg == CFARG_Factor /* ||arg == CFARG_FactorAlpha*/) + { + if (combine_argument[arg]->Source < CFARG_None) + { + // Resolve factor to local/other: + // The factor source references to the local/other, + // which can be retrieved via the combine_argument[] array + source = combine_argument[combine_argument[arg]->Source]->Source; + // but the operand of the factor specifies already the + // correct component of the pixel (rgb or alpha) to be used. + // Example: if factor == GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + // then the other alpha in AlphaCombineOthers is GL_SRC_ALPHA + // but the factor operand is correctly GL_ONE_MINUS_SRC_ALPHA. + // operand = combine_argument[arg]->Operand; + // Not after color inversion has been added + operand = combine_argument[combine_argument[arg]->Source]->Operand; // No + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else + { + // combinearg = local or other (alpha) + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else if (arg > CFARG_None) + { + source = unit.CombineArg[arg_index]; + operand = GL_SRC_COLOR; + } + else + { + // arg == CFARG_None -> argument not used + continue; + } +#ifdef OPENGL_DEBUG + GlideMsg("Arg %d = Source:0x%x, Operand:0x%x\n", arg_index, source, operand); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + arg_index, source); + glReportError(); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + arg_index, operand); + glReportError(); + } + } + glReportError(); + } + + // Alpha Combine State + if (s_bUpdateAlphaCombineState) + { + if (reset_state) s_bUpdateAlphaCombineState = false; + // Handle chromakey special case + if (OpenGL.ChromaKey && OpenGL.Texture && !OpenGL.Blend) + { + // need to disable alpha combining until an additional + // texture unit can be used to mask out the chroma key color. + // Note that the second unit must be setup because the + // texture unit might be turned on due to the color setup. + if (unit_index == 1) + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL AlphaCombine unit %d = unused\n", unit_index); +#endif + // OpenGL.ColorAlphaUnitAlphaEnabledState[1] = false; + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL AlphaCombine unit %d = texture_alpha\n", unit_index); +#endif + // OpenGL.ColorAlphaUnitAlphaEnabledState[0] = true; + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + } + glReportError(); + } + else + { + CombineFunctionGLTextureUnit unit = OpenGL.AlphaCombineFunctions[a_function].ColorAlphaUnit[unit_index]; + if (unit.Function == CF_Unused) + { + if (OpenGL.ChromaKey && OpenGL.Texture && OpenGL.Blend) + { + // Modulate the alpha mask with the output of the previous unit + // to make chromakey-colored pixels invisible (so they wouldn't pass the alpha test) + // (chromakey-colored pixels have an alpha value of 0.0, the others 1.0) +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL AlphaCombine unit %d = chromakey mask\n", unit_index); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + // OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL AlphaCombine unit %d = unused\n", unit_index); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + glReportError(); + // OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; + } + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL AlphaCombine Function for unit %d = 0x%x\n", unit_index, unit.Function); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, unit.Function); + glReportError(); + CombineFunctionColorAlphaArg arg; + GLint source; + GLint operand; + // Alpha @todo: colors are unused, aren't they? + const GrCombineLocal_t a_local = Glide.State.AlphaLocal; + const GrCombineOther_t a_other = Glide.State.AlphaOther; + const CombineArgument** combine_argument = &OpenGL.AlphaCombineArguments[0]; + // combine_argument[CFARG_Local] = 0; // This is set to 0 onn initialising OpenGL + // combine_argument[CFARG_Other] = 0; + combine_argument[CFARG_LocalAlpha] = &AlphaCombineLocals[a_local]; + combine_argument[CFARG_OtherAlpha] = Glide.State.TextureCombineAInvert ? &AlphaCombineOthersInverted[a_other] : &AlphaCombineOthers[a_other]; + combine_argument[CFARG_Factor] = Glide.State.TextureCombineAInvert ? &AlphaCombineFactorsInverted[a_factor] : &AlphaCombineFactors[a_factor]; + // Color + // OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = true; + for(unsigned long arg_index = 0; arg_index < 3; arg_index++) + { + arg = unit.CombineArg[arg_index]; + if (arg < CFARG_None) + { + if (arg == CFARG_Factor /*Alpha*/) + { + if (combine_argument[arg]->Source < CFARG_None) + { + // Resolve factor to local/other: + // The factor source references to local/other, + // which can be retrieved via the combine_argument[] array. + source = combine_argument[combine_argument[arg]->Source]->Source; + // but the operand of the factor specifies already which + // component of the pixel and how it should be used. + // Example: if factor == GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA + // then the other alpha in AlphaCombineOthers is GL_SRC_ALPHA + // but the factor operand is correctly GL_ONE_MINUS_SRC_ALPHA. + // operand = combine_argument[arg]->Operand; + // After color inversion has been added, the operand must be taken + // from the inversion table + operand = combine_argument[combine_argument[arg]->Source]->Operand; + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else + { + source = combine_argument[arg]->Source; + operand = combine_argument[arg]->Operand; + } + } + else if (arg > CFARG_None) + { + source = unit.CombineArg[arg_index]; + operand = GL_SRC_ALPHA; + } + else + { + // arg == CFARG_None -> argument not used + continue; + } +#ifdef OPENGL_DEBUG + GlideMsg("Arg %d = Source:0x%x, Operand:0x%x\n", arg_index, source, operand); +#endif + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + arg_index, source); + glReportError(); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + arg_index, operand); + glReportError(); + } + } + } + glReportError(); + } + + // Constant Color State + if (s_bUpdateConstantColorValueState || s_bUpdateConstantColorValue4State) + { + GLfloat* color; + if (Glide.State.Delta0Mode) + { + if (reset_state) s_bUpdateConstantColorValue4State = false; + color = &OpenGL.Delta0Color[0]; + } + else + { + if (reset_state) s_bUpdateConstantColorValueState = false; + color = &OpenGL.ConstantColor[0]; + } +#ifdef OPENGL_DEBUG + if (reset_state) GlideMsg("OpenGL.ConstantColor=(%g, %g, %g, %g)\n", + color[0], + color[1], + color[2], + color[3]); +#endif + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color[0]); + glReportError(); + } + } + // Ensure the state change flags are reset during the last iteration + reset_state = true; + } + glReportError(); + } + else // OpenGL.ColorAlphaTectureUnit2 == 0 + { + if (active_texture_unit_not_coloralpha1) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + active_texture_unit_not_coloralpha1 = false; + } + if (s_bUpdateTextureState) + { + s_bUpdateTextureState = false; + if (active_texture_unit_client_state_not_coloralpha1) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + active_texture_unit_client_state_not_coloralpha1 = false; + } + if (OpenGL.Texture) + { + glEnable(GL_TEXTURE_2D); + if (InternalConfig.EXT_compiled_vertex_array) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + else + { + if (InternalConfig.EXT_compiled_vertex_array) + { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + glDisable(GL_TEXTURE_2D); + } + glReportError(); + } + + if (s_bUpdateColorCombineState) + { + s_bUpdateColorCombineState = false; + if ( ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); + } + else + if ( ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); + } + else + if (InternalConfig.EXT_texture_env_add && + ( Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_ONE ) && + ( Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE ) && + ( ( Glide.State.ColorCombineFunction == GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA ) || + ( Glide.State.ColorCombineFunction == GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL ) ) ) + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); + } + else + { + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } + glReportError(); + } + } + } + + if (active_texture_unit_not_coloralpha1) + { + if (active_texture_unit_client_state_not_coloralpha1) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); +} + +void SetClipVerticesState_Update(bool clip_vertices) +{ + OpenGL.ClipVerticesEnabledState = clip_vertices; + if (InternalConfig.EXT_clip_volume_hint) + { + RenderDrawTriangles(); + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, clip_vertices ? GL_DONT_CARE : GL_FASTEST); +#ifdef OPENGL_DEBUG + GlideMsg("OpenGL.ClipVerticesEnabledState = %s\n", clip_vertices ? "GL_DONT_CARE" : "GL_FASTEST"); +#endif + } +} diff --git a/MacGLide/OpenGLide/GLRenderUpdateState.h b/MacGLide/OpenGLide/GLRenderUpdateState.h new file mode 100644 index 0000000..1390316 --- /dev/null +++ b/MacGLide/OpenGLide/GLRenderUpdateState.h @@ -0,0 +1,196 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* updates the GL state before rendering vertices +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlOgl.h" +#include "GlideApplication.h" + +extern bool s_bUpdateTextureState; +extern bool s_bUpdateFogModeState; +extern bool s_bUpdateFogColorState; +extern bool s_bUpdateBlendState; +extern bool s_bUpdateChromaKeyAndAlphaState; +extern bool s_bUpdateColorCombineState; +extern bool s_bUpdateAlphaCombineState; +extern bool s_bUpdateColorInvertState; +extern bool s_bUpdateAlphaInvertState; +extern bool s_bUpdateConstantColorValueState; +extern bool s_bUpdateConstantColorValue4State; + +extern bool s_bForceChromaKeyAndAlphaStateUpdate; + +// Forward declarations for inline functions +// (Deferred inlining) +inline void SetChromaKeyAndAlphaState(); +inline void SetAlphaCombineState(); + +inline void ForceChromaKeyAndAlphaStateUpdate() +{ + s_bForceChromaKeyAndAlphaStateUpdate = true; +} + +inline void SetColorTextureState() +{ + if ((Glide.COther && + (Glide.State.ColorCombineOther == GR_COMBINE_OTHER_TEXTURE) + && (Glide.State.TextureCombineCFunction != GR_COMBINE_FUNCTION_ZERO)) + || ((Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) + || (Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA) + || (Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_TEXTURE_RGB))) + { + OpenGL.ColorTexture = true; + } + else + { + OpenGL.ColorTexture = false; + } + +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.ColorTexture = %d\n", OpenGL.ColorTexture); +#endif +} + +inline void SetAlphaTextureState() +{ + if (OpenGL.ColorAlphaUnit2) + { + if (( Glide.AOther && + (Glide.State.AlphaOther == GR_COMBINE_OTHER_TEXTURE) + && (Glide.State.TextureCombineAFunction != GR_COMBINE_FUNCTION_ZERO)) + || ((Glide.State.AlphaFactor == GR_COMBINE_FACTOR_TEXTURE_ALPHA) + || (Glide.State.AlphaFactor == GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA) + || (Glide.State.AlphaFactor == GR_COMBINE_FACTOR_TEXTURE_RGB))) + { + OpenGL.AlphaTexture = true; + } + else + { + OpenGL.AlphaTexture = false; + } + } + else + { + if ( Glide.AOther && ( Glide.State.AlphaOther == GR_COMBINE_OTHER_TEXTURE ) ) + { + OpenGL.AlphaTexture = true; + } + else + { + OpenGL.AlphaTexture = false; + } + } + +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.AlphaTexture = %d\n", OpenGL.AlphaTexture); +#endif +} + +inline void SetTextureState() +{ + s_bUpdateTextureState = true; + bool opengl_texture = (OpenGL.ColorTexture || (OpenGL.Blend && OpenGL.AlphaTexture)) + && Glide.State.TexSource.StartAddress != GR_NULL_MIPMAP_HANDLE; + OpenGL.Texture = opengl_texture; + // When the texture state changes, chromakeying is also affected + SetChromaKeyAndAlphaState(); + +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.Texture = %d\n", OpenGL.Texture); +#endif +} + +inline void SetBlendState() +{ + s_bUpdateBlendState = true; +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.Blend = %d\n", OpenGL.Blend); +#endif +} + +inline void SetFogModeState() +{ + s_bUpdateFogModeState = true; +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.Fog = %d\n", OpenGL.Fog); +#endif +} + +inline void SetFogColorState() +{ + s_bUpdateFogColorState = true; +} + +inline void SetChromaKeyAndAlphaState() +{ + s_bUpdateChromaKeyAndAlphaState = true; +#ifdef OPENGL_DEBUG + GlideMsg( "OpenGL.ChromaKey = %d\n", OpenGL.ChromaKey); +#endif + if (OpenGL.ColorAlphaUnit2) + { + // Need to change alpha combine because the alpha channel + // in non-blended chromakey textures is a special case + SetAlphaCombineState(); + } +} + +inline void SetColorCombineState() +{ + s_bUpdateColorCombineState = true; +} + +inline void SetAlphaCombineState() +{ + s_bUpdateAlphaCombineState = true; +} + +inline void SetColorInvertState() +{ + s_bUpdateColorInvertState = true; + SetFogModeState(); +#ifdef OPENGL_DEBUG + GlideMsg( "Glide.State.ColorCombineInvert = %d\n", Glide.State.ColorCombineInvert); +#endif +} + +inline void SetAlphaInvertState() +{ + s_bUpdateAlphaInvertState = true; + SetFogModeState(); +#ifdef OPENGL_DEBUG + GlideMsg( "Glide.State.AlphaInvert = %d\n", Glide.State.AlphaInvert); +#endif +} + +inline void SetConstantColorValueState() +{ + s_bUpdateConstantColorValueState = true; +} + +inline void SetConstantColorValue4State() +{ + s_bUpdateConstantColorValue4State = true; +} + +// Also called from FrameBuffer class +extern void SetClipVerticesState_Update(bool clip_vertices); + +// Needs to be called before adding a triangle, line or point +inline void SetClipVerticesState(bool clip) +{ + bool clip_vertices = clip || OpenGL.Clipping; + // Triggers very seldomly (because grDrawXXXWithClip() is used very seldom) + // As a result this method is designed for cause the least cost when not being triggered + if (clip_vertices != OpenGL.ClipVerticesEnabledState) + { + SetClipVerticesState_Update(clip_vertices); + } +} + +extern void RenderUpdateState(); diff --git a/MacGLide/OpenGLide/GLutil.cpp b/MacGLide/OpenGLide/GLutil.cpp new file mode 100644 index 0000000..c510d5b --- /dev/null +++ b/MacGLide/OpenGLide/GLutil.cpp @@ -0,0 +1,475 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Utility File +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideDisplay.h" +#include "GlideSettings.h" +#include "GLExtensions.h" +#include "GLUtil.h" +#include "PGTexture.h" + + +OSStatus aglReportWarning(void) +{ + GLenum err = aglGetError(); + if (AGL_NO_ERROR != err) + { + GlideMsg("AGL-Error: %s\n", reinterpret_cast(aglErrorString(err))); + } + // ensure we are returning an OSStatus noErr if no error condition + if (err == AGL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} + +// Gobals for initialising the display +WindowPtr pGLWindow = NULL; +structWindowInfoPtr pWindowInfo = NULL; + +short SetAGLAttributes(GLint* aglAttributes, short index) +{ + // The maximun depth buffer size will be requested + // by choosing AGL_MAXIMUM_POLICY + if (UserConfig.DepthBufferBits < 0) UserConfig.DepthBufferBits = 0; + if (UserConfig.DepthBufferBits > 32) UserConfig.DepthBufferBits = 32; + GLint depthbufferbits = UserConfig.DepthBufferBits; + // 0 triggers the maximun number of available depth + // buffer bits to be used but at least 16 + if (depthbufferbits == 0) + { + depthbufferbits = 16; + } + aglAttributes[index++] = AGL_RGBA; + aglAttributes[index++] = AGL_ALPHA_SIZE; + aglAttributes[index++] = 0; // Alpha not supported on Glide Cards with depth buffering + aglAttributes[index++] = AGL_DOUBLEBUFFER; + // ARB_multisample doesn't seem to work in Classic, + // but maybe someone wants to port this to Carbon... + /* + if (UserConfig.FullSceneAntiAliasing > 0) + { + aglAttributes[index++] = AGL_SAMPLE_BUFFERS_ARB; + aglAttributes[index++] = 1; + aglAttributes[index++] = AGL_SAMPLES_ARB; + aglAttributes[index++] = UserConfig.FullSceneAntiAliasing > 0; + } + */ + aglAttributes[index++] = AGL_NO_RECOVERY; + if (UserConfig.DepthBufferBits == 0) aglAttributes[index++] = AGL_MAXIMUM_POLICY; + aglAttributes[index++] = AGL_DEPTH_SIZE; + aglAttributes[index++] = depthbufferbits; + if (UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + aglAttributes[index++] = AGL_FULLSCREEN; + } + if (UserConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + aglAttributes[index++] = AGL_STENCIL_SIZE; + aglAttributes[index++] = AGL_2_BIT; + } + aglAttributes[index] = AGL_NONE; + return index; +} + +// This function can only use settings from UserConfig, +// as it's called before InternalConfig +bool InitialiseOpenGLWindow(FxU32 hwnd, int x, int y, FxU32 width, FxU32 height ) +{ + glReportErrors("InitialiseOpenGLWindow"); + // Adjust the origin if the selected display resolution + // is greater than the OpenGL resolution + unsigned long display_width = 0; + unsigned long display_height = 0; + OpenGL.OriginX = 0; + OpenGL.OriginY = 0; + Rect rectWin = {y, x , height, width}; + // Change the screen resolution? + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + OSErr err = DisplayManager_RememberPassthroughDisplay(); + if (err == noErr) + { + // Avoid flicker during screen resolution switching + #ifndef OGL_DEBUG + DisplayManager_SetPassthroughDisplayGammaBlack(); + #endif + long freq = UserConfig.MonitorRefreshRate; + // sort out illegal values + if (freq < 60) freq = 0; + // check whether to use the refresh rate requested by the Glide application + if (freq == 0) freq = OpenGL.Refresh; + // Allows to play Falcon 4.0 in True Color and to play Tomb Raider Gold 1+2 with movies enabled. + // However, Tomb Raider II < 1.03 has problems displaying Lara and other in-game objects. + err = DisplayManager_SetGlideDisplay(width, height, freq); + if (err != noErr) + { + if (width < 640) + { + // Not all displays support all Glide resolutions, + // for instance the LCD-iMacs don't support 512x384 + GlideMsg("Error: Resolution %dx%d@%dHz not found. Trying double resolution %dx%d@%dHz.\n", width, height, freq, width << 1, height << 1, freq); + // Restore gamma first + err = DisplayManager_SetGlideDisplay(width << 1, height << 1, freq); + if (err == noErr) + { + width = width << 1; + height = height << 1; + OpenGL.WindowWidth = width; + OpenGL.WindowHeight = height; + } + } + } + } + if (err != noErr) + { + // If changing the screensize failed (for instance + // when the calling app checks for available resolutions) + // the gamma correction table must be restored or + // we may end up with a black screen + DisplayManager_RestorePassthroughDisplayGamma(); + return false; + } + if (DisplayManager_GetGlideDisplayResolution(display_width, display_height)) + { + // Position the viewport in the middle of the screen + OpenGL.OriginX = (display_width - width) / 2; + OpenGL.OriginY = (display_height - height) / 2; + rectWin.right = display_width; + rectWin.bottom = display_height; + } + } + else + { + if (DisplayManager_GetDesktopDisplayResolution(display_width, display_height)) + { + // Position the window in the middle of the screen + rectWin.left = (display_width - width) / 2; + rectWin.top = (display_height - height) / 2; + } + else + { + rectWin.left = 40; + rectWin.top = 60; + } + rectWin.right = rectWin.left + width; + rectWin.bottom = rectWin.top + height; + } + // build window + pWindowInfo = (structWindowInfoPtr) NewPtrSysClear (sizeof (structWindowInfo)); + OSStatus err = CreateNewWindow(kDocumentWindowClass, kWindowNoAttributes, &rectWin, &pGLWindow); + if (pGLWindow) + { + ShowWindow (pGLWindow); + SetPortWindowPort (pGLWindow); + pWindowInfo->glInfo.fDraggable = false; + pWindowInfo->glInfo.fmt = 0; + pWindowInfo->glInfo.fAcceleratedMust = true; + pWindowInfo->glInfo.VRAM = 0; + pWindowInfo->glInfo.textureRAM = 0; + SetAGLAttributes(pWindowInfo->glInfo.aglAttributes, 0); + BuildGLFromWindow(pGLWindow, &pWindowInfo->aglContext, &pWindowInfo->glInfo, NULL); + if (pWindowInfo->aglContext) + { + // This does not work reliably + /* + if (UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + long freq = UserConfig.MonitorRefreshRate; + // sort out illegal values + if (freq < 60) freq = 0; + // check whether to use the refresh rate requested by the Glide application + if (freq == 0) freq = OpenGL.Refresh; + // aglSetDrawable(pWindowInfo->aglContext, (AGLDrawable) NULL); + if (aglSetFullScreen(pWindowInfo->aglContext, width, height, freq, 0)) + { + if (aglSetCurrentContext(pWindowInfo->aglContext)) + { + aglUpdateContext(pWindowInfo->aglContext); + } + else + { + aglReportWarning(); + GlideError("aglSetCurrentContext() after aglSetFullScreen() failed\n"); + // shutdown full screen + aglSetCurrentContext(pWindowInfo->aglContext); + aglReportError(); + aglSetDrawable(pWindowInfo->aglContext, (AGLDrawable) GetWindowPort(pGLWindow)); + aglReportError(); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + } + } + else + { + aglReportWarning(); + GlideError("aglSetFullScreen() failed\n"); + // shutdown full screen + aglSetCurrentContext(pWindowInfo->aglContext); + aglReportError(); + aglSetDrawable(pWindowInfo->aglContext, (AGLDrawable) GetWindowPort(pGLWindow)); + aglReportError(); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + } + } + else + { + if (aglSetCurrentContext(pWindowInfo->aglContext)) + { + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + } + else + { + aglReportWarning(); + GlideError("aglSetCurrentContext() failed\n"); + } + } + */ + // Keep renderers in memory + aglConfigure(AGL_RETAIN_RENDERERS, GL_TRUE); + aglReportWarning(); + // And minimise cache size + aglConfigure(AGL_FORMAT_CACHE_SIZE, 1); + aglReportWarning(); + // Don't render ahead + bool runningInClassic = strstr(reinterpret_cast(glGetString(GL_EXTENSIONS)), "GL_EXT_fog_coord") != NULL; + if (runningInClassic) + { + aglEnable(pWindowInfo->aglContext, AGL_SWAP_LIMIT); + aglReportWarning(); + } + } + else + { + aglReportWarning(); + DestroyGLFromWindow(&pWindowInfo->aglContext, &pWindowInfo->glInfo); + GlideError("couldn't create agl context"); + return false; + } + } + else + { + GlideError("Couldn't create window"); + } + // clear color buffer to black to minimmise white screen flash on resolution change + // and white top/bottoms when displaying widescreen movies on 4/3 screens + glDrawBuffer(GL_BACK); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + GLint swap = 0; + aglSetInteger(pWindowInfo->aglContext, AGL_SWAP_INTERVAL, &swap); + aglSwapBuffers(pWindowInfo->aglContext); + aglReportError(); + + if (UserConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + glEnable(GL_STENCIL_TEST); + glStencilMask(0x03); + glClearStencil(0x00); + glStencilFunc(GL_ALWAYS, 0x02, 0x03); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glReportError(); + } + + // The gamma correction value is restored in grSstWinOpen() + // so we don't have to do anything here + return true; +} + +void FinaliseOpenGLWindow(void) +{ + s_Framebuffer.Cleanup(); + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + #ifndef OGL_DEBUG + DisplayManager_SetGlideDisplayGammaBlack(); + #endif + } + if (pWindowInfo) + { + // DeleteFontGL (pWindowInfo->fontList); + // must clean up failure to do so will result in an Unmapped Memory Exception + DestroyGLFromWindow(&pWindowInfo->aglContext, &pWindowInfo->glInfo); + DisposePtr ((Ptr) pWindowInfo); + pWindowInfo = NULL; + } + if (pGLWindow) + { + DisposeWindow (pGLWindow); + pGLWindow = NULL; + } + // Cleanup display manager? + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + DisplayManager_RestorePassthroughDisplay(); + } +} + +void HideOpenGLWindow() +{ + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { +#ifndef OGL_DEBUG + DisplayManager_SetGlideDisplayGammaBlack(); +#endif + } + // Hide window by moving it offscreen, allowing some extra offset to hide the bar + MoveWindow(pGLWindow, OpenGL.WindowWidth + 64, OpenGL.WindowHeight + 64, FALSE); + // Actually HideWIndow() should be working, but it blacks out + // the Movies in Tomb Raider Gold + // HideWindow(pGLWindow); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + DisplayManager_RestorePassthroughDisplay(); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + } +} + +void RestoreOpenGLWindow() +{ + // Change the screen resolution? + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager || + UserConfig.DisplayMode == OpenGLideDisplayMode_aglSetFullScreen) + { + OSErr err = DisplayManager_RememberPassthroughDisplay(); + if (err == noErr) + { + // Avoid flicker during screen resolution switching +#ifndef OGL_DEBUG + DisplayManager_SetPassthroughDisplayGammaBlack(); +#endif + } + } + DisplayManager_RestoreGlideDisplay(); + // 0,0 is only correct in fullscreen modes where the OpenGL window matches the + // Glide screen resolution. + MoveWindow(pGLWindow, 0, 0, FALSE); + // Actually HideWIndow() should be working, but it blacks out the + // Movies in Tomb Raider Gold + // ShowWindow(pGLWindow); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + SelectWindow(pGLWindow); + aglUpdateContext(pWindowInfo->aglContext); + aglReportError(); + // @todo: Sometimes textures in Descent look wierd + // Clearing the textues shouldn't be necessary, + // so updating the context might not be enough. + // to restore the textures (they look wierd after showing he window) + // Textures->Clear(); + DisplayManager_SetGlideDisplayGamma(Glide.State.Gamma); + +} + +void ConvertColorB( GrColor_t GlideColor, FxU8 &R, FxU8 &G, FxU8 &B, FxU8 &A ) +{ + switch ( Glide.State.ColorFormat ) + { + case GR_COLORFORMAT_ARGB: //0xAARRGGBB + A = (FxU8)( ( GlideColor & 0xFF000000 ) >> 24 ); + R = (FxU8)( ( GlideColor & 0x00FF0000 ) >> 16 ); + G = (FxU8)( ( GlideColor & 0x0000FF00 ) >> 8 ); + B = (FxU8)( ( GlideColor & 0x000000FF ) ); + break; + + case GR_COLORFORMAT_ABGR: //0xAABBGGRR + A = (FxU8)( ( GlideColor & 0xFF000000 ) >> 24 ); + B = (FxU8)( ( GlideColor & 0x00FF0000 ) >> 16 ); + G = (FxU8)( ( GlideColor & 0x0000FF00 ) >> 8 ); + R = (FxU8)( ( GlideColor & 0x000000FF ) ); + break; + + case GR_COLORFORMAT_RGBA: //0xRRGGBBAA + R = (FxU8)( ( GlideColor & 0xFF000000 ) >> 24 ); + G = (FxU8)( ( GlideColor & 0x00FF0000 ) >> 16 ); + B = (FxU8)( ( GlideColor & 0x0000FF00 ) >> 8 ); + A = (FxU8)( ( GlideColor & 0x000000FF ) ); + break; + + case GR_COLORFORMAT_BGRA: //0xBBGGRRAA + B = (FxU8)( ( GlideColor & 0xFF000000 ) >> 24 ); + G = (FxU8)( ( GlideColor & 0x00FF0000 ) >> 16 ); + R = (FxU8)( ( GlideColor & 0x0000FF00 ) >> 8 ); + A = (FxU8)( ( GlideColor & 0x000000FF ) ); + break; + } +} + +GrColor_t ConvertConstantColor( float R, float G, float B, float A ) +{ + GrColor_t r = (GrColor_t) R; + GrColor_t g = (GrColor_t) G; + GrColor_t b = (GrColor_t) B; + GrColor_t a = (GrColor_t) A; + + switch ( Glide.State.ColorFormat ) + { + case GR_COLORFORMAT_ARGB: //0xAARRGGBB + return ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b; + + case GR_COLORFORMAT_ABGR: //0xAABBGGRR + return ( a << 24 ) | ( b << 16 ) | ( g << 8 ) | r; + + case GR_COLORFORMAT_RGBA: //0xRRGGBBAA + return ( r << 24 ) | ( g << 16 ) | ( b << 8 ) | a; + + case GR_COLORFORMAT_BGRA: //0xBBGGRRAA + return ( b << 24 ) | ( g << 16 ) | ( r << 8 ) | a; + } + + return 0; +} + +void ConvertColorF( GrColor_t GlideColor, float &R, float &G, float &B, float &A ) +{ + switch ( Glide.State.ColorFormat ) + { + case GR_COLORFORMAT_ARGB: //0xAARRGGBB + A = (float)( ( GlideColor & 0xFF000000 ) >> 24 ) * D1OVER255; + R = (float)( ( GlideColor & 0x00FF0000 ) >> 16 ) * D1OVER255; + G = (float)( ( GlideColor & 0x0000FF00 ) >> 8 ) * D1OVER255; + B = (float)( ( GlideColor & 0x000000FF ) ) * D1OVER255; + break; + + case GR_COLORFORMAT_ABGR: //0xAABBGGRR + A = (float)( ( GlideColor & 0xFF000000 ) >> 24 ) * D1OVER255; + B = (float)( ( GlideColor & 0x00FF0000 ) >> 16 ) * D1OVER255; + G = (float)( ( GlideColor & 0x0000FF00 ) >> 8 ) * D1OVER255; + R = (float)( ( GlideColor & 0x000000FF ) ) * D1OVER255; + break; + + case GR_COLORFORMAT_RGBA: //0xRRGGBBAA + R = (float)( ( GlideColor & 0xFF000000 ) >> 24 ) * D1OVER255; + G = (float)( ( GlideColor & 0x00FF0000 ) >> 16 ) * D1OVER255; + B = (float)( ( GlideColor & 0x0000FF00 ) >> 8 ) * D1OVER255; + A = (float)( ( GlideColor & 0x000000FF ) ) * D1OVER255; + break; + + case GR_COLORFORMAT_BGRA: //0xBBGGRRAA + B = (float)( ( GlideColor & 0xFF000000 ) >> 24 ) * D1OVER255; + G = (float)( ( GlideColor & 0x00FF0000 ) >> 16 ) * D1OVER255; + R = (float)( ( GlideColor & 0x0000FF00 ) >> 8 ) * D1OVER255; + A = (float)( ( GlideColor & 0x000000FF ) ) * D1OVER255; + break; + } +} + diff --git a/MacGLide/OpenGLide/GLutil.h b/MacGLide/OpenGLide/GLutil.h new file mode 100644 index 0000000..796a1d0 --- /dev/null +++ b/MacGLide/OpenGLide/GLutil.h @@ -0,0 +1,43 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGL Utility File +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Carbon_SetupGL.h" +#include "Carbon_SetupDSP.h" +#include "Carbon_Error_Handler.h" +#include + +struct structWindowInfo +{ + structGLWindowInfo glInfo; + AGLContext aglContext; + GLuint fontList; + char strContext [256]; +}; + +typedef struct structWindowInfo structWindowInfo; +typedef struct structWindowInfo* structWindowInfoPtr; + +extern WindowPtr pGLWindow; +extern structWindowInfoPtr pWindowInfo; + +OSStatus aglReportWarning(void); + +// General opengl utility functions +bool InitialiseOpenGLWindow( FxU32 hwnd, int x, int y, FxU32 width, FxU32 height ); +void FinaliseOpenGLWindow( void ); +void HideOpenGLWindow(); +void RestoreOpenGLWindow(); + +void ConvertColor4B( GrColor_t GlideColor, FxU32 &C ); +void ConvertColorB( GrColor_t GlideColor, FxU8 &R, FxU8 &G, FxU8 &B, FxU8 &A ); +void ConvertColorF( GrColor_t GlideColor, float &R, float &G, float &B, float &A ); +GrColor_t ConvertConstantColor( float R, float G, float B, float A ); diff --git a/MacGLide/OpenGLide/GlOgl.h b/MacGLide/OpenGLide/GlOgl.h new file mode 100644 index 0000000..528f171 --- /dev/null +++ b/MacGLide/OpenGLide/GlOgl.h @@ -0,0 +1,228 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Main Header +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __GLOGL_H__ +#define __GLOGL_H__ + +// #define __WIN32__ + +#include "sdk2_glide.h" + +/* +#define RDTSC(v) __asm _emit 0x0f \ + __asm _emit 0x31 \ + __asm mov FxU32 ptr v, eax \ + __asm mov FxU32 ptr v+4, edx +*/ +#define RDTSC(v) + +#define OGL_LOG_SEPARATE "--------------------------------------------------------\n" + +#define OGL_MIN_FRAME_BUFFER 2 +#define OGL_MAX_FRAME_BUFFER 16 +#define OGL_MIN_TEXTURE_BUFFER 2 +#define OGL_MAX_TEXTURE_BUFFER 32 + +#define OPENGLFOGTABLESIZE 64 * 1024 + +#define D1OVER255 0.003921568627451f // 1 / 255 +#define D1OVER65536 0.0000152587890625f // 1 / 65536 +#define D1OVER65535 0.000015259021896696421759365224689097f // 1 / 65535 +#define D1OVER256 0.00390625f // 1 / 256 +#define D2OVER256 0.0078125f // 2 / 256 +#define D4OVER256 0.015625f // 4 / 256 +#define D8OVER256 0.03125f // 8 / 256 + +#define WBUFFERNEAR -1.0f +#define WBUFFERFAR 0.0f +#define ZBUFFERNEAR 0.0f +#define ZBUFFERFAR -1.0f + +// Class declarations + +struct BufferStruct +{ + bool Lock; + GrLock_t Type; + GrLfbWriteMode_t WriteMode; + GrBuffer_t Buffer; + FxBool PixelPipeline; + FxU16 *Address; +}; + +struct TexSourceStruct +{ + FxU32 StartAddress; + FxU32 EvenOdd; + GrTexInfo Info; +}; + +union OGLByteColor +{ + struct + { + FxU8 B; + FxU8 G; + FxU8 R; + FxU8 A; + }; + FxU32 C; +}; + +struct CombineFunction; +struct CombineArgument; + +struct GlideState +{ + GrBuffer_t RenderBuffer; + GrDepthBufferMode_t DepthBufferMode; + GrCmpFnc_t DepthFunction; + FxBool DepthBufferWritting; + FxI16 DepthBiasLevel; + GrDitherMode_t DitherMode; + GrColor_t ChromakeyValue; + GrChromakeyMode_t ChromaKeyMode; + GrAlpha_t AlphaReferenceValue; + GrCmpFnc_t AlphaTestFunction; + FxBool AlphaMask; + FxBool ColorMask; + GrColor_t ConstantColorValue; + GrColor_t FogColorValue; + GrFogMode_t FogMode; + GrCullMode_t CullMode; + GrTextureClampMode_t SClampMode; + GrTextureClampMode_t TClampMode; + GrTextureFilterMode_t MinFilterMode; + GrTextureFilterMode_t MagFilterMode; + GrMipMapMode_t MipMapMode; + FxBool LodBlend; + GrCombineFunction_t ColorCombineFunction; + GrCombineFactor_t ColorCombineFactor; + GrCombineLocal_t ColorCombineLocal; + GrCombineOther_t ColorCombineOther; + FxBool ColorCombineInvert; + GrCombineFunction_t AlphaFunction; + GrCombineFactor_t AlphaFactor; + GrCombineLocal_t AlphaLocal; + GrCombineOther_t AlphaOther; + FxBool AlphaInvert; + GrCombineFunction_t TextureCombineCFunction; + GrCombineFactor_t TextureCombineCFactor; + GrCombineFunction_t TextureCombineAFunction; + GrCombineFactor_t TextureCombineAFactor; + FxBool TextureCombineRGBInvert; + FxBool TextureCombineAInvert; + GrOriginLocation_t OriginInformation; + TexSourceStruct TexSource; + GrAlphaBlendFnc_t AlphaBlendRgbSf; + GrAlphaBlendFnc_t AlphaBlendRgbDf; + GrAlphaBlendFnc_t AlphaBlendAlphaSf; + GrAlphaBlendFnc_t AlphaBlendAlphaDf; + FxU32 ClipMinX; + FxU32 ClipMaxX; + FxU32 ClipMinY; + FxU32 ClipMaxY; + GrColorFormat_t ColorFormat; + FxU32 STWHint; + FxBool VRetrace; + FxFloat LodBias; + bool Delta0Mode; + FxFloat Delta0ModeColor[4]; + FxFloat Gamma; +}; + +struct GlideStruct +{ + int ActiveVoodoo; + // Frame Buffer Stuff + int WindowWidth; + int WindowHeight; + int WindowTotalPixels; + GrScreenResolution_t Resolution; + GrScreenRefresh_t Refresh; + int NumBuffers; + int AuxBuffers; + // States and Constants + FxU8 FogTable[ GR_FOG_TABLE_SIZE + 1 ]; + FxU32 TexMemoryMaxPosition; + bool CLocal; + bool COther; + bool ALocal; + bool AOther; + GlideState State; + BufferStruct TempBuffer; + BufferStruct FrameBuffer; + BufferStruct ReadBuffer; + FxU32 TextureMemory; +}; + +struct OpenGLStruct +{ + bool GlideInit; + bool WinOpen; + unsigned long WindowWidth; + unsigned long WindowHeight; + FxU32 OriginX; + FxU32 OriginY; + FxU32 ClipMinX; + FxU32 ClipMaxX; + FxU32 ClipMinY; + FxU32 ClipMaxY; + GLfloat Gamma; + GLfloat AlphaReferenceValue; + GLenum AlphaTestFunction; + GLboolean DepthBufferWritting; + GLfloat DepthBiasLevel; + GLenum DepthFunction; + int DepthBufferType; + GLenum RenderBuffer; + GLenum SClampMode; + GLenum TClampMode; + GLenum MinFilterMode; + GLenum MagFilterMode; + GLenum SrcBlend; + GLenum DstBlend; + GLenum SrcAlphaBlend; + GLenum DstAlphaBlend; + GLuint Refresh; + GLfloat ConstantColor[4]; + GLfloat Delta0Color[4]; + GLfloat AlphaColor[4]; + GLfloat ZNear; + GLfloat ZFar; + GLint ColorAlphaUnit1; + GLint ColorAlphaUnit2; + bool ColorAlphaUnitColorEnabledState[2]; + bool ColorAlphaUnitAlphaEnabledState[2]; + GLuint DummyTextureName; + GLint FogTextureUnit; + bool FogTextureUnitEnabledState; + GLfloat FogColor[4]; + OGLByteColor ChromaColor; + bool Fog; + bool ColorTexture; + bool AlphaTexture; + bool Blend; + bool Texture; + bool ChromaKey; + bool Clipping; + bool ClipVerticesEnabledState; + int MultiTextureTMUs; + const CombineFunction* ColorCombineFunctions; + const CombineFunction* AlphaCombineFunctions; + const CombineArgument* ColorCombineArguments[5]; + const CombineArgument* AlphaCombineArguments[5]; + FxU32 WaitSignal; + FxU8 FogTable[OPENGLFOGTABLESIZE]; +}; + +#endif diff --git a/MacGLide/OpenGLide/Glextensions.h b/MacGLide/OpenGLide/Glextensions.h new file mode 100644 index 0000000..0184774 --- /dev/null +++ b/MacGLide/OpenGLide/Glextensions.h @@ -0,0 +1,21 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* OpenGL Extensions Header +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __GLEXTENSIONS__ +#define __GLEXTENSIONS__ + +void ValidateUserConfig(); +void GLExtensions( ); +void GLExtensionsCleanup(); +bool OGLIsExtensionSupported(const char* extension); + +#endif diff --git a/MacGLide/OpenGLide/Glide.cpp b/MacGLide/OpenGLide/Glide.cpp new file mode 100644 index 0000000..9ffa931 --- /dev/null +++ b/MacGLide/OpenGLide/Glide.cpp @@ -0,0 +1,475 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Main File +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideDisplay.h" +#include "GlideFramebuffer.h" +#include "GlideSettings.h" +#include "GLextensions.h" +#include "GLUtil.h" +#include "PGTexture.h" +#include "PGUTexture.h" + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Version numbers /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +const char* OpenGLideVersion = "0.13a1"; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +// Structs +GlideStruct Glide; +OpenGLStruct OpenGL; +GlideSettingsImpl UserConfig; +GlideSettingsImpl InternalConfig; +PGTexture* Textures = NULL; +PGUTexture UTextures; +GlideFramebuffer s_Framebuffer; + +// Number of Errors +unsigned long NumberOfErrors; + +OSErr InitMainVariables(void) +{ + OpenGL.WinOpen = false; + OpenGL.GlideInit = false; + NumberOfErrors = 0; + OSErr err = UserConfig.load(); + if (err == noErr) + { + // The following values must be updated right away, because the client application + // might call grSstQueryHardware() before opening a window + if ((UserConfig.TextureMemorySize >= OGL_MIN_TEXTURE_BUFFER) && + (UserConfig.TextureMemorySize <= OGL_MAX_TEXTURE_BUFFER)) + { + UserConfig.TextureMemorySize = UserConfig.TextureMemorySize; + } + + if ((UserConfig.FrameBufferMemorySize >= OGL_MIN_FRAME_BUFFER) && + (UserConfig.FrameBufferMemorySize <= OGL_MAX_FRAME_BUFFER)) + { + UserConfig.FrameBufferMemorySize = UserConfig.FrameBufferMemorySize; + } + + if (UserConfig.BoardType < OpenGLideBoardType_Voodoo) + { + UserConfig.BoardType = OpenGLideBoardType_Voodoo; + } + else if (UserConfig.BoardType > OpenGLideBoardType_Voodoo2) + { + UserConfig.BoardType = OpenGLideBoardType_Voodoo2; + } + + if (UserConfig.GlideTextureUnits < 1) + { + UserConfig.GlideTextureUnits = 1; + } + else if (UserConfig.GlideTextureUnits > 3) + { + UserConfig.GlideTextureUnits = 3; + } + // Apply mandatory application dependent settings/patches + GlideApplication::Type application = s_GlideApplication.GetType(); + switch (application) + { + case GlideApplication::Quake: + { + // Quake would not display anything without fixing the memory + unsigned int megabytes = 4; + if (UserConfig.FrameBufferMemorySize > megabytes) + { + UserConfig.FrameBufferMemorySize = megabytes; + GlideMsg("Decreased frmaebuffer memory size to %d megabytes to make Quake 3Dfx happy\n"); + } + } + break; + } + // Apply optional game specific settings + if (UserConfig.AutoEnableGameSpecificSettings) + { + bool texturesmoothing = false; + bool subtextures = false; + bool gapfix = false; + switch(application) + { + case GlideApplication::Carmageddon: + texturesmoothing = true; + break; + case GlideApplication::MythTFL: + texturesmoothing = true; + break; + case GlideApplication::Falcon40: + texturesmoothing = true; + break; + case GlideApplication::TombRaiderI: + texturesmoothing = true; + subtextures = true; + gapfix = true; + break; + case GlideApplication::TombRaiderII: + // subtextures = true; // works but slow + gapfix = true; + break; + default: + break; + } + if (texturesmoothing || subtextures || gapfix) + { + GlideMsg("Auto-enabling game specific settings for %s:\n", s_GlideApplication.GetName()); + } + // Suppress artefacts in main menu + if (texturesmoothing) + { + UserConfig.TextureSmoothing = true; + GlideMsg("TextureSmoothing enabled\n"); + } + if (subtextures) + { + UserConfig.GenerateSubTextures = 8; // Good for TR1 and TR2 + GlideMsg("Subtexture generation enabled\n"); + } + if (gapfix) + { + UserConfig.GapFix = static_cast(UserConfig.GapFix | (OpenGLideGapFixFlag_Enabled)); + GlideMsg("GapFix enabled\n"); + } + } + } + if (err != noErr) GlideError("Failed to load user config file: Error code %d", err); + return err; +} + +bool InitWindow(FxU32 hwnd) +{ + if (InitialiseOpenGLWindow(hwnd, 0, 0, OpenGL.WindowWidth, OpenGL.WindowHeight) == false) + { + return FXFALSE; + } + // Initialise some basic OpenGL() settings + InitOpenGL(); + // Continue initialising OpenGL with processing + // the user config and setup OpenGL extensions + ValidateUserConfig(); + + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "Configuration:\n"); + GlideMsg( OGL_LOG_SEPARATE ); + char sEnabled[] = "enabled"; + char sDisabled[] = "disabled"; + const char* boardnames[4] = {"Voodoo", "Voodoo Rush", "AT3D", "Voodoo 2"}; + GlideMsg( "Board type = %s\n", boardnames[InternalConfig.BoardType]); + GlideMsg( "Number of Texture Units = %d\n", InternalConfig.GlideTextureUnits ); + GlideMsg( "Texture Memory Size = %d Mb\n", InternalConfig.TextureMemorySize ); + GlideMsg( "Frame Buffer Memory Size = %d Mb\n", InternalConfig.FrameBufferMemorySize ); + GlideMsg( "Display method = %d\n", InternalConfig.DisplayMode); + // display resolution + GlideMsg("Display resolution = %dx%d\n", OpenGL.WindowWidth, OpenGL.WindowHeight); + if (InternalConfig.MonitorRefreshRate > 0) + { + GlideMsg( "Monitor Refresh Rate = %d\n", InternalConfig.MonitorRefreshRate ); + } + GlideMsg("Mipmapping %s\n", InternalConfig.Mipmapping ? sEnabled : sDisabled ); + if (InternalConfig.AnisotropylLevel >= 2 && InternalConfig.EXT_texture_filter_anisotropic) + { + GlideMsg("Selected level of anisotropy = %d\n", InternalConfig.AnisotropylLevel); + } + else + { + GlideMsg("Anisotropic texture filtering disabled\n"); + } + if (InternalConfig.FullSceneAntiAliasing == 0) + { + GlideMsg("FullSceneAntiAliasing disabled\n"); + } + else + { + GlideMsg("FullSceneAntiAliasing enabled, using %d samples\n", InternalConfig.FullSceneAntiAliasing); + } + GlideMsg("TextureSmoothing = %s\n", InternalConfig.TextureSmoothing ? sEnabled : sDisabled ); + GlideMsg("Precision Fix = %s\n", InternalConfig.PrecisionFix ? sEnabled : sDisabled ); + bool gapfix_enabled = InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled; + GlideMsg("GapFix = %s\n", gapfix_enabled ? sEnabled : sDisabled); + if (gapfix_enabled) + { + GlideMsg(" Debug = %s\n", InternalConfig.GapFix & OpenGLideGapFixFlag_Debug ? sEnabled : sDisabled); + GlideMsg(" IncircleFilterOr = %s\n", InternalConfig.GapFix & OpenGLideGapFixFlag_IncircleOr ? sEnabled : sDisabled); + GlideMsg(" IncircleFilterAnd = %s\n", InternalConfig.GapFix & OpenGLideGapFixFlag_IncircleAnd ? sEnabled : sDisabled); + GlideMsg(" IncircleFilterSecondRadius = %s\n", InternalConfig.GapFix & OpenGLideGapFixFlag_IncircleSecondRadius ? sEnabled : sDisabled); + GlideMsg("VertexLengthFilterSecondRadius = %s\n", InternalConfig.GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius ? sEnabled : sDisabled); + GlideMsg(" 1st radius = %g\n", InternalConfig.GapFixParam1); + if (InternalConfig.GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius) + { + GlideMsg(" Vertex Length = %g\n", InternalConfig.GapFixParam2); + } + else + { + GlideMsg(" triangle isoscelesness= %g\n", InternalConfig.GapFixParam2); + } + if ((InternalConfig.GapFix & OpenGLideGapFixFlag_IncircleSecondRadius) || (InternalConfig.GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius)) + { + GlideMsg(" 2nd radius = %g\n", InternalConfig.GapFixParam3); + } + if (InternalConfig.GapFix & OpenGLideGapFixFlag_DepthFactor) + { + GlideMsg(" Depth Factor = %g\n", InternalConfig.GapFixDepthFactor); + } + } + GlideMsg("Generate subtextures = %s", InternalConfig.GenerateSubTextures ? sEnabled : sDisabled ); + if (InternalConfig.GenerateSubTextures) GlideMsg(" (gridsize = %d)", InternalConfig.GenerateSubTextures); + GlideMsg("\n"); + GlideMsg("Framebuffer overlays = %s\n", InternalConfig.EnableFrameBufferOverlays ? sEnabled : sDisabled ); + GlideMsg("Framebuffer underlays = %s\n", InternalConfig.EnableFrameBufferUnderlays ? sEnabled : sDisabled ); + if (InternalConfig.FramebufferIgnoreUnlock) GlideMsg( "Ignore buffer unlocks = %s\n", InternalConfig.FramebufferIgnoreUnlock ? sEnabled : sDisabled); + if (InternalConfig.PedanticFrameBufferEmulation) GlideMsg( "Pedantic Framebuffer emulation = %s\n", InternalConfig.PedanticFrameBufferEmulation ? sEnabled : sDisabled); + GlideMsg(OGL_LOG_SEPARATE); + +#ifdef OGL_DEBUG + GlideMsg("GlideState size = %d\n", sizeof(GlideState)); + GlideMsg("GrState size = %d\n", sizeof(GrState)); + GlideMsg(OGL_LOG_SEPARATE); +#endif + GlideMsg("** Glide Calls **\n" ); + GlideMsg(OGL_LOG_SEPARATE); + + return true; +} + +void* AllocFrameBuffer(long buffersize, long buffertypesize) +{ + void* buffer = AllocSysPtr16ByteAligned(buffersize * buffertypesize); + if (buffer == NULL) + { + GlideError("Could NOT allocate sufficient memory for framebuffer... Sorry."); + exit( -1 ); + } + return buffer; +} + +void FreeFrameBuffer(void* buffer) +{ + Free16ByteAligned(buffer); +} + +void* AllocBuffer(long buffersize, long buffertypesize) +{ + void* buffer = AllocSysPtr16ByteAligned(buffersize * buffertypesize); + if (buffer == NULL) + { + GlideError("Could NOT allocate sufficient memory for buffer... Sorry."); + exit( -1 ); + } + return buffer; +} + +void FreeBuffer(void* buffer) +{ + Free16ByteAligned(buffer); +} + + +void* AllocObject(long buffersize) +{ + // Causes classic to crash + void* buffer = AllocSysPtr16ByteAligned(buffersize); + if (buffer == NULL) + { + GlideError("Could NOT allocate sufficient memory for object... Sorry."); + exit( -1 ); + } + return buffer; +} + +void FreeObject(void* buffer) +{ + Free16ByteAligned(buffer); +} + +// error handling +#ifdef OPENGL_DEBUG +OSStatus glReportError_impl (const char* __glide_functionname) +{ + char* errortext = NULL; + GLenum err = glGetError(); + switch (err) + { + case GL_NO_ERROR: + break; + case GL_INVALID_ENUM: + errortext = "Invalid enumeration"; + break; + case GL_INVALID_VALUE: + errortext ="Invalid value"; + break; + case GL_INVALID_OPERATION: + errortext = "Invalid operation"; + break; + case GL_STACK_OVERFLOW: + errortext = "Stack overflow"; + break; + case GL_STACK_UNDERFLOW: + errortext = "Stack underflow"; + break; + case GL_OUT_OF_MEMORY: + errortext = "Out of memory"; + break; + default: + errortext = "Unknown error code"; + break; + } + if (errortext) + { + GlideMsg ("Function %s, GL Error: %s\n", __glide_functionname, errortext); + } + // ensure we are returning an OSStatus noErr if no error condition + if (err == GL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} +#endif + +#if defined(OPTIMISE_OPENGL_STATE_CHANGES) || defined(OGL_DEBUG) || defined(OPENGL_DEBUG) +bool VerifyActiveTextureUnit_impl(GLint x, const char* functionname) +{ + glReportErrors("VerifyActiveTextureUnit_impl"); + GLint y; + glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &y); + glReportError(); + bool bVerified = x == y; + if (!bVerified) + { + GlideMsg("Warning: %s() active texture unit is GL_TEXTURE%d_ARB, but should be GL_TEXTURE%d_ARB\n", functionname, y - GL_TEXTURE0_ARB, x - GL_TEXTURE0_ARB); + } + return bVerified; +} +#endif + +#if defined(OPTIMISE_OPENGL_STATE_CHANGES) || defined(OGL_DEBUG) || defined(OPENGL_DEBUG) +bool VerifyTextureEnabledState_impl(const char* functionname) +{ + glReportErrors("VerifyActiveTextureUnit_impl"); + + // emember state + GLint current; + glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, ¤t); + glReportError(); + bool bVerified = true; + if (OpenGL.ColorAlphaUnit2) + { + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + bool bState = glIsEnabled(GL_TEXTURE_2D); + if (bState != (OpenGL.ColorAlphaUnitColorEnabledState[unit_index] || + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index])) + { + GlideMsg("Warning: texture unit GL_TEXTURE%d_ARB is %s in %s()\n", OpenGL.ColorAlphaUnit1 + unit_index - GL_TEXTURE0_ARB, bState ? "enabled" : "disabled", functionname); + bVerified = false; + } + glReportError(); + } + } + // Restore previous state + glActiveTextureARB(current); + return bVerified; +} +#endif + +//************************************************* +//* Initializes OpenGL +//************************************************* +void InitOpenGL( void ) +{ + OpenGL.ZNear = ZBUFFERNEAR; + OpenGL.ZFar = ZBUFFERFAR; + OpenGL.ClipMinX = 0; + OpenGL.ClipMinY = 0; + OpenGL.ClipMaxX = OpenGL.WindowWidth; + OpenGL.ClipMaxY = OpenGL.WindowHeight; + // Glide texture data is aligned at 8 byte boundaries + int alignment = 8; + glPixelStorei( GL_PACK_ALIGNMENT, alignment); + glPixelStorei( GL_UNPACK_ALIGNMENT, alignment); +} + +void GlideMsg(const char* message, ... ) +{ + va_list(args); + va_start(args, message); + + char buffer[StringBufferSize]; + + vsnprintf(buffer, StringBufferSize, message, args); + UserConfig.write_log(buffer); + va_end(args); +} + +void GlideError(const char *message, ... ) +{ + va_list(args); + va_start(args, message); + + char buffer[StringBufferSize]; + + NumberOfErrors++; + vsnprintf(buffer, StringBufferSize, message, args); + GlideMsg(buffer); + + va_end(args); + + grGlideShutdown(); + if (UserConfig.DisplayMode == OpenGLideDisplayMode_DisplayManager) + { + DisplayManager_RestoreDesktopDisplay(); + } + FatalErrorMessageBox(buffer); + exit(0); +} + + +bool ClearAndGenerateLogFile( void ) +{ + UserConfig.create_log(); + char buffer[32]; + GlideMsg(OGL_LOG_SEPARATE ); + GlideMsg("%s Log File\n", OpenGLideProductName); + GlideMsg(OGL_LOG_SEPARATE ); + GlideMsg("***** %s %s *****\n", OpenGLideProductName, OpenGLideVersion); + GlideMsg(OGL_LOG_SEPARATE ); + _strdate(buffer); + GlideMsg("Date: %s\n", buffer); + _strtime(buffer); + GlideMsg("Time: %s\n", buffer); + GlideMsg("Application: %s\n", s_GlideApplication.GetName()); + return true; +} + +void CloseLogFile( void ) +{ + char tmpbuf[ 128 ]; + GlideMsg( OGL_LOG_SEPARATE ); + _strtime( tmpbuf ); + GlideMsg( "Time: %s\n", tmpbuf ); + GlideMsg( OGL_LOG_SEPARATE ); +} + diff --git a/MacGLide/OpenGLide/Glide.h b/MacGLide/OpenGLide/Glide.h new file mode 100644 index 0000000..d7fe496 --- /dev/null +++ b/MacGLide/OpenGLide/Glide.h @@ -0,0 +1,142 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Shared Library entry points +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "GlideFramebuffer.h" +#include "GlideSettings_FSp.h" +typedef GlideSettingsFSp GlideSettingsImpl; + +#ifdef OPENGLIDE_HOST_MAC + #include "MacGlide.h" +#endif + +// Pointer to version string +extern const char* OpenGLideVersion; + +// Product name of the library +extern const char* OpenGLideProductName; + +// extern double ClockFreq; +extern GlideStruct Glide; // Glide Internal +extern OpenGLStruct OpenGL; // OpenGL equivalents +extern GlideSettingsImpl UserConfig; +extern GlideSettingsImpl InternalConfig; + +// GLide +OSErr InitMainVariables(); +bool InitWindow( FxU32 hwnd ); +void InitOpenGL( void ); +bool ClearAndGenerateLogFile( void ); +void CloseLogFile( void ); + +// Memory management +void* AllocFrameBuffer(long buffersize, long buffertypesize); +void FreeFrameBuffer(void* address); +void* AllocBuffer(long buffersize, long buffertypesize); +void FreeBuffer(void* address); +void* AllocObject(long buffersize); +void FreeObject(void* buffer); +// Platform specific +void* AllocSysPtr16ByteAligned(long buffersize); +void Free16ByteAligned(void* aligned_buffer); + +// framebuffer emulation +extern GlideFramebuffer s_Framebuffer; + +// endianess +inline void swaplong(void* l) +{ + unsigned char* v = reinterpret_cast(l); + unsigned char n[4]; + n[0] = v[3]; n[1] = v[2]; n[2] = v[1]; n[3] = v[0]; + *reinterpret_cast(l) = *reinterpret_cast(n); +} + +inline void swapshort(void* s) +{ + unsigned char* v = reinterpret_cast(s); + unsigned char n[2]; + n[0] = v[1]; n[1] = v[0]; + *reinterpret_cast(s) = *reinterpret_cast(n); +} + +inline void swaplong(void* d, const void* l) +{ + const unsigned char* v = reinterpret_cast(l); + unsigned char n[4]; + n[0] = v[3]; n[1] = v[2]; n[2] = v[1]; n[3] = v[0]; + *reinterpret_cast(d) = *reinterpret_cast(n); +} + +inline void swapshort(void* d, const void* s) +{ + const unsigned char* v = reinterpret_cast(s); + unsigned char n[2]; + n[0] = v[1]; n[1] = v[0]; + *reinterpret_cast(d) = *reinterpret_cast(n); +} + +#define max(X,Y) ( (X) > (Y) ? (X) : (Y) ) +#define min(X,Y) ( (X) < (Y) ? (X) : (Y) ) + +// size of temporary buffers for string processing +const int StringBufferSize = 256; + +void GlideMsg(const char *message, ...); +void GlideError(const char *message, ...); + +extern void FatalErrorMessageBox(const char* message); + +// error handling and debugging +#ifdef OPENGL_DEBUG + OSStatus glReportError_impl(const char* __glide_functionname); + #ifdef OGL_STOP_ON_GL_ERROR + #define glReportError() assert(GL_NO_ERROR == glReportError_impl(__glide_functionname)); + #else + #define glReportError() glReportError_impl(__glide_functionname); + #endif + #define glReportErrors(name) const char* __glide_functionname = name +#else + #define glReportError() + #define glReportErrors(name) +#endif + +// Optimising the code +#ifdef OPTIMISE_GLIDE_STATE_CHANGES + #define CHECK_STATE_CHANGED(x) if (x) return +#else + #define CHECK_STATE_CHANGED(x) +#endif + +// Veryfying state +#if defined(OPTIMISE_OPENGL_STATE_CHANGES) && defined(OPENGL_DEBUG) + bool VerifyActiveTextureUnit_impl(GLint x, const char* functionname); +#ifdef OGL_STOP_ON_GL_ERROR + #define VERIFY_ACTIVE_TEXTURE_UNIT(x) assert(VerifyActiveTextureUnit_impl(x, __glide_functionname)); +#else + #define VERIFY_ACTIVE_TEXTURE_UNIT(x) VerifyActiveTextureUnit_impl(x, __glide_functionname); +#endif +#else + #define VERIFY_ACTIVE_TEXTURE_UNIT(x) +#endif + +#if defined(OPTIMISE_OPENGL_STATE_CHANGES) && defined(OPENGL_DEBUG) + bool VerifyTextureEnabledState_impl(const char* functionname); +#ifdef OGL_STOP_ON_GL_ERROR + #define VERIFY_TEXTURE_ENABLED_STATE() assert(VerifyTextureEnabledState_impl(__glide_functionname)); +#else + #define VERIFY_TEXTURE_ENABLED_STATE() VerifyTextureEnabledState_impl(__glide_functionname); +#endif +#else + #define VERIFY_TEXTURE_ENABLED_STATE() +#endif diff --git a/MacGLide/OpenGLide/GlideApplication.h b/MacGLide/OpenGLide/GlideApplication.h new file mode 100644 index 0000000..8dfb2cb --- /dev/null +++ b/MacGLide/OpenGLide/GlideApplication.h @@ -0,0 +1,39 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Glide application management +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +class GlideApplication +{ +public: + GlideApplication(); + enum Type + { + Generic, + Carmageddon, + Carmageddon2, + FA18, + Falcon40, + FutureCop, + MythTFL, + Quake, + TombRaiderI, + TombRaiderII, + TombRaiderIII + }; + const char* GetName() const {return &m_Name[1];}; + inline const Type GetType() const {return m_Type;}; +protected: + void Init(); + char m_Name[33]; + Type m_Type; +}; + +extern GlideApplication s_GlideApplication; diff --git a/MacGLide/OpenGLide/GlideDisplay.h b/MacGLide/OpenGLide/GlideDisplay.h new file mode 100644 index 0000000..72e2151 --- /dev/null +++ b/MacGLide/OpenGLide/GlideDisplay.h @@ -0,0 +1,28 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Macintosh display +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +void DisplayManager_Initialise(); +void DisplayManager_Cleanup(); + +OSErr DisplayManager_SetGlideDisplay(unsigned int width, unsigned int height, unsigned int freq); +OSErr DisplayManager_RememberPassthroughDisplay(); +OSErr DisplayManager_RememberDesktopDisplay(); +OSErr DisplayManager_RestoreGlideDisplay(); +OSErr DisplayManager_RestorePassthroughDisplay(); +OSErr DisplayManager_RestoreDesktopDisplay(); +bool DisplayManager_GetDesktopDisplayResolution(unsigned long& width, unsigned long& height); +bool DisplayManager_GetGlideDisplayResolution(unsigned long& width, unsigned long& height); + +// gamma related functions +void DisplayManager_SetGlideDisplayGamma(FxFloat gamma); +void DisplayManager_SetGlideDisplayGammaBlack(); +void DisplayManager_SetPassthroughDisplayGammaBlack(); +void DisplayManager_RestorePassthroughDisplayGamma(); +void DisplayManager_SetDesktopDisplayGammaBlack(); diff --git a/MacGLide/OpenGLide/GlideFramebuffer.cpp b/MacGLide/OpenGLide/GlideFramebuffer.cpp new file mode 100644 index 0000000..e5677a7 --- /dev/null +++ b/MacGLide/OpenGLide/GlideFramebuffer.cpp @@ -0,0 +1,542 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Glide framebuffer emulation +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "driversrc_declarations.h" +#include "GlideApplication.h" +#include "GlideFramebuffer.h" +#include "GlideSettings.h" + + +// Optimised framebuffer tile layout for Carmageddon: Minimise calls to glTexImage2D +// Note: Carmageddon uses only the glide resolution 640x480. +// The sum of the first column must be 480 (vertical resolution) +// The sum of each row must be 640 (horizontal resolution) +// This does not apply to drawing the underlay +// (Underlays are drawn with max tile sizes because they're usally used to draw backgrounds) +const Framebuffer::tilesize GlideFramebuffer::tilesize_table_carmageddon[11] = +{ + { 64, {128,128, 8,128,128, 64, 32, 16, 8,0,0}}, + { 64, {128,128,128,128, 64, 64, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}}, + { 64, { 8,128,256,128, 32, 8, 64, 16, 0,0,0,0}}, + { 64, { 8,128,256,128, 32, 8, 64, 16, 0,0,0,0}} +}; + +GlideFramebuffer::GlideFramebuffer() +: m_write_opaque(false) +, m_must_write(false) +, m_renderbuffer_changed(false) +, m_renderbuffer_changed_for_read(false) +, m_depth(0.0f) +, m_alpha(0x000000ff) +, m_chromakeyvalue_changed(false) +, m_chromakeyvalue_new(0x0) +, m_bufferclearcalls(0) +{ +} + +GlideFramebuffer::~GlideFramebuffer() +{ +} + +void GlideFramebuffer::initialise(BufferStruct* framebuffer, BufferStruct* texbuffer) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::initialise(---, ---)\n"); + #endif + + m_grLfbLockWriteMode[0] = GR_LFBWRITEMODE_UNUSED; + m_grLfbLockWriteMode[1] = GR_LFBWRITEMODE_UNUSED; + m_grLfbLockWriteMode[2] = GR_LFBWRITEMODE_UNUSED; + m_grLfbLockWriteMode[3] = GR_LFBWRITEMODE_UNUSED; + m_grLfbLockWriteMode[4] = GR_LFBWRITEMODE_UNUSED; + m_grLfbLockWriteMode[5] = GR_LFBWRITEMODE_UNUSED; + GlideApplication::Type application = s_GlideApplication.GetType(); + if (application == GlideApplication::Carmageddon && Glide.WindowWidth == 640 && Glide.WindowHeight == 480) + { + initialise_buffers( framebuffer, texbuffer, + Glide.WindowWidth, Glide.WindowHeight, + tilesize_table_carmageddon, InternalConfig.EXT_Client_Storage); + } + else + { + initialise_buffers( framebuffer, texbuffer, + Glide.WindowWidth, Glide.WindowHeight, + 128, 128, InternalConfig.EXT_Client_Storage); + } + framebuffer->WriteMode = GR_LFBWRITEMODE_UNUSED; + texbuffer->WriteMode = GR_LFBWRITEMODE_UNUSED; +} + +void GlideFramebuffer::OnBufferLockStartWrite(GrLock_t dwType, GrBuffer_t dwBuffer, GrLfbWriteMode_t dwWriteMode, GrOriginLocation_t dwOrigin, FxBool bPixelPipeline) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnBufferLockStartWrite(%d)\n", dwOrigin); + #endif + + // Finish current write if buffer properties are about to change + if (m_must_write && + (m_framebuffer->WriteMode != dwWriteMode || + m_framebuffer->PixelPipeline != bPixelPipeline || + m_origin != dwOrigin || + (m_chromakeyvalue_changed && bPixelPipeline))) + { + // @todo: If the condition would trigger the frame buffer write + // in Falcon 4.0 (which it doesn't), parts of the cockpit overlay + // would appear twice or at unexpected places. This suggests there + // might be a bug in here (in conjunction with clipping??). + // Also be careful regarding performance issues. + WriteFrameBuffer(m_framebuffer->PixelPipeline); + m_must_write = false; + } + // Change format? + if (m_framebuffer->WriteMode != dwWriteMode) + { + if (dwWriteMode == GR_LFBWRITEMODE_565 || + dwWriteMode == GR_LFBWRITEMODE_1555 || + dwWriteMode == GR_LFBWRITEMODE_888) + { + initialise_format(dwWriteMode); + } + // The chromakey value is not flagged as changed here, + // because the initialise_format() function just changes + // the current value, not the new one + } + // Apply new values + m_grLfbLockWriteMode[m_framebuffer->Buffer] = dwWriteMode; + m_framebuffer->Lock = true; + m_framebuffer->Type = dwType; + m_framebuffer->WriteMode = dwWriteMode; + m_framebuffer->Buffer = dwBuffer; + m_framebuffer->PixelPipeline = bPixelPipeline; + m_origin = dwOrigin; + // Update chromakeyvalue for pixel pipeline + if (m_chromakeyvalue_changed && m_framebuffer->PixelPipeline) + { + // Apply changes to the frame buffer + m_ChromaKey = m_chromakeyvalue_new; + m_chromakeyvalue_changed = false; + m_must_clear_buffer = true; + begin_write(); + } + else if (m_must_write == false) + { + // If we don't have to flush the framebuffer, then no write + // operation is in progress and we must start a new one + // (and clear the buffer if necessary) + begin_write(); + } + m_must_write = true; +} + +void GlideFramebuffer::OnBufferUnlockEndWrite(GrBuffer_t dwBuffer) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnBufferUnlockEndWrite(%d)\n", dwBuffer); + #endif + + // continuing to write into the framebuffer is toggeled by not setting back + // the buffer write mode flag. As a result, we don't have to query for the + // FramebufferIgnoreUnlock elsewhere (only if we want to defer drawing). + if (!InternalConfig.FramebufferIgnoreUnlock) + { + // reset buffer write mode to indicate the buffer is no more in use + m_grLfbLockWriteMode[dwBuffer] = GR_LFBWRITEMODE_UNUSED; + } + + // When the pixel pipeline is enabled, the buffer must be written right away, + // in order to avoid commands like grColorCombine() etc. changing the + // pixel pipeline state before the buffer will eventtually be written out. + if (m_framebuffer->PixelPipeline) + { + WriteFrameBuffer(true); + // This write is finished + m_must_write = false; + } + // If the pixelpipeline is disabled, writing the frame buffer is defered + // until the next call to OnRenderDrawTriangles() or OnBeforeBufferSwap() + // m_must_write is not set to "true" here because it has already been set + // in OnBufferLockStartWrite() +} + +/* +void GlideFramebuffer::OnBufferNumPending() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnBufferNumPending()\n"); + #endif + + // Defer writing the frame buffer until the next call to + // OnRenderDrawTriangles() or OnBeforeBufferSwap(). + // Only the back buffer is checked as front and backbuffer locks + // share the same Glide buffer. + if (BackBufferIsLocked()) + { + // Update: This should be obsolete as the + // flag is set in OnAfterBufferSwap() + // m_must_write = true; + } +} +*/ + +/* +void GlideFramebuffer::OnSetIdle() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnSetIdle()\n"); + #endif + + // Defer writing the frame buffer until the next call to + // OnRenderDrawTriangles() or OnBeforeBufferSwap(). + // Only the back buffer is checked as front and backbuffer locks + // share the same Glide buffer. + if (BackBufferIsLocked()) + { + // Disabled in favour of better frame rates + // Uncomment if PedanticFrameBufferEmulation + // reveals otherwise unrendered graphics + // Update: This should be obsolete as the + // flag is set in OnAfterBufferSwap() + // m_must_write = true; + } +} +*/ + +void GlideFramebuffer::OnClipWindow() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnClipWindow()\n"); + #endif + + // When the clip window changes, and the pixel pipeline is enabled + // and the clip window applies to framebuffer writes, so the current + // contents of the frame buffer must be rendered. + // @todo: This must be reconsidered because it triggers all the time + if (m_framebuffer->PixelPipeline) + { + WriteFrameBuffer(true); + // Keep writing as the frame buffer may still be locked + m_must_write = m_framebuffer->Lock; + // @todo: Think this is obsolete as the case is catched by OnChromaKeyValueChanged() + if (m_chromakeyvalue_changed) + { + m_ChromaKey = m_chromakeyvalue_new; + m_chromakeyvalue_changed = false; + // Fill the framebuffer with the new chromakey value + m_must_clear_buffer = true; + } + if (m_must_write) + { + begin_write(); + } + } +} + +void GlideFramebuffer::OnBeforeBufferClear() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnBufferClear()\n"); + #endif + + // Render Carma retro mirror + if (s_GlideApplication.GetType() == GlideApplication::Carmageddon && + !InternalConfig.PedanticFrameBufferEmulation) + { + // ignore solid colored backgrounds (happens in some levels) + if (Glide.State.ColorMask == false) + { + m_bufferclearcalls++; + if (m_bufferclearcalls == 2) + { + // Trigger write in order to render cockpit layer before the retro mirror 3D-view +#ifdef OGL_FRAMEBUFFER + GlideMsg( "Triggering write in order to render cockpit layer before the retro mirror 3D-view\n"); +#endif + m_must_write = true; + } + else if (m_write_opaque == false) + { + // This is be needed to render the 3D-View in the map screen + // in levels without a background texture. In these levels, the + // background of the 3d_View is cleared by writing a fog colored + // rectangle to the framebuffer, and this data must be rendered + // before the 3D-View (or it will be deleted before buffer swap) +#ifdef OGL_FRAMEBUFFER + GlideMsg( "Triggering write in order to make 3D-View in map mode visible\n"); +#endif + m_must_write = true; + } + else if (m_framebuffer->Address[Glide.WindowTotalPixels >> 1] == m_ChromaKey) + { + // In Carmageddon, an opaque background is written to the frame buffer + // as the background for the Car Damage screen. By peeking just one pixel + // the framebuffer opaque render call can be avoided whilst in race mode. + // This triggers in levels with a background texture. +#ifdef OGL_FRAMEBUFFER + GlideMsg( "Detected background texture - skipping framebuffer underlay write\n"); +#endif + m_write_opaque = false; + m_must_write = false; + } + } + else + { + // In levels without background texture, the background is cleared with + // grBufferClear() during the race, and we can skip writing the underlays +#ifdef OGL_FRAMEBUFFER + GlideMsg( "Detected opaque background - Skipping framebuffer underlay write in order to improve frame rate\n"); +#endif + m_write_opaque = false; + m_must_write = false; + } + } +} + +void GlideFramebuffer::OnLfbReadRegion() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnLfbReadRegion()\n"); + #endif + + if (s_GlideApplication.GetType() == GlideApplication::Carmageddon) + { +#ifdef OPENGL_DEBUG + GlideMsg("Framebuffer unlocks will be ignored from now on in order to display the framebuffer's content\n"); +#endif + + // Carmageddon unlocks the write buffer when moving the cursor + // in Movie mode, causing its contents not being displayed anymore. + // To avoid this, we must ignore the unlock. + InternalConfig.FramebufferIgnoreUnlock = true; + } +} + +void GlideFramebuffer::OnRenderDrawTriangles() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnRenderDrawTriangles()\n"); + #endif + + // determine whether to write the underlays + if (m_write_opaque && m_must_write) + { + if (InternalConfig.EnableFrameBufferUnderlays) + { + // write underlays + end_write_opaque(); + } + else + { + // clear the buffer in order to prevent drawing the underlays + // as an overlay in a subsequent write + m_must_clear_buffer = true; + } + } + else if (InternalConfig.PedanticFrameBufferEmulation || m_must_write) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + // Need to start a new write + if (InternalConfig.PedanticFrameBufferEmulation) + { + if (m_chromakeyvalue_changed && m_framebuffer->PixelPipeline) + { + m_ChromaKey = m_chromakeyvalue_new; + m_chromakeyvalue_changed = false; + // Fill the framebuffer with the new chromakey value + m_must_clear_buffer = true; + } + begin_write(); + } + else + { + m_must_write = false; + } + // Once a triangle has been drawn, the framebuffer + // data must be considered as overlay graphics + m_write_opaque = false; +} + +void GlideFramebuffer::OnBeforeBufferSwap() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnBeforeBufferSwap()\n"); + #endif + + // apply the framebuffer changes? + if (InternalConfig.EnableFrameBufferOverlays) + { + // There's no check against the underlay flag here, because if no triangles + // have been drawn, then the display is rendered via the frame buffer only, + // and in that case, there's no such thing like under- and overlay. + if (m_write_opaque && m_must_write && !m_renderbuffer_changed) + { + end_write_opaque(); + } + else if (m_must_write) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + else if (BackBufferIsLocked()) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + m_must_write = false; + // optionally render the 3Dfx powerfield logo overlay on top of the frame + if (InternalConfig.ShamelessPlug) + { + // @todo: For apps that lock the frame buffer accross buffer swaps + // (for instance Carmageddon) the current state must be saved... + _grShamelessPlug(); + if (m_must_write) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + // ... and restored after rendering the shameless plug + } + } + else + { + m_must_clear_buffer = true; + } + m_must_write = false; +} + +void GlideFramebuffer::OnAfterBufferSwap() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnAfterBufferSwap()\n"); + #endif + + m_must_write = BackBufferIsLocked() || m_framebuffer->Lock; + m_write_opaque = true; + m_renderbuffer_changed = false; + m_renderbuffer_changed_for_read = true; + m_bufferclearcalls = 0; + begin_write(); +} + +void GlideFramebuffer::WriteFrameBuffer(bool pixelpipeline) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::WriteFrameBuffer(%d)\n", pixelpipeline); + #endif + + // apply the framebuffer changes? + if (InternalConfig.EnableFrameBufferOverlays) + { + // Only the back buffer is supported because games like Carmageddon + // temporarily lock and unlock the front buffer while holding the lock + // to the back buffer. Becasue he current implementation of the framebuffer + // emulation doesn't support locks to multiple buffers, data is written to + // the current buffer (which is usally the back buffer). + if (pixelpipeline) + { + end_write(m_alpha, m_depth, pixelpipeline); + } + else + { + end_write(); + } + } + else + { + m_must_clear_buffer = true; + } +} + +void GlideFramebuffer::Cleanup() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::Cleanup()\n"); + #endif + + free_buffers(); +} + +void GlideFramebuffer::CopyFrameBuffer(FxU16* targetbuffer) +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::CopyFrameBuffer( 0x%x)\n", targetbuffer); + #endif + + FxU16 chromakey = m_ChromaKey; + FxU16* framebuffer = m_framebuffer->Address; + FxU32 count = m_width * m_height; + for (FxU16* end = framebuffer + count; framebuffer < end; framebuffer++, targetbuffer++) + { + FxU16 pixel = *framebuffer; + if (pixel != chromakey) *targetbuffer = pixel; + } +} + +FxU16 GlideFramebuffer::GetChromaKeyValue16(GrColor_t chromakeyvalue) +{ + FxU16 chromakeyvalue16; + if (m_framebuffer->WriteMode == GR_LFBWRITEMODE_565) + { + chromakeyvalue16 = static_cast((chromakeyvalue & 0x00F80000) >> 8 | + (chromakeyvalue & 0x0000FC00) >> 5 | + (chromakeyvalue & 0x000000F8) >> 3); + } + else + { + chromakeyvalue16 = 0x0; + } + return chromakeyvalue16; +} + +void GlideFramebuffer::OnChromaKeyValueChanged() +{ + #ifdef OGL_FRAMEBUFFER + GlideMsg( "GlideFrameBuffer::OnChromaKeyColorChanged()\n"); + #endif + + FxU16 chromakeyvalue = GetChromaKeyValue16(Glide.State.ChromakeyValue); + m_chromakeyvalue_changed = m_ChromaKey != chromakeyvalue; + m_chromakeyvalue_new = chromakeyvalue; + if (m_must_write) + { + if (m_chromakeyvalue_changed && m_framebuffer->PixelPipeline) + { + // Flush the current contents of the framebuffer + WriteFrameBuffer(m_framebuffer->PixelPipeline); + m_ChromaKey = m_chromakeyvalue_new; + m_chromakeyvalue_changed = false; + // Fill the framebuffer with the new chromakey value + m_must_clear_buffer = true; + begin_write(); + } + } +} + +void GlideFramebuffer::SetAlpha(FxU32 alpha) +{ + if (m_must_write && m_framebuffer->PixelPipeline & m_alpha != alpha) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + m_alpha = alpha; +}; + +void GlideFramebuffer::SetDepth(GLfloat depth) +{ + if (m_must_write && m_framebuffer->PixelPipeline && m_depth != depth) + { + WriteFrameBuffer(m_framebuffer->PixelPipeline); + } + m_depth = depth; +}; diff --git a/MacGLide/OpenGLide/GlideFramebuffer.h b/MacGLide/OpenGLide/GlideFramebuffer.h new file mode 100644 index 0000000..262be75 --- /dev/null +++ b/MacGLide/OpenGLide/GlideFramebuffer.h @@ -0,0 +1,60 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Glide framebuffer emulation +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "Framebuffer.h" + +#define GR_LFBWRITEMODE_UNUSED (GR_LFBWRITEMODE_ANY -1) + +class GlideFramebuffer : protected Framebuffer +{ +public: + GlideFramebuffer(); + ~GlideFramebuffer(); +protected: + bool m_write_opaque; + bool m_must_write; + bool m_renderbuffer_changed; + bool m_renderbuffer_changed_for_read; + GLfloat m_depth; + FxU32 m_alpha; + bool m_chromakeyvalue_changed; + FxU16 m_chromakeyvalue_new; + GrLfbWriteMode_t m_grLfbLockWriteMode[6]; + unsigned int m_bufferclearcalls; + static const tilesize tilesize_table_carmageddon[11]; +public: + void initialise(BufferStruct* framebuffer, BufferStruct* texbuffer); + void OnBufferLockStartWrite(GrLock_t dwType, GrBuffer_t dwBuffer, GrLfbWriteMode_t dwWriteMode, GrOriginLocation_t dwOrigin, FxBool bPixelPipeline); + void OnBufferUnlockEndWrite(GrBuffer_t dwBuffer); + // void OnBufferNumPending(); + void OnBeforeBufferClear(); + void OnLfbReadRegion(); + void OnRenderDrawTriangles(); + void OnBeforeBufferSwap(); + void OnAfterBufferSwap(); + // void OnSetIdle(); + void OnClipWindow(); + void OnChromaKeyValueChanged(); + void Cleanup(); + void SetAlpha(FxU32 alpha); + void SetDepth(GLfloat depth); + FxU16 GetChromaKeyValue16(GrColor_t chromakeyvalue); + inline void SetRenderBufferChanged() {m_renderbuffer_changed = m_renderbuffer_changed_for_read = true;}; + inline bool GetRenderBufferChanged() const {return m_renderbuffer_changed;}; + inline bool GetRenderBufferChangedForRead() const {return m_renderbuffer_changed_for_read;}; + inline void ResetRenderBufferChangedForRead() {m_renderbuffer_changed_for_read = false;}; + void CopyFrameBuffer(FxU16* targetbuffer); + inline FxU16 GetChromaKeyValue() {return m_ChromaKey;}; +protected: + void WriteFrameBuffer(bool pixelpipline); + inline bool BackBufferIsLocked() {return m_grLfbLockWriteMode[GR_BUFFER_BACKBUFFER] != GR_LFBWRITEMODE_UNUSED;}; +}; diff --git a/MacGLide/OpenGLide/GlideSettings.cpp b/MacGLide/OpenGLide/GlideSettings.cpp new file mode 100644 index 0000000..8f37501 --- /dev/null +++ b/MacGLide/OpenGLide/GlideSettings.cpp @@ -0,0 +1,615 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlOgl.h" +#include "GlideSettings.h" +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Version numbers /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +const char* GlideSettings::OpenGLidePreferencesVersion = "0.13"; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +GlideSettings::GlideSettings() +: m_FileBuffer(NULL) +, m_FileBufferSize(0) +{ + defaults(); +} + +GlideSettings::~GlideSettings(void) +{ +} + +bool GlideSettings::get(const char* setting, const char** value) +{ + static char buffer[StringBufferSize]; + buffer[0] = 0x0; + bool found = false; + const char* v = m_FileBuffer; + while(!found && v) + { + v = strstr(v, setting); + if (v) + { + int s = strlen(setting); + // At the beginning of the line or tabbed and followed by '=' + if (v[-1] < 0x20 && v[s] == '=') + { + // found, point to begin of setting + v = v + s + 1; + // copy til end of line + sscanf(v, "%255s", buffer); + found = true; + } + } + } + *value = buffer; + if (!found) + { + GlideMsg("Setting '%s' not found, using default value\n", setting); + } + return found; +} + +bool GlideSettings::get(const char* setting, unsigned long* value) +{ + const char* v; + if (get(setting, &v)) + { + *value = atol(v); + return true; + } + else + { + // keep default value + return false; + } +} + +bool GlideSettings::get(const char* setting, float* value) +{ + const char* v; + if (get(setting, &v)) + { + *value = atof(v); + return true; + } + else + { + // keep default value + return false; + } +} + +bool GlideSettings::get(const char* setting, bool* value) +{ + const char* v; + if (get(setting, &v)) + { + *value = atol(v) != 0; + return true; + } + else + { + // keep default value + return false; + } +} + +void GlideSettings::defaults() +{ +#ifdef OGL_DEBUG + GlideMsg("Initialising to internal default settings...\n"); +#endif + // These are the default values that will end up in a new configuration file. + // OpenGL extensions that can be disabled via the config file must be set to + // true in order to become enabled in ValidateUserConfig() + Resolution = 1; + MonitorRefreshRate = 0; + DepthBufferBits = 0; + FullSceneAntiAliasing = 0; + GammaBias = -0.3f; + TextureSmoothing = false; + DisplayMode = OpenGLideDisplayMode_DisplayManager; + #ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + FogMode = OpenGLideFogEmulation_FogCoord; + #else + FogMode = OpenGLideFogEmulation_EnvCombine; + #endif + ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Automatic; + PrecisionFix = 1; + /* + // Not bad + GapFix = static_cast(OpenGLideGapFixFlag_Enabled | + OpenGLideGapFixFlag_IncircleOr | + OpenGLideGapFixFlag_DepthFactor); + GapFixParam1 = 3.0f; + GapFixParam2 = 10.0f; + GapFixParam3 = 3.0f; + GapFixDepthFactor = 3.3f; + */ + /* + // But this one is better + GapFix = static_cast(OpenGLideGapFixFlag_Enabled | + OpenGLideGapFixFlag_VertexLengthSecondRadius | + OpenGLideGapFixFlag_DepthFactor); + GapFixParam1 = 3.0f; + GapFixParam2 = 25.0f; + GapFixParam3 = 0.9f; + GapFixDepthFactor = 3.3f; + */ + // @todo: Let's make this even more better + GapFix = static_cast(/*OpenGLideGapFixFlag_Enabled |*/ + OpenGLideGapFixFlag_VertexLengthSecondRadius | + OpenGLideGapFixFlag_DepthFactor); + GapFixParam1 = 3.0f; + GapFixParam2 = 25.0f; + GapFixParam3 = 0.9f; + GapFixDepthFactor = 3.3f; + + GenerateSubTextures = 0; + Mipmapping = true; + AnisotropylLevel = 16; + IgnorePaletteChange = false; + ARB_multitexture = true; + EXT_paletted_texture = true; + EXT_texture_env_add = true; + EXT_texture_env_combine = true; + ATI_texture_env_combine3 = true; +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + EXT_fog_coord = true; +#endif +#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE + EXT_blend_func_separate = true; +#endif + EXT_texture_lod_bias = true; + EXT_secondary_color = true; + EXT_SGIS_generate_mipmap = true; + EXT_SGIS_texture_edge_clamp = true; + EXT_Client_Storage = true; + EXT_compiled_vertex_array = true; + EXT_texture_filter_anisotropic = true; + ARB_multisample = true; + NV_multisample_filter_hint = true; + EXT_clip_volume_hint = true; + APPLE_transform_hint = true; + TextureMemorySize = 16; + FrameBufferMemorySize = 8; + EnableFrameBufferOverlays = true; + EnableFrameBufferUnderlays = true; + FramebufferIgnoreUnlock = false; + PedanticFrameBufferEmulation = false; + BoardType = static_cast(GR_SSTTYPE_VOODOO); + GlideTextureUnits = 0; + NoSplash = false; + ShamelessPlug = false; + UseApplicationSpecificSettings = false; + AutoEnableGameSpecificSettings = true; +} + +GlideSettings::IOErr GlideSettings::read_settings() +{ +#ifdef OGL_DEBUG + GlideMsg("Reading values...\n"); +#endif + GlideSettings::IOErr err = noErr; + unsigned long value; + get("DisplayMode", &value); + DisplayMode = static_cast(value); + get("Resolution", &Resolution); + get("MonitorRefreshRate", &MonitorRefreshRate); + get("DepthBufferBits", &DepthBufferBits); + get("Mipmapping", &Mipmapping); + get("AnisotropylLevel", &AnisotropylLevel); + get("FullSceneAntiAliasing", &FullSceneAntiAliasing); + get("GammaBias", &GammaBias); + get("TextureSmoothing", &TextureSmoothing); + get("FogMode", &value); + FogMode = static_cast(value); + get("ColorAlphaRenderMode", &value); + ColorAlphaRenderMode = static_cast(value); + get("EnablePrecisionFix", &PrecisionFix); + get("GapFix", &value); + GapFix = static_cast(value); + get("GapFixParam1", &GapFixParam1); + get("GapFixParam2", &GapFixParam2); + get("GapFixParam3", &GapFixParam3); + get("GapFixDepthFactor", &GapFixDepthFactor); + get("GenerateSubTextures", &GenerateSubTextures); + get("IgnorePaletteChange", &IgnorePaletteChange); + get("TextureMemorySize", &TextureMemorySize); + get("FrameBufferMemorySize", &FrameBufferMemorySize); + get("EnableFrameBufferOverlays", &EnableFrameBufferOverlays); + get("EnableFrameBufferUnderlays", &EnableFrameBufferUnderlays); + get("FramebufferIgnoreUnlock", &FramebufferIgnoreUnlock); + get("PedanticFrameBufferEmulation", &PedanticFrameBufferEmulation); + get("CompiledVertexArray", &EXT_compiled_vertex_array); + get("EnableMultiTextureEXT", &ARB_multitexture); + get("EnablePaletteEXT", &EXT_paletted_texture); + get("EXT_clip_volume_hint", &EXT_clip_volume_hint); + get("BoardType", &value); + BoardType = static_cast(value); + get("GlideTextureUnits", &GlideTextureUnits); + get("NoSplash", &NoSplash); + get("ShamelessPlug", &ShamelessPlug); + get("UseApplicationSpecificSettings", &UseApplicationSpecificSettings); + get("AutoEnableGameSpecificSettings", &AutoEnableGameSpecificSettings); + return err; +} + +GlideSettings::IOErr GlideSettings::load() +{ +#ifdef OGL_DEBUG + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg("Loading settings from preferences directory...\n"); +#endif + const char* prefs_version = OpenGLidePreferencesVersion; + GlideSettings::IOErr err = read_defaults(); + if (err == noErr) + { + const char* version_complaint = "Unable to read version information from %s settings - using default values\n"; + const char* version; + bool success = get("Version", &version); + if (success) + { + GlideMsg("Settings file version = %s\n", version); + } + if (success && strcmp(version, prefs_version) == 0) + { + err = read_settings(); + } + else if (!success) + { + GlideMsg(version_complaint, "default"); + } + else + { + GlideMsg("Configuration outdated - Creating new default settings %s...\n", prefs_version); + defaults(); + err = create_defaults(); + if (err == noErr) + { + err = save(); + } + } + if (err == noErr) + { + if (UseApplicationSpecificSettings) + { + err = read(); + if (err == noErr) + { + success = get("Version", &version); + if (success && strcmp(version, prefs_version) == 0) + { + bool use_app_specific_settings = false; + success = get("UseApplicationSpecificSettings", &use_app_specific_settings); + if (use_app_specific_settings) + { + err = read_settings(); + } + } + else if (!success) + { + GlideMsg(version_complaint, "application specific"); + } + else + { + GlideMsg("Configuration outdated - Creating new application specific settings %s...\n", prefs_version); + defaults(); + err = create(); + if (err == noErr) + { + err = save(); + } + } + } + } + } +// if (!success) err = fnfErr; + } + return err; +} + +GlideSettings::IOErr GlideSettings::save() +{ +#ifdef OGL_DEBUG + GlideMsg("Saving...\n"); +#endif + put("Configuration File for MacGLide"); + put(); + put(); + put("Current version number of the settings file:" ); + put("Version", OpenGLidePreferencesVersion); + put(); + put("Enable to apply application specific settings:"); + put("UseApplicationSpecificSettings", UseApplicationSpecificSettings); + put(); + put("Video settings"); + put(); + put("Fullscreen display:"); + put("0 for windowed mode, 1 for fullscreen display"); + put("DisplayMode", static_cast(DisplayMode)); + put(); + put("Display resolution:"); + put("1-8: Multiplier for Glide resolution as requested by the"); + put("game/application. Any value equal or greater than 512:"); + put("fixed x resolution (y is computed for a 4/3 aspect ratio)"); + put("Resolution", Resolution); + put(); + put("Refresh rate of the monitor:"); + put("0 to use the Glide refresh rate as requested by the game/"); + put("application. Any other value equal or greater than 60(Hz):"); + put("Use fixed refresh rate"); + put("MonitorRefreshRate", MonitorRefreshRate); + put(); + put("Gamma bias value for the Glide display:"); + put("Most games adjust the gamma correction of the display."); + put("For certain monitors and LCD display the resulting gamma"); + put("correction might be too bright (probably because the"); + put("3Dfx-Hardware was never supposed to work with LCD displays)."); + put("Although most games provide a way to adjust the gamma"); + put("correction via their configuration dialog, it might be"); + put("necessary to set a reasonable default bias value."); + put("Reasonable bias values are -1.0 to 1.0."); + put("GammaBias", GammaBias); + put(); + put("Mip-Mapping: 0 to disable, 1 to enable mipmapped textures"); + put("Mipmapping", Mipmapping); + put(); + put("Anisotropic filtering:"); + put("0 or 1 to disable, 2, 4, 8, 16 to specify the quality"); + put("level of anisotropic filtering"); + put("AnisotropylLevel", AnisotropylLevel); + put(); + put("Fullscene antialiasing:"); + put("0 to disable, any other value to set number of samples to use"); + put("for antialiasing (currently this works with ATI cards only)"); + put("FullSceneAntiAliasing", FullSceneAntiAliasing); + put(); + put(); + put("Game specific settings (usually set automatically per application"); + put(); + put("Enable game specific settings automatically:"); + put("0 to disable, 1 to automatically certain enable game specific settings"); + put("The settings in this section don't work with all games. To avoid"); + put("problems, these settings are usually set individually for each game."); + put("AutoEnableGameSpecificSettings", AutoEnableGameSpecificSettings); + put(); + put("Texture smoothing:"); + put("0 to disable, 1 to enable texture filtering. Overrides Glide"); + put("texture filter settings in order to suppress blocky pixels."); + put("Some games don't like these filter settings to be changed, for"); + put("instance horizontal and vertical gaps may appear in texture-based"); + put("menu screens"); + put("TextureSmoothing", TextureSmoothing); + put(); + put("Texture artefact optimisation for Tomb Raider 1 & 2:"); + put("Tomb Raider joins a number of texture images within a"); + put("larger texture object. In conjunction with ansisotropic"); + put("filtering and mipmapping this cause artefacts at the"); + put("edges of single tiles/triangles."); + put("0 to disable, n (power of 2) to place each texture image"); + put("into a seperate OpenGL texture object. The value determines"); + put("the grid points and the minimal size of the generated"); + put("OpenGL textures."); + put("GenerateSubTextures", GenerateSubTextures); + put(); + put("Vertex gapfix optimisation for Tomb Raider 1 & 2:"); + put("Reduces gaps between tiles in the tomb raider series"); + put("(best observed in TR1, but TR2 is also affected)"); + put("A combination of the following values:"); + put("1=Enable, 2=Debug, 4=DepthFactor, 16=IncircleOr,"); + put("32=IncircleAnd, 64=IncircleSecondRadius,"); + put("128=VertexLengthSecondRadius"); + put("GapFix", static_cast(GapFix)); + put(); + put("Minimum pixel incircle of a triangle for applying the gapfix"); + put("GapFixParam1", GapFixParam1); + put(); + put("Minimum value of the isoscelesness or the maximum vertex"); + put("length of a triangle for applying the gapfix"); + put("(an isosceles triangle has a value of 10)"); + put("GapFixParam2", GapFixParam2); + put(); + put("Second minimum incircle of a triangle for applying the gapfix,"); + put(" this one is independent from the isoscelesness/vertex length"); + put("GapFixParam3", GapFixParam3); + put(); + put("Multiplies the incircles/isoscelesness with the vertex depth to"); + put("allow applying the gapfix to smaller triangles in the background"); + put("GapFixDepthFactor", GapFixDepthFactor); + put(); + put(); + put("Various settings that affect the rendering quality."); + put(); + put("Fog emulation method:"); + put("0 to disable, 1 for simple, 2 for complete fog emulation"); + put("FogMode", static_cast(FogMode)); + put(); + put("The renderer to be used to emulate the Glide color and alpha"); + put("combine unit. 0 for automatic selection, 1 for simple (0.10),"); + put("2 for enhanced, and 3 for enhanced ATI optimised emulation"); + put("ColorAlphaRenderMode", static_cast(ColorAlphaRenderMode)); + put(); + put("Number of bits to use for the depth buffer:"); + put("0: automatic (attempts to use the largest possible value)"); + put("16, 24, 32: use the specified number of bits for the depth buffer"); + put("DepthBufferBits", DepthBufferBits); + put(); + put("Depth precision fix: attempts to avoid depth precision"); + put("problems on graphic cards with only 16bit-zbuffer depth"); + put("0 = always off, 1 = automatic, 2 = always on"); + put("EnablePrecisionFix", PrecisionFix); + put(); + put(); + put("Various debug settings"); + put(); + put("IgnorePaletteChange", IgnorePaletteChange); + put("EnableFrameBufferOverlays", EnableFrameBufferOverlays); + put("EnableFrameBufferUnderlays", EnableFrameBufferUnderlays); + put("FramebufferIgnoreUnlock", FramebufferIgnoreUnlock); + put("PedanticFrameBufferEmulation", PedanticFrameBufferEmulation); + put("CompiledVertexArray", EXT_compiled_vertex_array); + put("EnableMultiTextureEXT", ARB_multitexture); + put("EnablePaletteEXT", EXT_paletted_texture); + put("EXT_clip_volume_hint", EXT_clip_volume_hint); + put(); + put(); + put("Glide hardware settings"); + put(); + putv("Texture Memory goes from %d to %d", OGL_MIN_TEXTURE_BUFFER, OGL_MAX_TEXTURE_BUFFER); + put("TextureMemorySize", TextureMemorySize); + put(); + putv("Frame Buffer Memory goes from %d to %d", OGL_MIN_FRAME_BUFFER, OGL_MAX_FRAME_BUFFER); + put("FrameBufferMemorySize", FrameBufferMemorySize); + put(); + put("The hardware we're pretending to be emulating"); + put("(This has no effect on the emulation, but games may change"); + put("their behaviour/features depending on this setting)"); + put("0 = Voodoo, 1 = SST-96, 2 = AT3D, 3 = Voodoo 2"); + put("BoardType", static_cast(BoardType)); + put(); + put("The number of emulated Glide texture units (TMUs)"); + put("0 = as many as possible, 1-3 number of emulated TMUs"); + put("GlideTextureUnits", GlideTextureUnits); + put(); + put("0 to display the cool splash animation on startup,"); + put("or 1 to supress the annoying splash animation"); + put("NoSplash", NoSplash); + put(); + put("Shows the 3Dfx logo in the lower right corner of the screen"); + put("ShamelessPlug", ShamelessPlug); + GlideSettings::IOErr err = close(); + return err; +} + +GlideSettings::IOErr GlideSettings::put() +{ + return put_raw("\n"); +} + +GlideSettings::IOErr GlideSettings::put(const char* string) +{ + GlideSettings::IOErr err = put_raw("# "); + if (err == noErr) + { + err = put_raw(string); + if (err == noErr) + { + put(); + } + } + return err; +} + +GlideSettings::IOErr GlideSettings::putv(const char* format, ...) +{ + va_list(args); + va_start(args, format); + char buffer[StringBufferSize]; + vsnprintf(buffer, StringBufferSize, format, args ); + GlideSettings::IOErr err = put(buffer); + va_end(args); + return err; +} + +GlideSettings::IOErr GlideSettings::put(unsigned long value) +{ + GlideSettings::IOErr err = noErr; + char buffer[StringBufferSize]; + if (snprintf(buffer, StringBufferSize, "%d", value) > 0) + { + err = put_raw(buffer); + } + return err; +} + +GlideSettings::IOErr GlideSettings::put(const char* setting, const char* value) +{ + GlideSettings::IOErr err = put_raw(setting); + if (err == noErr) + { + err = put_raw("="); + if (err == noErr) + { + err = put_raw(value); + if (err == noErr) + { + err = put_raw("\n"); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettings::put(const char* setting, unsigned long value) +{ + GlideSettings::IOErr err = put_raw(setting); + if (err == noErr) + { + err = put_raw("="); + if (err == noErr) + { + char buffer[StringBufferSize]; + if (snprintf(buffer, StringBufferSize, "%d", value) > 0) + { + err = put_raw(buffer); + } + if (err == noErr) + { + err = put_raw("\n"); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettings::put(const char* setting, float value) +{ + GlideSettings::IOErr err = put_raw(setting); + if (err == noErr) + { + err = put_raw("="); + if (err == noErr) + { + char buffer[StringBufferSize]; + if (snprintf(buffer, StringBufferSize, "%g", value) > 0) + { + err = put_raw(buffer); + } + if (err == noErr) + { + err = put_raw("\n"); + } + } + } + return err; +} + +GlideSettings::IOErr GlideSettings::put(const char* setting, bool value) +{ + return put(setting, value ? "1" : "0"); +} diff --git a/MacGLide/OpenGLide/GlideSettings.h b/MacGLide/OpenGLide/GlideSettings.h new file mode 100644 index 0000000..cbdf1e8 --- /dev/null +++ b/MacGLide/OpenGLide/GlideSettings.h @@ -0,0 +1,156 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "sdk2_glide.h" + +enum OpenGLideDisplayMode +{ + OpenGLideDisplayMode_Window = 0, + OpenGLideDisplayMode_DisplayManager = 1, + OpenGLideDisplayMode_aglSetFullScreen = 2 +}; + +enum OpenGLideFogEmulation +{ + OpenGLideFogEmulation_None = 0, + OpenGLideFogEmulation_Simple = 1, + OpenGLideFogEmulation_EnvCombine = 2 +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + , + OpenGLideFogEmulation_FogCoord = 3 +#endif +}; + +enum OpenGLideColorAlphaRenderMode +{ + OpenGLideColorAlphaRenderMode_Automatic = 0, + OpenGLideColorAlphaRenderMode_Simple = 1, + OpenGLideColorAlphaRenderMode_EnvCombine_ARB = 2, + OpenGLideColorAlphaRenderMode_EnvCombine3_ATI = 3, + OpenGLideColorAlphaRenderMode_Unknown = 4 +}; + +enum OpenGLideBoardType +{ + OpenGLideBoardType_Voodoo = GR_SSTTYPE_VOODOO, + OpenGLideBoardType_VoodooRush = GR_SSTTYPE_SST96, + OpenGLideBoardType_AT3D = GR_SSTTYPE_AT3D, + OpenGLideBoardType_Voodoo2 = GR_SSTTYPE_Voodoo2 +}; + +enum OpenGLideGapFixFlags +{ + OpenGLideGapFixFlag_Disabled = 0x00, + OpenGLideGapFixFlag_Enabled = 0x01, + OpenGLideGapFixFlag_Debug = 0x02, + OpenGLideGapFixFlag_DepthFactor = 0x04, + OpenGLideGapFixFlag_IncircleOr = 0x10, + OpenGLideGapFixFlag_IncircleAnd = 0x20, + OpenGLideGapFixFlag_IncircleSecondRadius = 0x40, + OpenGLideGapFixFlag_VertexLengthSecondRadius = 0x80 +}; + +struct ConfigStruct +{ + OpenGLideDisplayMode DisplayMode; + unsigned long Resolution; + unsigned long MonitorRefreshRate; + unsigned long DepthBufferBits; + unsigned long FullSceneAntiAliasing; + float GammaBias; + bool TextureSmoothing; + OpenGLideFogEmulation FogMode; + OpenGLideColorAlphaRenderMode ColorAlphaRenderMode; + unsigned long PrecisionFix; + OpenGLideGapFixFlags GapFix; + float GapFixParam1; + float GapFixParam2; + float GapFixParam3; + float GapFixDepthFactor; + unsigned long GenerateSubTextures; + unsigned long TextureMemorySize; + unsigned long FrameBufferMemorySize; + unsigned long AnisotropylLevel; + bool Mipmapping; + bool IgnorePaletteChange; + bool EXT_secondary_color; + bool ARB_multitexture; + bool EXT_texture_env_add; + bool EXT_texture_env_combine; + bool ATI_texture_env_combine3; + bool EXT_texture_lod_bias; + bool EXT_paletted_texture; + bool EXT_SGIS_generate_mipmap; + bool EXT_SGIS_texture_edge_clamp; + bool EXT_Client_Storage; + bool EXT_compiled_vertex_array; +#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD + bool EXT_fog_coord; +#endif +#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE + bool EXT_blend_func_separate; +#endif + bool EXT_texture_filter_anisotropic; + bool ARB_multisample; + bool NV_multisample_filter_hint; + bool EXT_clip_volume_hint; + bool APPLE_transform_hint; + bool EnableFrameBufferOverlays; + bool EnableFrameBufferUnderlays; + bool FramebufferIgnoreUnlock; + bool PedanticFrameBufferEmulation; + OpenGLideBoardType BoardType; + unsigned long GlideTextureUnits; + bool NoSplash; + bool ShamelessPlug; + bool UseApplicationSpecificSettings; + bool AutoEnableGameSpecificSettings; +}; + +class GlideSettings : public ConfigStruct +{ +protected: + static const char* OpenGLidePreferencesVersion; +public: + GlideSettings(); + virtual ~GlideSettings(void); +public: + typedef int IOErr; + virtual IOErr init(const char* application)=0; + IOErr load(); + IOErr save(); + virtual IOErr create_log()=0; + virtual IOErr write_log(const char* message)=0; + virtual IOErr create_defaults()=0; + virtual IOErr create()=0; +protected: + void defaults(); + virtual IOErr read_defaults()=0; + virtual IOErr read()=0; + IOErr read_settings(); + bool get(const char* setting, const char** value); + bool get(const char* setting, unsigned long* value); + bool get(const char* setting, float* value); + bool get(const char* setting, bool* value); + virtual IOErr put_raw(const char* string)=0; + virtual IOErr close()=0; + IOErr put(); + IOErr put(const char* string); + IOErr putv(const char* format, ...); + IOErr put(unsigned long value); + IOErr put(const char* setting, const char* value); + IOErr put(const char* setting, unsigned long value); + IOErr put(const char* setting, float value); + IOErr put(const char* setting, bool value); + char* m_FileBuffer; + long m_FileBufferSize; +}; diff --git a/MacGLide/OpenGLide/GlideSettings_iostream.cpp b/MacGLide/OpenGLide/GlideSettings_iostream.cpp new file mode 100644 index 0000000..752dcb3 --- /dev/null +++ b/MacGLide/OpenGLide/GlideSettings_iostream.cpp @@ -0,0 +1,77 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideSettings_iostream.h" + +GlideSettingsIOStream::GlideSettingsIOStream() +{ +} + +GlideSettingsIOStream::~GlideSettingsIOStream(void) +{ + if (m_FileBuffer) delete(m_FileBuffer); +} + +GlideSettings::IOErr GlideSettingsIOStream::init(const char* applicationname) +{ + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::read_defaults() +{ +#ifdef OGL_DEBUG + GlideMsg("Reading default settings...\n"); +#endif + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::read() +{ +#ifdef OGL_DEBUG + GlideMsg("Reading application specific settings...\n"); +#endif + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::create_defaults() +{ +#ifdef OGL_DEBUG + GlideMsg("Creating new file with default settings...\n"); +#endif + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::create() +{ +#ifdef OGL_DEBUG + GlideMsg("Creating new file with application specific settings...\n"); +#endif + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::put_raw(const char* string) +{ + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::close() +{ + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::create_log() +{ + return -1; +} + +GlideSettings::IOErr GlideSettingsIOStream::write_log(const char* message) +{ + return -1; +} diff --git a/MacGLide/OpenGLide/GlideSettings_iostream.h b/MacGLide/OpenGLide/GlideSettings_iostream.h new file mode 100755 index 0000000..62dc672 --- /dev/null +++ b/MacGLide/OpenGLide/GlideSettings_iostream.h @@ -0,0 +1,31 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* OpenGLide Settings File +//* +//* OpenGLide is OpenSource under LGPL license +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "GlideSettings.h" + +class GlideSettingsIOStream : public GlideSettings +{ +public: + GlideSettingsIOStream(); + virtual ~GlideSettingsIOStream(void); +public: + IOErr init(const char* application); + IOErr create_log(); + IOErr write_log(const char* message); +protected: + IOErr create_defaults(); + IOErr create(); + IOErr read_defaults(); + IOErr read(); + IOErr put_raw(const char* string); + IOErr close(); +}; diff --git a/MacGLide/OpenGLide/OGLColorAlphaTables.cpp b/MacGLide/OpenGLide/OGLColorAlphaTables.cpp new file mode 100644 index 0000000..71edff5 --- /dev/null +++ b/MacGLide/OpenGLide/OGLColorAlphaTables.cpp @@ -0,0 +1,543 @@ + +#include "GLRender.h" +#include "OGLTables.h" + +const OGLColorTable colorCombineTable[ 14 ][ 17 ] = +{ + { // GR_COMBINE_FACTOR_ZERO 0x0 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3Zero, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3Zero, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, false, false, ColorFactor3Zero, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, false, false, false, ColorFactor3Zero, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, false, true, false, ColorFactor3Zero, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, false, false, ColorFactor3Zero, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, false, false, false, ColorFactor3Zero, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { false, false, true, false, ColorFactor3Zero, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3Zero, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xf + { false, false, true, false, ColorFactor3Zero, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_LOCAL 0x1 + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3Local, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3Local, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, false, false, ColorFactor3Local, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3Local, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, true, false, ColorFactor3Local, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3Local, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3Local, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3Local, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3Local, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3Local, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3Local, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_OTHER_ALPHA 0x2 + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3OtherAlpha, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3OtherAlpha, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, true, ColorFactor3OtherAlpha, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, true, ColorFactor3OtherAlpha, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, true, ColorFactor3OtherAlpha, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, true, ColorFactor3OtherAlpha, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, true, ColorFactor3OtherAlpha, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, true, ColorFactor3OtherAlpha, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, true, ColorFactor3OtherAlpha, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3OtherAlpha, ColorFunctionZero }, // 0xf + { true, false, true, true, ColorFactor3OtherAlpha, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_LOCAL_ALPHA 0x3 + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3LocalAlpha, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3LocalAlpha, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3LocalAlpha, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, true, false, ColorFactor3LocalAlpha, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3LocalAlpha, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3LocalAlpha, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_TEXTURE_ALPHA 0x4 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3One, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3One, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, false, ColorFactor3One, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3One, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3One, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3One, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_TEXTURE_RGB 0x5 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3One, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3One, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, false, ColorFactor3One, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3One, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3One, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3One, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // 6 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xf + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // 7 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero }, // 0xf + { false, false, false, false, ColorFactor3Zero, ColorFunctionZero } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE 0x8 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3One, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3One, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, false, ColorFactor3One, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3One, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3One, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3One, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOCAL 0x9 + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3OneMinusLocal, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, false, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, true, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3OneMinusLocal, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3OneMinusLocal, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3OneMinusLocal, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA 0xa + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3OneMinusOtherAlpha, ColorFunctionZero }, // 0xf + { true, false, true, true, ColorFactor3OneMinusOtherAlpha, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA 0xb + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3OneMinusLocalAlpha, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3One, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3One, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, false, ColorFactor3One, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3One, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3One, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3One, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, false, false, ColorFactor3One, ColorFunctionLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, true, false, ColorFactor3One, ColorFunctionLocalAlpha }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, false, false, ColorFactor3One, ColorFunctionScaleOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, true, true, false, ColorFactor3One, ColorFunctionScaleOtherAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, false, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, true, false, ColorFactor3One, ColorFunctionScaleOtherMinusLocalAddLocalAlpha }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, false, false, ColorFactor3One, ColorFunctionMinusLocalAddLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xa + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xb + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xc + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xd + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xe + { false, false, false, false, ColorFactor3One, ColorFunctionZero }, // 0xf + { true, false, true, false, ColorFactor3One, ColorFunctionMinusLocalAddLocalAlpha } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + } +}; + +const OGLAlphaTable alphaCombineTable[ 14 ][ 17 ] = +{ + { // GR_COMBINE_FACTOR_ZERO 0x0 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorZero }, // 0xa + { false, false, AlphaFactorZero }, // 0xb + { false, false, AlphaFactorZero }, // 0xc + { false, false, AlphaFactorZero }, // 0xd + { false, false, AlphaFactorZero }, // 0xe + { false, false, AlphaFactorZero }, // 0xf + { true, false, AlphaFactorZero } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_LOCAL 0x1 + { false, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorLocal }, // 0xa + { false, false, AlphaFactorLocal }, // 0xb + { false, false, AlphaFactorLocal }, // 0xc + { false, false, AlphaFactorLocal }, // 0xd + { false, false, AlphaFactorLocal }, // 0xe + { false, false, AlphaFactorLocal }, // 0xf + { true, false, AlphaFactorLocal } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_OTHER_ALPHA 0x2 + { false, false, AlphaFactorOther }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOther }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOther }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, true, AlphaFactorOther }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOther }, // 0xa + { false, false, AlphaFactorOther }, // 0xb + { false, false, AlphaFactorOther }, // 0xc + { false, false, AlphaFactorOther }, // 0xd + { false, false, AlphaFactorOther }, // 0xe + { false, false, AlphaFactorOther }, // 0xf + { true, true, AlphaFactorOther } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_LOCAL_ALPHA 0x3 + { false, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorLocal }, // 0xa + { false, false, AlphaFactorLocal }, // 0xb + { false, false, AlphaFactorLocal }, // 0xc + { false, false, AlphaFactorLocal }, // 0xd + { false, false, AlphaFactorLocal }, // 0xe + { false, false, AlphaFactorLocal }, // 0xf + { true, false, AlphaFactorLocal } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_TEXTURE_ALPHA 0x4 + { false, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOne }, // 0xa + { false, false, AlphaFactorOne }, // 0xb + { false, false, AlphaFactorOne }, // 0xc + { false, false, AlphaFactorOne }, // 0xd + { false, false, AlphaFactorOne }, // 0xe + { false, false, AlphaFactorOne }, // 0xf + { true, false, AlphaFactorOne } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_TEXTURE_RGB 0x5 + { false, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOne }, // 0xa + { false, false, AlphaFactorOne }, // 0xb + { false, false, AlphaFactorOne }, // 0xc + { false, false, AlphaFactorOne }, // 0xd + { false, false, AlphaFactorOne }, // 0xe + { false, false, AlphaFactorOne }, // 0xf + { true, false, AlphaFactorOne } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // 6 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorZero }, // 0xa + { false, false, AlphaFactorZero }, // 0xb + { false, false, AlphaFactorZero }, // 0xc + { false, false, AlphaFactorZero }, // 0xd + { false, false, AlphaFactorZero }, // 0xe + { false, false, AlphaFactorZero }, // 0xf + { false, false, AlphaFactorZero } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // 7 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { false, false, AlphaFactorZero }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorZero }, // 0xa + { false, false, AlphaFactorZero }, // 0xb + { false, false, AlphaFactorZero }, // 0xc + { false, false, AlphaFactorZero }, // 0xd + { false, false, AlphaFactorZero }, // 0xe + { false, false, AlphaFactorZero }, // 0xf + { false, false, AlphaFactorZero } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE 0x8 + { false, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOne }, // 0xa + { false, false, AlphaFactorOne }, // 0xb + { false, false, AlphaFactorOne }, // 0xc + { false, false, AlphaFactorOne }, // 0xd + { false, false, AlphaFactorOne }, // 0xe + { false, false, AlphaFactorOne }, // 0xf + { true, false, AlphaFactorOne } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOCAL 0x9 + { false, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOneMinusLocal }, // 0xa + { false, false, AlphaFactorOneMinusLocal }, // 0xb + { false, false, AlphaFactorOneMinusLocal }, // 0xc + { false, false, AlphaFactorOneMinusLocal }, // 0xd + { false, false, AlphaFactorOneMinusLocal }, // 0xe + { false, false, AlphaFactorOneMinusLocal }, // 0xf + { true, false, AlphaFactorOneMinusLocal } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA 0xa + { false, false, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, true, AlphaFactorOneMinusOther }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOneMinusOther }, // 0xa + { false, false, AlphaFactorOneMinusOther }, // 0xb + { false, false, AlphaFactorOneMinusOther }, // 0xc + { false, false, AlphaFactorOneMinusOther }, // 0xd + { false, false, AlphaFactorOneMinusOther }, // 0xe + { false, false, AlphaFactorOneMinusOther }, // 0xf + { true, true, AlphaFactorOneMinusOther } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA 0xb + { false, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOneMinusLocal }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOneMinusLocal }, // 0xa + { false, false, AlphaFactorOneMinusLocal }, // 0xb + { false, false, AlphaFactorOneMinusLocal }, // 0xc + { false, false, AlphaFactorOneMinusLocal }, // 0xd + { false, false, AlphaFactorOneMinusLocal }, // 0xe + { false, false, AlphaFactorOneMinusLocal }, // 0xf + { true, false, AlphaFactorOneMinusLocal } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA 0xc + { false, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOne }, // 0xa + { false, false, AlphaFactorOne }, // 0xb + { false, false, AlphaFactorOne }, // 0xc + { false, false, AlphaFactorOne }, // 0xd + { false, false, AlphaFactorOne }, // 0xe + { false, false, AlphaFactorOne }, // 0xf + { true, false, AlphaFactorOne } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + }, + { // GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION 0xd + { false, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_ZERO 0x0 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL 0x1 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 + { false, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 + { true, true, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 + { true, false, AlphaFactorOne }, // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 + { false, false, AlphaFactorOne }, // 0xa + { false, false, AlphaFactorOne }, // 0xb + { false, false, AlphaFactorOne }, // 0xc + { false, false, AlphaFactorOne }, // 0xd + { false, false, AlphaFactorOne }, // 0xe + { false, false, AlphaFactorOne }, // 0xf + { true, false, AlphaFactorOne } // GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + } +}; diff --git a/MacGLide/OpenGLide/OGLFogTables.cpp b/MacGLide/OpenGLide/OGLFogTables.cpp new file mode 100644 index 0000000..ad17e6f --- /dev/null +++ b/MacGLide/OpenGLide/OGLFogTables.cpp @@ -0,0 +1,39 @@ + +#include "OGLTables.h" + +const FxU32 intStartEnd[ GR_FOG_TABLE_SIZE + 1 ] = +{ + 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 8, 9, 11, 13, 16, 19, 22, 26, 32, 38, 45, 53, + 64, 76, 90, 107, 128, 152, 181, 215, 256, 304, 362, 430, 512, 608, 724, 861, + 1024, 1217, 1448, 1722, 2048, 2435, 2896, 3444, 4096, 4870, 5792, 6888, 8192, + 9741, 11585, 13777, 16384, 19483, 23170, 27554, 32768, 38967, 46340, 55108, 65536 +}; + +const FxU32 intEndMinusStart[ GR_FOG_TABLE_SIZE ] = +{ + 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 2, 2, 3, 3, 3, 4, 6, 6, 7, 8, 11, 12, 14, + 17, 21, 24, 29, 34, 41, 48, 58, 68, 82, 96, 116, 137, 163, 193, 231, 274, 326, + 387, 461, 548, 652, 774, 922, 1096, 1304, 1549, 1844, 2192, 2607, 3099, 3687, + 4384, 5214, 6199, 7373, 8768, 10428 +}; + +const float tableIndexToW[ GR_FOG_TABLE_SIZE ] = +{ + 1.000000f, 1.142857f, 1.333333f, 1.600000f, + 2.000000f, 2.285714f, 2.666667f, 3.200000f, + 4.000000f, 4.571429f, 5.333333f, 6.400000f, + 8.000000f, 9.142858f, 10.666667f, 12.800000f, + 16.000000f, 18.285715f, 21.333334f, 25.600000f, + 32.000000f, 36.571430f, 42.666668f, 51.200001f, + 64.000000f, 73.142860f, 85.333336f, 102.400002f, + 128.000000f, 146.285721f, 170.666672f, 204.800003f, + 256.000000f, 292.571442f, 341.333344f, 409.600006f, + 512.000000f, 585.142883f, 682.666687f, 819.200012f, + 1024.000000f, 1170.285767f, 1365.333374f, 1638.400024f, + 2048.000000f, 2340.571533f, 2730.666748f, 3276.800049f, + 4096.000000f, 4681.143066f, 5461.333496f, 6553.600098f, + 8192.000000f, 9362.286133f, 10922.666992f, 13107.200195f, + 16384.000000f, 18724.572266f, 21845.333984f, 26214.400391f, + 32768.000000f, 37449.144531f, 43690.667969f, 52428.800781f +}; + diff --git a/MacGLide/OpenGLide/OGLMiscTables.cpp b/MacGLide/OpenGLide/OGLMiscTables.cpp new file mode 100644 index 0000000..27ec228 --- /dev/null +++ b/MacGLide/OpenGLide/OGLMiscTables.cpp @@ -0,0 +1,36 @@ + +#include "OGLTables.h" + + +const OGLWindow windowDimensions[ 16 ] = +{ + { 320, 200 }, // GR_RESOLUTION_320x200 + { 320, 240 }, // GR_RESOLUTION_320x240 + { 400, 256 }, // GR_RESOLUTION_400x256 + { 512, 384 }, // GR_RESOLUTION_512x384 + { 640, 200 }, // GR_RESOLUTION_640x200 + { 640, 350 }, // GR_RESOLUTION_640x350 + { 640, 400 }, // GR_RESOLUTION_640x400 + { 640, 480 }, // GR_RESOLUTION_640x480 + { 800, 600 }, // GR_RESOLUTION_800x600 + { 960, 720 }, // GR_RESOLUTION_960x720 + { 856, 480 }, // GR_RESOLUTION_856x480: + { 512, 256 }, // GR_RESOLUTION_512x256: + { 1024, 768 }, // GR_RESOLUTION_1024x768: + { 1280, 1024 }, // GR_RESOLUTION_1280x1024: + { 1600, 1200 }, // GR_RESOLUTION_1600x1200: + { 400, 300 } // GR_RESOLUTION_400x300: +}; + +const int windowRefresh[ 9 ] = +{ + 60, // GR_REFRESH_60Hz + 70, // GR_REFRESH_70Hz + 72, // GR_REFRESH_72Hz + 75, // GR_REFRESH_75Hz + 80, // GR_REFRESH_80Hz + 90, // GR_REFRESH_90Hz + 100, // GR_REFRESH_100Hz + 85, // GR_REFRESH_85Hz + 120 // GR_REFRESH_120Hz +}; diff --git a/MacGLide/OpenGLide/OGLTables.h b/MacGLide/OpenGLide/OGLTables.h new file mode 100644 index 0000000..07c8650 --- /dev/null +++ b/MacGLide/OpenGLide/OGLTables.h @@ -0,0 +1,63 @@ + +#ifndef __OGL_TABLES_H__ +#define __OGL_TABLES_H__ + +#include "glogl.h" +#include "GLRender.h" + +typedef struct +{ + float h; + float w; +} OGLAspect; + +typedef struct +{ + int width; + int height; +} OGLWindow; + +typedef struct +{ + int width; + int height; + int numPixels; +} OGLTexInfo; + +typedef struct +{ + bool local; + bool other; + ALPHAFACTORFUNCPROC func; +} OGLAlphaTable; + +typedef struct +{ + bool local; + bool other; + bool alocal; + bool aother; + COLORFACTORFUNCPROC factorfunc; + COLORFUNCTIONPROC func; +} OGLColorTable; + +// OGLTextureTables.cpp +extern const OGLAspect texAspects[ 7 ]; +extern const OGLTexInfo texInfo[ 7 ][ 9 ]; +extern const FxU32 nSquareLod[ 2 ][ 7 ][ 9 ]; +extern const FxU32 nSquareTexLod[ 2 ][ 7 ][ 9 ][ 9 ]; + +// OGLColorAlphaTables.cpp +extern const OGLAlphaTable alphaCombineTable[ 14 ][ 17 ]; +extern const OGLColorTable colorCombineTable[ 14 ][ 17 ]; + +// OGLFogTables.cpp +extern const FxU32 intStartEnd[ GR_FOG_TABLE_SIZE + 1 ]; +extern const FxU32 intEndMinusStart[ GR_FOG_TABLE_SIZE ]; +extern const float tableIndexToW[ GR_FOG_TABLE_SIZE ]; + +// OGLMiscTables.cpp +extern const OGLWindow windowDimensions[ 16 ]; +extern const int windowRefresh[ 9 ]; + +#endif diff --git a/MacGLide/OpenGLide/OGLTextureTables.cpp b/MacGLide/OpenGLide/OGLTextureTables.cpp new file mode 100644 index 0000000..510177a --- /dev/null +++ b/MacGLide/OpenGLide/OGLTextureTables.cpp @@ -0,0 +1,239 @@ + +#include "OGLTables.h" + + +const OGLAspect texAspects[ 7 ] = +{ + { D8OVER256, D1OVER256 }, // GR_ASPECT_8x1 + { D4OVER256, D1OVER256 }, // GR_ASPECT_4x1 + { D2OVER256, D1OVER256 }, // GR_ASPECT_2x1 + { D1OVER256, D1OVER256 }, // GR_ASPECT_1x1 + { D1OVER256, D2OVER256 }, // GR_ASPECT_1x2 + { D1OVER256, D4OVER256 }, // GR_ASPECT_1x4 + { D1OVER256, D8OVER256 } // GR_ASPECT_1x8 +}; + +const OGLTexInfo texInfo[ 7 ][ 9 ] = +{ + { // GR_ASPECT_8x1 + { 256, 32, 8192 }, { 128, 16, 2048 }, { 64, 8, 512 }, + { 32, 4, 128 }, { 16, 2, 32 }, { 8, 1, 8 }, + { 4, 1, 4 }, { 2, 1, 2 }, { 1, 1, 1 } + }, + { // GR_ASPECT_4x1 + { 256, 64, 16384 }, { 128, 32, 4096 }, { 64, 16, 1024 }, + { 32, 8, 256 }, { 16, 4, 64 }, { 8, 2, 16 }, + { 4, 1, 4 }, { 2, 1, 2 }, { 1, 1, 1 } + }, + { // GR_ASPECT_2x1 + { 256, 128, 32768 }, { 128, 64, 8192 }, { 64, 32, 2048 }, + { 32, 16, 512 }, { 16, 8, 128 }, { 8, 4, 32 }, + { 4, 2, 8 }, { 2, 1, 2 }, { 1, 1, 1 } + }, + { // GR_ASPECT_1x1 + { 256, 256, 65536 }, { 128, 128, 16384 }, { 64, 64, 4096 }, + { 32, 32, 1024 }, { 16, 16, 256 }, { 8, 8, 64 }, + { 4, 4, 16 }, { 2, 2, 4 }, { 1, 1, 1 } + }, + { // GR_ASPECT_1x2 + { 128, 256, 32768 }, { 64, 128, 8192 }, { 32, 64, 2048 }, + { 16, 32, 512 }, { 8, 16, 128 }, { 4, 8, 32 }, + { 2, 4, 8 }, { 1, 2, 2 }, { 1, 1, 1 } + }, + { // GR_ASPECT_1x4 + { 64, 256, 16384 }, { 32, 128, 4096 }, { 16, 64, 1024 }, + { 8, 32, 256 }, { 4, 16, 64 }, { 2, 8, 16 }, + { 1, 4, 4 }, { 1, 2, 2 }, { 1, 1, 1 } + }, + { // GR_ASPECT_1x8 + { 32, 256, 8192 }, { 16, 128, 2048 }, { 8, 64, 512 }, + { 4, 32, 128 }, { 2, 16, 32 }, { 1, 8, 8 }, + { 1, 4, 4 }, { 1, 2, 2 }, { 1, 1, 1 } + } +}; + +const FxU32 nSquareLod[ 2 ][ 7 ][ 9 ] = +{ + { + { 8192, 2048, 512, 128, 32, 8, 2, 1, 1 }, + { 16384, 4096, 1024, 256, 64, 16, 4, 1, 1 }, + { 32768, 8192, 2048, 512, 128, 32, 8, 2, 1 }, + { 65536, 16384, 4096, 1024, 256, 64, 16, 4, 1 }, + { 32768, 8192, 2048, 512, 128, 32, 8, 2, 1 }, + { 16384, 4096, 1024, 256, 64, 16, 4, 1, 1 }, + { 8192, 2048, 512, 128, 32, 8, 2, 1, 1 } + }, + { + { 16384, 4096, 1024, 256, 64, 16, 4, 1, 1 }, + { 32768, 8192, 2048, 512, 128, 32, 8, 2, 1 }, + { 65536, 16384, 4096, 1024, 256, 64, 16, 4, 1 }, + { 131072, 32768, 8192, 2048, 512, 128, 32, 8, 2 }, + { 65536, 16384, 4096, 1024, 256, 64, 16, 4, 1 }, + { 32768, 8192, 2048, 512, 128, 32, 8, 2, 1 }, + { 16384, 4096, 1024, 256, 64, 16, 4, 1, 1 } + } +}; + +// Necessary memory for textures +// Big table to minimize calculation +const FxU32 nSquareTexLod[ 2 ][ 7 ][ 9 ][ 9 ] = // Tex type, aspect, largelod, smalllod +{ + { // Dual byte Textures + { // GR_ASPECT_8x1 + { 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848, 21848 }, + { 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464, 5464 }, + { 0, 0, 1024, 1280, 1344, 1360, 1368, 1368, 1368 }, + { 0, 0, 0, 256, 320, 336, 344, 344, 344 }, + { 0, 0, 0, 0, 64, 80, 88, 88, 88 }, + { 0, 0, 0, 0, 0, 16, 24, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_4x1 + { 32768, 40960, 43008, 43520, 43648, 43680, 43688, 43696, 43696 }, + { 0, 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928 }, + { 0, 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736 }, + { 0, 0, 0, 512, 640, 672, 680, 688, 688 }, + { 0, 0, 0, 0, 128, 160, 168, 176, 176 }, + { 0, 0, 0, 0, 0, 32, 40, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 8, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_2x1 + { 65536, 81920, 86016, 87040, 87296, 87360, 87376, 87384, 87384 }, + { 0, 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848 }, + { 0, 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464 }, + { 0, 0, 0, 1024, 1280, 1344, 1360, 1368, 1368 }, + { 0, 0, 0, 0, 256, 320, 336, 344, 344 }, + { 0, 0, 0, 0, 0, 64, 80, 88, 88 }, + { 0, 0, 0, 0, 0, 0, 16, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x1 + { 131072, 163840, 172032, 174080, 174592, 174720, 174752, 174760, 174768 }, + { 0, 32768, 40960, 43008, 43520, 43648, 43680, 43688, 43696 }, + { 0, 0, 8192, 10240, 10752, 10880, 10912, 10920, 10928 }, + { 0, 0, 0, 2048, 2560, 2688, 2720, 2728, 2736 }, + { 0, 0, 0, 0, 512, 640, 672, 680, 688 }, + { 0, 0, 0, 0, 0, 128, 160, 168, 176 }, + { 0, 0, 0, 0, 0, 0, 32, 40, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x2 + { 65536, 81920, 86016, 87040, 87296, 87360, 87376, 87384, 87384 }, + { 0, 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848 }, + { 0, 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464 }, + { 0, 0, 0, 1024, 1280, 1344, 1360, 1368, 1368 }, + { 0, 0, 0, 0, 256, 320, 336, 344, 344 }, + { 0, 0, 0, 0, 0, 64, 80, 88, 88 }, + { 0, 0, 0, 0, 0, 0, 16, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x4 + { 32768, 40960, 43008, 43520, 43648, 43680, 43688, 43696, 43696 }, + { 0, 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928 }, + { 0, 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736 }, + { 0, 0, 0, 512, 640, 672, 680, 688, 688 }, + { 0, 0, 0, 0, 128, 160, 168, 176, 176 }, + { 0, 0, 0, 0, 0, 32, 40, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 8, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x8 + { 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848, 21848 }, + { 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464, 5464 }, + { 0, 0, 1024, 1280, 1344, 1360, 1368, 1368, 1368 }, + { 0, 0, 0, 256, 320, 336, 344, 344, 344 }, + { 0, 0, 0, 0, 64, 80, 88, 88, 88 }, + { 0, 0, 0, 0, 0, 16, 24, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + } + }, + { // Single byte Textures + { // GR_ASPECT_8x1 + { 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928, 10928 }, + { 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736, 2736 }, + { 0, 0, 512, 640, 672, 680, 688, 688, 688 }, + { 0, 0, 0, 128, 160, 168, 176, 176, 176 }, + { 0, 0, 0, 0, 32, 40, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 8, 16, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_4x1 + { 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848, 21848 }, + { 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464, 5464 }, + { 0, 0, 1024, 1280, 1344, 1360, 1368, 1368, 1368 }, + { 0, 0, 0, 256, 320, 336, 344, 344, 344 }, + { 0, 0, 0, 0, 64, 80, 88, 88, 88 }, + { 0, 0, 0, 0, 0, 16, 24, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_2x1 + { 32768, 40960, 43008, 43520, 43648, 43680, 43688, 43696, 43696 }, + { 0, 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928 }, + { 0, 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736 }, + { 0, 0, 0, 512, 640, 672, 680, 688, 688 }, + { 0, 0, 0, 0, 128, 160, 168, 176, 176 }, + { 0, 0, 0, 0, 0, 32, 40, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 8, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x1 + { 65536, 81920, 86016, 87040, 87296, 87360, 87376, 87384, 87384 }, + { 0, 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848 }, + { 0, 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464 }, + { 0, 0, 0, 1024, 1280, 1344, 1360, 1368, 1368 }, + { 0, 0, 0, 0, 256, 320, 336, 344, 344 }, + { 0, 0, 0, 0, 0, 64, 80, 88, 88 }, + { 0, 0, 0, 0, 0, 0, 16, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x2 + { 32768, 40960, 43008, 43520, 43648, 43680, 43688, 43696, 43696 }, + { 0, 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928 }, + { 0, 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736 }, + { 0, 0, 0, 512, 640, 672, 680, 688, 688 }, + { 0, 0, 0, 0, 128, 160, 168, 176, 176 }, + { 0, 0, 0, 0, 0, 32, 40, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 8, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x4 + { 16384, 20480, 21504, 21760, 21824, 21840, 21848, 21848, 21848 }, + { 0, 4096, 5120, 5376, 5440, 5456, 5464, 5464, 5464 }, + { 0, 0, 1024, 1280, 1344, 1360, 1368, 1368, 1368 }, + { 0, 0, 0, 256, 320, 336, 344, 344, 344 }, + { 0, 0, 0, 0, 64, 80, 88, 88, 88 }, + { 0, 0, 0, 0, 0, 16, 24, 24, 24 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + }, + { // GR_ASPECT_1x8 + { 8192, 10240, 10752, 10880, 10912, 10920, 10928, 10928, 10928 }, + { 0, 2048, 2560, 2688, 2720, 2728, 2736, 2736, 2736 }, + { 0, 0, 512, 640, 672, 680, 688, 688, 688 }, + { 0, 0, 0, 128, 160, 168, 176, 176, 176 }, + { 0, 0, 0, 0, 32, 40, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 8, 16, 16, 16 }, + { 0, 0, 0, 0, 0, 0, 8, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 8, 8 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 8 }, + } + } +}; diff --git a/MacGLide/OpenGLide/Optimise.h b/MacGLide/OpenGLide/Optimise.h new file mode 100644 index 0000000..8f8acc2 --- /dev/null +++ b/MacGLide/OpenGLide/Optimise.h @@ -0,0 +1,57 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* Optimise switches +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + + +// Check if the Glide state really changes before executing a function. +// The idea behind this is to avoid unnecessary calls to RenderDrawTriangles(). +// As a result, the necessary call to RenderDrawTriangles() can render more +// triangles at once. +// +// Most called functions (by analysing Falcon4.0): +// - grAlphaBlendFunction +// - grAlphaCombine +// - grAlphaTestFunction +// - grAlphaTestReferenceValue +// - grChromakeyMode +// - grChromakeyValue +// - grConstantColorValue +// - grConstantColorValue4 +// - grClipWindow +// - grColorCombine +// - grDepthBufferMode +// - grDitherMode +// - grFogMode +// - grTexClampMode +// - grTexCombine +// - grTexFilterMode +// - grTexMipMapMode +// - guTexSource +// +// Would need support but are not yet implemented +// - grTexDetailControl +// - grHints +// +// The following function names appear in the logs on each call, +// but just call other functions which are already state-optimised. +// - guTexCombineFunction +// - guColorCombineFunction +// +// Optimises Glide calls with parameters that wouldn't change the Glide state +// (by placing the CHECK_STATE_CHANGED macro at the beginning of a function) +#define OPTIMISE_GLIDE_STATE_CHANGES + +// Optimises internal function calls that wouldn't result +// in a change of the OpenGL state +#define OPTIMISE_OPENGL_STATE_CHANGES + +// Retrieve TexDB records via a lookup table half the size of the texture memory. +#define OPTIMISE_TEXTURE_LOOKUP diff --git a/MacGLide/OpenGLide/PGTexture.cpp b/MacGLide/OpenGLide/PGTexture.cpp new file mode 100644 index 0000000..c18c2a5 --- /dev/null +++ b/MacGLide/OpenGLide/PGTexture.cpp @@ -0,0 +1,927 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* implementation of the PGTexture class +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "FormatConversion.h" +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideSettings.h" +#include "Glextensions.h" +#include "GLRender.h" +#include "OGLTables.h" +#include "PGTexture.h" + + +void PGTexture::genPaletteMipmaps( FxU32 width, FxU32 height, const FxU8 *data ) +{ + FxU8 buf[ 128 * 128 ]; + FxU32 mmwidth; + FxU32 mmheight; + FxU32 lod; + FxU32 skip; + + mmwidth = width; + mmheight = height; + lod = 0; + skip = 1; + + while ( ( mmwidth > 1 ) || ( mmheight > 1 ) ) + { + FxU32 x, + y; + + mmwidth = mmwidth > 1 ? mmwidth / 2 : 1; + mmheight = mmheight > 1 ? mmheight / 2 : 1; + lod += 1; + skip *= 2; + + for ( y = 0; y < mmheight; y++ ) + { + const FxU8* in; + FxU8* out; + + in = data + width * y * skip; + out = buf + mmwidth * y; + for ( x = 0; x < mmwidth; x++ ) + { + out[ x ] = in[ x * skip ]; + } + } + + glTexImage2D( GL_TEXTURE_2D, lod, GL_COLOR_INDEX8_EXT, mmwidth, mmheight, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buf ); + } +} + +PGTexture::PGTexture( int mem_size ) +{ + m_db = new TexDB( mem_size ); + m_palette_dirty = true; + m_valid = false; + m_chromakey_mode = GR_CHROMAKEY_DISABLE; + m_tex_memory_size = mem_size; + m_memory = (FxU8*) AllocBuffer(mem_size, sizeof(FxU8)); + m_tex_temp = reinterpret_cast(AllocBuffer(256 * 256, sizeof(FxU32))); + m_ncc_select = GR_NCCTABLE_NCC0; + +#ifdef OGL_DEBUG + Num_565_Tex = 0; + Num_565_Chromakey_Tex = 0; + Num_1555_Tex = 0; + Num_1555_Chromakey_Tex = 0; + Num_4444_Tex = 0; + Num_4444_Chromakey_Tex = 0; + Num_332_Tex = 0; + Num_8332_Tex = 0; + Num_Alpha_Tex = 0; + Num_AlphaIntensity88_Tex = 0; + Num_AlphaIntensity44_Tex = 0; + Num_AlphaPalette_Tex = 0; + Num_Palette_Tex = 0; + Num_Palette_Chromakey_Tex = 0; + Num_Intensity_Tex = 0; + Num_YIQ_Tex = 0; + Num_AYIQ_Tex = 0; + Num_Other_Tex = 0; +#endif +} + +PGTexture::~PGTexture( void ) +{ + FreeBuffer(m_memory); + FreeBuffer(m_tex_temp); + delete m_db; +} + +void PGTexture::DownloadMipMap( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ) +{ + const FxU32 mip_size = MipMapMemRequired( info->smallLod, + info->aspectRatio, + info->format ); + const FxU32 mip_offset = startAddress + TextureMemRequired( evenOdd, info ); + + if ( mip_offset <= m_tex_memory_size ) + { + memcpy( m_memory + mip_offset - mip_size, info->data, mip_size ); + } + + // Any texture based on memory crossing this range + // is now out of date + m_db->WipeRange( startAddress, mip_offset, 0 ); + +#ifdef OGL_DEBUG + if ( info->smallLod == info->largeLod ) + { + switch ( info->format ) + { + case GR_TEXFMT_RGB_332: Num_332_Tex++; break; + case GR_TEXFMT_YIQ_422: Num_YIQ_Tex++; break; + case GR_TEXFMT_ALPHA_8: Num_Alpha_Tex++; break; + case GR_TEXFMT_INTENSITY_8: Num_Intensity_Tex++; break; + case GR_TEXFMT_ALPHA_INTENSITY_44: Num_AlphaIntensity44_Tex++; break; + case GR_TEXFMT_P_8: m_chromakey_mode + ? Num_Palette_Chromakey_Tex++ + : Num_Palette_Tex++; + break; + case GR_TEXFMT_ARGB_8332: Num_8332_Tex++; break; + case GR_TEXFMT_AYIQ_8422: Num_AYIQ_Tex++; break; + case GR_TEXFMT_RGB_565: m_chromakey_mode + ? Num_565_Chromakey_Tex++ + : Num_565_Tex++; + break; + case GR_TEXFMT_ARGB_1555: m_chromakey_mode + ? Num_1555_Chromakey_Tex++ + : Num_1555_Tex++; + break; + case GR_TEXFMT_ARGB_4444: m_chromakey_mode + ? Num_4444_Chromakey_Tex++ + : Num_4444_Tex++; + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: Num_AlphaIntensity88_Tex++; break; + case GR_TEXFMT_AP_88: Num_AlphaPalette_Tex++; break; + case GR_TEXFMT_RSVD0: + case GR_TEXFMT_RSVD1: + case GR_TEXFMT_RSVD2: + default: Num_Other_Tex++; break; + } + } +#endif +} + +void PGTexture::DownloadMipMapLevel(FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data) +{ + GrTexInfo info; + info.smallLod = thisLod; + info.largeLod = largeLod; + info.aspectRatio = aspectRatio; + info.format = format; + info.data = data; + DownloadMipMap(startAddress, evenOdd, &info); +} + +void PGTexture::DownloadMipMapLevelPartial(FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data, + int start, + int end) +{ + GrTexInfo info; + info.smallLod = thisLod; + info.largeLod = largeLod; + info.aspectRatio = aspectRatio; + info.format = format; + info.data = data; + const FxU32 mip_size = MipMapMemRequired(info.smallLod, info.aspectRatio, info.format); + // instead of forwarding evenOdd, GR_MIPMAPLEVELMASK_BOTH might also be appropriate + const FxU32 mip_offset = startAddress + TextureMemRequired(evenOdd, &info); + // Choose the rows to copy (only largeLod is supported) + TexValues texVals; + GetTexValues(&texVals); + const FxU32 texel_size = info.format >= GR_TEXFMT_16BIT ? 2 : 1; + const FxU32 startRow = texVals.width * texel_size * start; + const FxU32 rows = texVals.width * texel_size * (end - start); + if ( mip_offset <= m_tex_memory_size ) + { + memcpy(m_memory + mip_offset - mip_size + startRow, info.data, rows); + } + // Any texture based on memory crossing this range + // is now out of date + m_db->WipeRange(startAddress, mip_offset, 0); +} + +void PGTexture::Source( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ) +{ + m_startAddress = startAddress; + m_evenOdd = evenOdd; + m_info = *info; + + m_wAspect = texAspects[ info->aspectRatio ].w; + m_hAspect = texAspects[ info->aspectRatio ].h; + + m_valid = ( ( startAddress + TextureMemRequired( evenOdd, info ) ) <= m_tex_memory_size ); +} + +void PGTexture::DownloadMipmapsToOpenGL(GLint compnum, GLint compformat, GLenum comptype, const void* texdata, TexValues& t, bool build_mipmaps) +{ + glReportErrors("DownloadMipmapsToOpenGL"); + + glTexImage2D(GL_TEXTURE_2D, t.lod, compnum, t.width, t.height, 0, compformat, comptype, texdata); + if (InternalConfig.Mipmapping && build_mipmaps) + { + gluBuild2DMipmaps(GL_TEXTURE_2D, compnum, t.width, t.height, compformat, comptype, texdata); + } + glReportError(); +} + +inline void ncc_convert_FxI9_2_FxI16(FxI16* ncc_xRGB) +{ + if (*ncc_xRGB & 0x100) + *ncc_xRGB |= 0xff00; +} + +void PGTexture::DownloadTable( GrTexTable_t type, const FxU32 *data, int first, int count ) +{ + if ( type == GR_TEXTABLE_PALETTE ) + { + for ( int i = count - 1; i >= 0; i-- ) + { + // Convert palette entry from ARGB to RGBA + const FxU32& src = data[ i ]; + m_palette[ first + i ] = ((src & 0x00ffffff) << 8) | // RGB + ((src & 0xff000000) >> 24); // A + } + m_palette_dirty = true; + } + else + { + // GR_TEXTABLE_NCC0 or GR_TEXTABLE_NCC1 + GuNccTable *ncc = &(m_ncc[ type ]); + memcpy( ncc, data, sizeof( GuNccTable ) ); + for (int i = 0; i < 4; i++ ) + { + ncc_convert_FxI9_2_FxI16(&ncc->iRGB[ i ][ 0 ]); + ncc_convert_FxI9_2_FxI16(&ncc->iRGB[ i ][ 1 ]); + ncc_convert_FxI9_2_FxI16(&ncc->iRGB[ i ][ 2 ]); + ncc_convert_FxI9_2_FxI16(&ncc->qRGB[ i ][ 0 ]); + ncc_convert_FxI9_2_FxI16(&ncc->qRGB[ i ][ 1 ]); + ncc_convert_FxI9_2_FxI16(&ncc->qRGB[ i ][ 2 ]); + } + } +} + +bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_triangles) +{ + glReportErrors("PGTexture::MakeReady"); + if( ! m_valid ) + { + return false; + } + + FxU32 test_hash = 0; + FxU32 wipe_hash = 0; + bool palette_changed = false; + bool use_mipmap_ext = InternalConfig.Mipmapping && InternalConfig.EXT_SGIS_generate_mipmap; + bool use_two_textures = false; + bool* pal_change_ptr = NULL; + const FxU8* data = m_memory + m_startAddress; + FxU32 size = TextureMemRequired(m_evenOdd, &m_info); + + TexValues texVals; + GetTexValues(&texVals); + switch (m_info.format) + { + case GR_TEXFMT_P_8: + ApplyKeyToPalette(); + // todo: Would work with anisotropic filtering if chromakeying was disabled + if (InternalConfig.EXT_paletted_texture && InternalConfig.AnisotropylLevel < 2) + { + // + // OpenGL's mipmap generation doesn't seem + // to handle paletted textures. + // + use_mipmap_ext = false; + pal_change_ptr = &palette_changed; + } + else + { + wipe_hash = m_palette_hash; + } + test_hash = m_palette_hash; + break; + case GR_TEXFMT_AP_88: + ApplyKeyToPalette(); + if (InternalConfig.EXT_paletted_texture && InternalConfig.ARB_multitexture) + { + use_mipmap_ext = false; + pal_change_ptr = &palette_changed; + // Two textures can only be used with the simple coloralpha engine + // and if there are enough texture units left to support fog + use_two_textures = (OpenGL.ColorAlphaUnit2 == 0) && (OpenGL.FogTextureUnit >= GL_TEXTURE1_ARB); + } + else + { + wipe_hash = m_palette_hash; + } + test_hash = m_palette_hash; + break; + } + // Look if we already have an OpenGL texture to match this + TexDB::Record* texture_record; + SubTexCoord_t subtexcoords_struct; + const bool generate_sub_textures = InternalConfig.GenerateSubTextures && + OpenGL.SClampMode != GL_REPEAT && + OpenGL.TClampMode != GL_REPEAT; + SubTexCoord_t* subtexcoords = generate_sub_textures ? &subtexcoords_struct : NULL; + if (subtexcoords) + { + assert(number_of_triangles == 1); + GLfloat min; + GLfloat max; + const unsigned int grid_snap = 0xffffffff - (InternalConfig.GenerateSubTextures -1); + // Get Glide pixel coordinates (prepared in RenderAddTriangle()) + const GLfloat as = tex_coords->as; + const GLfloat bs = tex_coords->bs; + const GLfloat cs = tex_coords->cs; + max = as; + min = bs; + if (max < min) + { + max = bs; + min = as; + } + if (max < cs) + { + max = cs; + } + else if (min > cs) + { + min = cs; + } + subtexcoords->smin = min; + subtexcoords->smax = max; + subtexcoords->left = min; + // snap to grid to allow using the left/top values as keys for caching + subtexcoords->left &= grid_snap; // snap to 8 pixel grid + subtexcoords->smin = subtexcoords->left; + // same for t + const GLfloat at = tex_coords->at; + const GLfloat bt = tex_coords->bt; + const GLfloat ct = tex_coords->ct; + max = at; + min = bt; + if (max < min) + { + max = bt; + min = at; + } + if (max < ct) + { + max = ct; + } + else if (min > ct) + { + min = ct; + } + subtexcoords->tmin = min; + subtexcoords->tmax = max; + subtexcoords->top = min; + subtexcoords->top &= grid_snap; // snap to 8 pixel grid + subtexcoords->tmin = subtexcoords->top; + // Calculate width and height of the texture + subtexcoords->width = subtexcoords->smax - subtexcoords->left; + subtexcoords->height = subtexcoords->tmax - subtexcoords->top; + subtexcoords->texImageWidth = max(InternalConfig.GenerateSubTextures, PowerOfTwoCeiling(subtexcoords->width)); + subtexcoords->texImageHeight = max(InternalConfig.GenerateSubTextures, PowerOfTwoCeiling(subtexcoords->height)); + texture_record = texture_record = m_db->Find(m_startAddress, &m_info, test_hash, pal_change_ptr, subtexcoords); + // At this point the subtexcoord texsize might have been updated (by Find()) + // Calculate texture coordinates for rendering the subtexture + // 1. scale a->s to texture pixel s-space: as = a->tmuvtx[ 0 ].sow / atmuoow; + // 2. shift as to origin: as_s = as - subtexcoords.smin; + // 3. scale as_s to opengl texture space as_s *= wAspect / subtexcoords.width; + // 4. scale as_s to opengl subtexture space: * subtexcoords.width / subtexcoords.texImageWidth + // 5. undo dividing by atmoow and scale with maxoow to fit texture edge into object edges + // tex_coords->aoow is actually maxoow * aoow what is what we want + const GLfloat s_factor = 1.0f / subtexcoords->texImageWidth; + tex_coords->as = (as - subtexcoords->smin) * s_factor * tex_coords->aoow; + tex_coords->bs = (bs - subtexcoords->smin) * s_factor * tex_coords->boow; + tex_coords->cs = (cs - subtexcoords->smin) * s_factor * tex_coords->coow; + const GLfloat t_factor = 1.0f / subtexcoords->texImageHeight; + tex_coords->at = (at - subtexcoords->tmin) * t_factor * tex_coords->aoow; + tex_coords->bt = (bt - subtexcoords->tmin) * t_factor * tex_coords->boow; + tex_coords->ct = (ct - subtexcoords->tmin) * t_factor * tex_coords->coow; +#ifdef OGL_UTEX + GlideMsg("glTexCoords(%g,%g)-(%g,%g)-(%g,%g), ", + tex_coords->as, + tex_coords->at, + tex_coords->bs, + tex_coords->bt, + tex_coords->cs, + tex_coords->ct); + GlideMsg("Subtex: min/max(%g,%g)-(%g,%g),", + subtexcoords->smin, + subtexcoords->smax, + subtexcoords->tmin, + subtexcoords->tmax); + GlideMsg(" w/h(%g,%g), texture(%d,%d)-(%d,%d)\n", + subtexcoords->width, + subtexcoords->height, + subtexcoords->left, + subtexcoords->top, + subtexcoords->texImageWidth, + subtexcoords->texImageHeight); +#endif + } + else + { + texture_record = texture_record = m_db->Find(m_startAddress, &m_info, test_hash, pal_change_ptr, NULL); + } +#ifdef OGL_DEBUG + if (InternalConfig.EXT_paletted_texture == false && palette_changed) + { + GlideMsg("Performance Warning: PGTexture palette change for 0x%x causes texture regeneration\n", m_startAddress); + } +#endif + + const bool enable_coloralpha_texture_unit_1 = OpenGL.ColorAlphaUnit2 == NULL || + OpenGL.ColorAlphaUnitColorEnabledState[0] || + OpenGL.ColorAlphaUnitAlphaEnabledState[0]; + const bool enable_coloralpha_texture_unit_2 = OpenGL.ColorAlphaUnitColorEnabledState[1] || + OpenGL.ColorAlphaUnitAlphaEnabledState[1]; + if (texture_record) + { + if (palette_changed && InternalConfig.EXT_paletted_texture) + { + glColorTable(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_palette); + glReportError(); + } + GLint texnum2; + if (OpenGL.ColorAlphaUnit2 && enable_coloralpha_texture_unit_2) + { + texnum2 = texture_record->texNum; + } + else if (use_two_textures) + { + texnum2 = texture_record->tex2Num; + } + else + { + texnum2 = 0; + } + if (texnum2) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glBindTexture(GL_TEXTURE_2D, texnum2); + // Only needed if the two textures are different + if (use_two_textures) + { + if (texture_record->SClampMode != OpenGL.SClampMode) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture_record->SClampMode); + } + if (texture_record->TClampMode != OpenGL.TClampMode) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture_record->TClampMode); + } + if (InternalConfig.TextureSmoothing == false) + { + if (texture_record->MinFilterMode != OpenGL.MinFilterMode) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_record->MinFilterMode); + } + if (texture_record->MagFilterMode != OpenGL.MagFilterMode) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texture_record->MagFilterMode); + } + } + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + if (enable_coloralpha_texture_unit_1) + { + glBindTexture(GL_TEXTURE_2D, texture_record->texNum); + if (texture_record->SClampMode != OpenGL.SClampMode) + { + texture_record->SClampMode = OpenGL.SClampMode; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, OpenGL.SClampMode); + } + if (texture_record->TClampMode != OpenGL.TClampMode) + { + texture_record->TClampMode = OpenGL.TClampMode; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, OpenGL.TClampMode); + } + if (InternalConfig.TextureSmoothing == false) + { + if (texture_record->MinFilterMode != OpenGL.MinFilterMode) + { + texture_record->MinFilterMode = OpenGL.MinFilterMode; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, OpenGL.MinFilterMode); + } + if (texture_record->MagFilterMode != OpenGL.MagFilterMode) + { + texture_record->MagFilterMode = OpenGL.MagFilterMode; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, OpenGL.MagFilterMode); + } + } + glReportError(); + } + } + else + { + // Any existing textures crossing this memory range + // is unlikely to be used, so remove the OpenGL version + // of them + if (wipe_hash) + { + // If we don't have GL_PALETTE_EXT, the texture must be rebuilt + // after the palette has changed. Any existing textures must be deleted. + // This is because Find() above was looking for a texture with + // the current palette hash and might not have found it, although + // a texture with a different palette exists. + // @todo: Find doesn't return handles to TexDB records, so we have + // to search again every time a paletted texture is used -> optimise. + if (subtexcoords) + { + // Fall back to non-subtexture behaviour and just + // wipe the range if the texture doesn't exist at all + if (m_db->Find(m_startAddress, &m_info, test_hash, pal_change_ptr, NULL) == NULL) + { + m_db->WipeRange(m_startAddress, m_startAddress + size, wipe_hash); + } + } + } + else + { + // Nothing needs to be done because if it's not a paletted texture, + // the range has been wiped while downloading the texture + // m_db->WipeRange( m_startAddress, m_startAddress + size, wipe_hash); + } + // Add the new texture to the data base + TexDB::TextureMode texturemode = subtexcoords ? (use_two_textures ? TexDB::SubTextureTwo : TexDB::SubTextureOne) : (use_two_textures ? TexDB::Two : TexDB::One); + texture_record = m_db->Add(m_startAddress, m_startAddress + size, &m_info, test_hash, texturemode, subtexcoords); + texture_record->SClampMode = OpenGL.SClampMode; + texture_record->TClampMode = OpenGL.TClampMode; + texture_record->MinFilterMode = OpenGL.MinFilterMode; + texture_record->MagFilterMode = OpenGL.MagFilterMode; + glBindTexture( GL_TEXTURE_2D, texture_record->texNum); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, OpenGL.SClampMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, OpenGL.TClampMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, OpenGL.MinFilterMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, OpenGL.MagFilterMode); + // Texture artefact fix for TR2 + // This would solve remaining issues with texture artefacts caused by filtering, + // but degrades the overall image quality too much + /* + bool fix_subtexture_artefacts = false; + if (subtexcoords) + { + // While TR1 uses subtextures with power-of-2 sizes only (as far as I know), + // some TR2 textures don't fit into this scheme, and thus still produces artefacts + // (for instance the joins in Lara's hair and butler james clothes) + const GLfloat epsilon = 0.75; + if (subtexcoords->width / static_cast(subtexcoords->texImageWidth) <= epsilon || + subtexcoords->height / static_cast(subtexcoords->texImageHeight) <= epsilon) + { + // The artefacts can be fixed by applying neither mipmapping nor anisotropic filtering + fix_subtexture_artefacts = true; + } + } + // These are constant parameters and don't change between calls + const unsigned long anisotropy_level = fix_subtexture_artefacts ? 1 : InternalConfig.AnisotropylLevel; + const bool enable_mipmaps = fix_subtexture_artefacts ? false : InternalConfig.Mipmapping; + */ + const unsigned long anisotropy_level = InternalConfig.AnisotropylLevel; + const bool enable_mipmaps = InternalConfig.Mipmapping; + // Write only if enabled in config + if(InternalConfig.AnisotropylLevel > 1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy_level); + } + if(use_mipmap_ext) + { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, enable_mipmaps); + } + GLint texnum2; + if (OpenGL.ColorAlphaUnit2 && enable_coloralpha_texture_unit_2) + { + texnum2 = texture_record->texNum; + } + else if (use_two_textures) + { + texnum2 = texture_record->tex2Num; + } + else + { + texnum2 = 0; + } + if (texnum2) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + glBindTexture(GL_TEXTURE_2D, texnum2); + // Only needed if the two textures are different + if (use_two_textures) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, OpenGL.SClampMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, OpenGL.TClampMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, OpenGL.MinFilterMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, OpenGL.MagFilterMode); + if(InternalConfig.AnisotropylLevel > 1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy_level); + } + if (use_mipmap_ext) + { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, enable_mipmaps); + } + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + } + glReportError(); + + if (subtexcoords) + { + /* + // Don't generate mipmaps in DownloadMipmapsToOpenGL() + if (fix_subtexture_artefacts) + { + // Pretend to have mipmap ext in order to + // avoid generating mipmaps without mipmap ext + use_mipmap_ext = true; + glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName); + } + */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, subtexcoords->left); + glPixelStorei(GL_UNPACK_SKIP_ROWS, subtexcoords->top); + glPixelStorei(GL_UNPACK_ROW_LENGTH, texVals.width); + // Must update texVals.width, texVals.height to new texture size + texVals.width = subtexcoords->texImageWidth; + texVals.height = subtexcoords->texImageHeight; + } + + switch ( m_info.format ) + { + case GR_TEXFMT_RGB_565: + if ( m_chromakey_mode ) + { + // Read about anisotropy and chromakey issues in macFormatConversions.cpp + Convert565Kto8888((FxU16*)data, m_chromakey_value_565, m_tex_temp, texVals.nPixels); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + } + else + { + DownloadMipmapsToOpenGL(3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data, texVals, !use_mipmap_ext); + } + break; + case GR_TEXFMT_ARGB_4444: + DownloadMipmapsToOpenGL(4, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV, data, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_ARGB_1555: + if (m_chromakey_mode) + { + // Read about anisotropy and chromakey issues in macFormatConversions.cpp + Convert1555Kto8888((FxU16*) data, m_chromakey_value_1555, m_tex_temp, texVals.nPixels); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + } + else + { + DownloadMipmapsToOpenGL(4, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, data, texVals, !use_mipmap_ext); + } + break; + case GR_TEXFMT_P_8: + // Read about anisotropy and chromakey issues in macFormatConversions.cpp + if ( InternalConfig.EXT_paletted_texture && InternalConfig.AnisotropylLevel < 2) + { + glColorTable(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_palette); + glTexImage2D( GL_TEXTURE_2D, texVals.lod, GL_COLOR_INDEX8_EXT, + texVals.width, texVals.height, 0, + GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data ); + if (InternalConfig.Mipmapping && !use_mipmap_ext) + { + genPaletteMipmaps(texVals.width, texVals.height, data); + } + glReportError(); + } + else + { + if (InternalConfig.AnisotropylLevel >= 2) + { + // minimise anisotropy artefacts + ConvertP8Kto8888(data, m_chromakey_value_8888, m_tex_temp, texVals.nPixels, m_palette); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + } + else + { + ConvertP8to8888(data, m_tex_temp, texVals.nPixels, m_palette); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + } + } + break; + case GR_TEXFMT_AP_88: + if ( use_two_textures ) + { + FxU32 *tex_temp2 = m_tex_temp + 256 * 128; + glColorTable(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_palette); + SplitAP88( (FxU16 *)data, (FxU8 *)m_tex_temp, (FxU8 *)tex_temp2, texVals.nPixels ); + glTexImage2D( GL_TEXTURE_2D, texVals.lod, GL_COLOR_INDEX8_EXT, + texVals.width, texVals.height, 0, + GL_COLOR_INDEX, GL_UNSIGNED_BYTE, m_tex_temp ); + if (InternalConfig.Mipmapping && !use_mipmap_ext) + { + genPaletteMipmaps( texVals.width, texVals.height, (FxU8 *)m_tex_temp ); + } + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); + DownloadMipmapsToOpenGL( GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, tex_temp2, texVals, !use_mipmap_ext); + glActiveTextureARB(OpenGL.ColorAlphaUnit1); + glReportError(); + } + else + { + ConvertAP88to8888( (FxU16*)data, m_tex_temp, texVals.nPixels, m_palette ); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + } + break; + case GR_TEXFMT_ALPHA_8: + ConvertA8toAP88( (FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels ); + DownloadMipmapsToOpenGL( 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + // @todo: The statement below breaks the overlay texts in Myth TFL. + // As a result ,this optimsation has been undone for now + // DownloadMipmapsToOpenGL(1, GL_ALPHA, GL_UNSIGNED_BYTE, data, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + DownloadMipmapsToOpenGL(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_INTENSITY_8: + DownloadMipmapsToOpenGL(1, GL_LUMINANCE, GL_UNSIGNED_BYTE, data, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_ALPHA_INTENSITY_44: + // @todo: untested + // DownloadMipmapsToOpenGL(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data, &texVals); + // @todo: untested + ConvertAI44toAP88((FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels); + DownloadMipmapsToOpenGL(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + /* + ConvertAI44toAP88( (FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels ); + glTexImage2D( GL_TEXTURE_2D, texVals.lod, 2, texVals.width, texVals.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp ); + if (InternalConfig.Mipmapping && !use_mipmap_ext) + { + gluBuild2DMipmaps( GL_TEXTURE_2D, 2, texVals.width, texVals.height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp ); + } + glReportError(); + */ + break; + case GR_TEXFMT_8BIT: //GR_TEXFMT_RGB_332 + DownloadMipmapsToOpenGL(3, GL_RGB, GL_UNSIGNED_BYTE_3_3_2_EXT, data, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_16BIT: //GR_TEXFMT_ARGB_8332: + Convert8332to8888( (FxU16*)data, m_tex_temp, texVals.nPixels ); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_YIQ_422: + ConvertYIQto8888( (FxU8*)data, m_tex_temp, texVals.nPixels, &(m_ncc[m_ncc_select]) ); + // @todo: Should just be RGB in order to apply constant color per default, shouldn't it? + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_AYIQ_8422: + ConvertAYIQto8888( (FxU16*)data, m_tex_temp, texVals.nPixels, &(m_ncc[m_ncc_select]) ); + DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + break; + case GR_TEXFMT_RSVD0: + case GR_TEXFMT_RSVD1: + case GR_TEXFMT_RSVD2: + default: + GlideMsg("Error: grTexDownloadMipMapLevel - Unsupported format(%d)\n", m_info.format); + memset( m_tex_temp, 255, texVals.nPixels * 2 ); + DownloadMipmapsToOpenGL(1, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); + break; + } + if (subtexcoords) + { + // restore values + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + return use_two_textures; +} + +FxU32 PGTexture::LodOffset( FxU32 evenOdd, const GrTexInfo *info ) +{ + FxU32 total = 0; + GrLOD_t i; + + for( i = info->largeLod; i < info->smallLod; i++ ) + { + total += MipMapMemRequired( i, info->aspectRatio, info->format ); + } + + total = ( total + 7 ) & ~7; + + return total; +} + +FxU32 PGTexture::TextureMemRequired( FxU32 evenOdd, const GrTexInfo *info ) +{ + // + // If the format is one of these: + // GR_TEXFMT_RGB_332, GR_TEXFMT_YIQ_422, GR_TEXFMT_ALPHA_8 + // GR_TEXFMT_INTENSITY_8, GR_TEXFMT_ALPHA_INTENSITY_44, GR_TEXFMT_P_8 + // Reduces the size by 2 + // + return nSquareTexLod[ info->format < GR_TEXFMT_16BIT ][ info->aspectRatio ][ info->largeLod ][ info->smallLod ]; +} + +FxU32 PGTexture::MipMapMemRequired( GrLOD_t lod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format ) +{ + // + // If the format is one of these: + // GR_TEXFMT_RGB_332, GR_TEXFMT_YIQ_422, GR_TEXFMT_ALPHA_8 + // GR_TEXFMT_INTENSITY_8, GR_TEXFMT_ALPHA_INTENSITY_44, GR_TEXFMT_P_8 + // Reduces the size by 2 + // + return nSquareLod[ format >= GR_TEXFMT_16BIT ][ aspectRatio ][ lod ]; +} + +void PGTexture::GetTexValues( TexValues * tval ) const +{ + tval->width = texInfo[ m_info.aspectRatio ][ m_info.largeLod ].width; + tval->height = texInfo[ m_info.aspectRatio ][ m_info.largeLod ].height; + tval->nPixels = texInfo[ m_info.aspectRatio ][ m_info.largeLod ].numPixels; + tval->lod = 0; +} + +void PGTexture::Clear( void ) +{ + m_db->Clear( ); +} + +void PGTexture::ChromakeyValue( GrColor_t value ) +{ + m_chromakey_value_8888 = (value & 0xffffff00); // RGB, Alpha ommited + m_chromakey_value_565 = (FxU16) (( value & 0xF8000000 ) >> 16 | + ( value & 0x00FC0000 ) >> 13 | + ( value & 0x0000F800 ) >> 11 ); + m_chromakey_value_1555 = (FxU16) (( value & 0xf8000000 ) >> 17 | + ( value & 0x00f80000 ) >> 14 | + ( value & 0x0000f800 ) >> 11 ); + m_palette_dirty = true; +} + +void PGTexture::ChromakeyMode( GrChromakeyMode_t mode ) +{ + m_chromakey_mode = mode; + m_palette_dirty = true; +} + +void PGTexture::ApplyKeyToPalette( void ) +{ + FxU32 hash; + int i; + if ( m_palette_dirty ) + { + hash = 0; + { + for ( i = 0; i < 256; i++ ) + { + if ( ( m_chromakey_mode ) + && ( ( m_palette[i] & 0xffffff00 ) == m_chromakey_value_8888)) + { + m_palette[i] &= 0xffffff00; + } + else + { + m_palette[i] |= 0x000000ff; + } + hash = ( ( hash << 5 ) | ( hash >> 27 ) ); + hash += ( InternalConfig.IgnorePaletteChange + ? ( m_palette[ i ] & 0x000000ff ) + : m_palette[ i ]); + } + } + m_palette_hash = hash; + m_palette_dirty = false; + } +} + +void PGTexture::NCCTable( GrNCCTable_t tab ) +{ + switch ( tab ) + { + case GR_NCCTABLE_NCC0: + case GR_NCCTABLE_NCC1: + m_ncc_select = tab; + } +} + +FxU32 PGTexture::GetMemorySize( void ) const +{ + return m_tex_memory_size; +} + +unsigned int PGTexture::PowerOfTwoCeiling(unsigned int x) +{ + for(unsigned int potc= 1; potc < 0x0fffffff; potc <<= 1) + { + if (potc >= x) return potc; + } + return 0; +} diff --git a/MacGLide/OpenGLide/PGTexture.h b/MacGLide/OpenGLide/PGTexture.h new file mode 100644 index 0000000..554c79e --- /dev/null +++ b/MacGLide/OpenGLide/PGTexture.h @@ -0,0 +1,124 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* PGTexture Class Definition +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __PGTEXTURE_H__ +#define __PGTEXTURE_H__ + +#include "TexDB.h" + +struct TTextureStruct; + +class PGTexture +{ + struct TexValues + { + GrLOD_t lod; + FxU32 width; + FxU32 height; + FxU32 nPixels; + }; + unsigned int PowerOfTwoCeiling(unsigned int x); +public: + void NCCTable( GrNCCTable_t tab ); + static FxU32 LodOffset( FxU32 evenOdd, const GrTexInfo *info ); + static FxU32 MipMapMemRequired( GrLOD_t lod, GrAspectRatio_t aspectRatio, + GrTextureFormat_t format ); + static FxU32 TextureMemRequired( FxU32 evenOdd, const GrTexInfo *info ); + static void genPaletteMipmaps( FxU32 width, FxU32 height, const FxU8 *data ); + void ChromakeyMode( GrChromakeyMode_t mode ); + void ChromakeyValue( GrColor_t value ); + inline float GetHAspect() const + { + return m_hAspect; + } + inline float GetWAspect() const + { + return m_wAspect; + } + inline const GrTexInfo* GetCurrentTexInfo() const + { + return &m_info; + } + void Clear(); + bool MakeReady(TTextureStruct* tex_coords = NULL, unsigned long number_of_triangles = 0); + void DownloadTable( GrTexTable_t type, const FxU32 *data, int first, int count ); + void Source( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ); + void DownloadMipMap( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ); + void DownloadMipMapLevel(FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data); + void DownloadMipMapLevelPartial(FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data, + int start, + int end); + FxU32 GetMemorySize( void ) const; + PGTexture( int mem_size ); + virtual ~PGTexture(); + +#ifdef OGL_DEBUG + int Num_565_Tex; + int Num_565_Chromakey_Tex; + int Num_1555_Tex; + int Num_1555_Chromakey_Tex; + int Num_4444_Tex; + int Num_4444_Chromakey_Tex; + int Num_332_Tex; + int Num_8332_Tex; + int Num_Alpha_Tex; + int Num_AlphaIntensity88_Tex; + int Num_AlphaIntensity44_Tex; + int Num_AlphaPalette_Tex; + int Num_Palette_Tex; + int Num_Palette_Chromakey_Tex; + int Num_Intensity_Tex; + int Num_YIQ_Tex; + int Num_AYIQ_Tex; + int Num_Other_Tex; +#endif + +private: + void ApplyKeyToPalette( void ); + void GetTexValues( TexValues *tval ) const; + void DownloadMipmapsToOpenGL(GLint compnum, GLint compformat, GLenum comptype, const void* texdata, TexValues& t, bool build_mipmaps); + FxU32 m_tex_memory_size; + bool m_palette_dirty; + FxU32 m_palette_hash; + TexDB * m_db; + GrChromakeyMode_t m_chromakey_mode; + FxU32 m_chromakey_value_8888; + FxU16 m_chromakey_value_565; + FxU16 m_chromakey_value_1555; + float m_wAspect; + float m_hAspect; + FxU32* m_tex_temp; + bool m_valid; + FxU8 * m_memory; + FxU32 m_startAddress; + FxU32 m_evenOdd; + GrTexInfo m_info; + FxU32 m_palette[ 256 ]; + GrNCCTable_t m_ncc_select; + GuNccTable m_ncc[2]; +}; + +extern PGTexture *Textures; + +#endif diff --git a/MacGLide/OpenGLide/PGUTexture.cpp b/MacGLide/OpenGLide/PGUTexture.cpp new file mode 100644 index 0000000..8b8dac2 --- /dev/null +++ b/MacGLide/OpenGLide/PGUTexture.cpp @@ -0,0 +1,222 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* implementation of the PGUexture class +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "PGTexture.h" +#include "PGUTexture.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +PGUTexture::PGUTexture( void ) +{ + for ( int i = 0; i < MAX_MM; i++ ) + { + mm_info[ i ].valid = false; + } + + m_free_mem = 0; + m_free_id = 0; + m_current_id = GR_NULL_MIPMAP_HANDLE; +} + +PGUTexture::~PGUTexture( void ) +{ +} + +GrMipMapId_t PGUTexture::AllocateMemory( GrChipID_t tmu, FxU8 odd_even_mask, + int width, int height, + GrTextureFormat_t fmt, GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, + GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode, + float lod_bias, FxBool trilinear ) +{ + FxU32 size = 0; + GrLOD_t lod; + + for ( lod = largest_lod; lod <= smallest_lod; lod++ ) + { + size += PGTexture::MipMapMemRequired( lod, aspect, fmt ); + } + + size = ((size + 7) & ~7); + +#ifdef OGL_UTEX + GlideMsg( "Allocate id = %d size = %d\n", m_free_id, size ); +#endif + + if ( ( m_free_id >= MAX_MM ) || + ( ( m_free_mem + size ) >= Textures->GetMemorySize( ) ) ) + { +#ifdef OGL_UTEX + GlideMsg("Allocation failed\n"); +#endif + return GR_NULL_MIPMAP_HANDLE; + } + + mm_info[ m_free_id ].tmu = tmu; + mm_info[ m_free_id ].odd_even_mask = odd_even_mask; + mm_info[ m_free_id ].width = width; + mm_info[ m_free_id ].height = height; + mm_info[ m_free_id ].format = fmt; + mm_info[ m_free_id ].mipmap_mode = mm_mode; + mm_info[ m_free_id ].lod_min = smallest_lod; + mm_info[ m_free_id ].lod_max = largest_lod; + mm_info[ m_free_id ].aspect_ratio = aspect; + mm_info[ m_free_id ].s_clamp_mode = s_clamp_mode; + mm_info[ m_free_id ].t_clamp_mode = t_clamp_mode; + mm_info[ m_free_id ].minfilter_mode = minfilter_mode; + mm_info[ m_free_id ].magfilter_mode = magfilter_mode; + mm_info[ m_free_id ].lod_bias = lod_bias; + mm_info[ m_free_id ].trilinear = trilinear; + mm_info[ m_free_id ].valid = FXTRUE; + + mm_start[ m_free_id ] = m_free_mem; + + m_free_mem += size; + + return m_free_id++; +} + +void PGUTexture::DownloadMipMap( GrMipMapId_t mmid, const void *src, const GuNccTable *table ) +{ +#ifdef OGL_UTEX + GlideMsg("Download id = %d ", mmid); +#endif + + if ( ( mmid >=0 ) && ( mmid < MAX_MM ) && ( mm_info[ mmid ].valid ) ) + { + GrTexInfo info; + + info.aspectRatio = mm_info[ mmid ].aspect_ratio; + info.format = mm_info[ mmid ].format; + info.largeLod = mm_info[ mmid ].lod_max; + info.smallLod = mm_info[ mmid ].lod_min; + info.data = (void *)src; + if (info.format == GR_TEXFMT_YIQ_422 || + info.format == GR_TEXFMT_AYIQ_8422) + { + memcpy(&mm_info[ mmid ].ncc_table, table, sizeof(GuNccTable)); + } + +#ifdef OGL_UTEX + { + FxU32 size = 0; + + for ( GrLOD_t lod = info.largeLod; lod <= info.smallLod; lod++ ) + { + size += PGTexture::MipMapMemRequired( lod, info.aspectRatio, info.format ); + } + + GlideMsg( "size = %d\n", size ); + } +#endif + + grTexDownloadMipMap( mm_info[mmid].tmu, mm_start[ mmid ], mm_info[ mmid ].odd_even_mask, &info ); + } +#ifdef OGL_UTEX + else + { + GlideMsg( "failed\n" ); + } +#endif +} + +void PGUTexture::DownloadMipMapLevel( GrMipMapId_t mmid, GrLOD_t lod, const void **src ) +{ +#ifdef OGL_NOTDONE + GlideMsg("PGUTexture::DownloadMipMapLevel(...)\n"); +#endif +} + +void PGUTexture::MemReset( void ) +{ +#ifdef OGL_UTEX + GlideMsg("Reset\n"); +#endif + + for ( int i = 0; i < MAX_MM; i++ ) + { + mm_info[ i ].valid = false; + } + + m_free_mem = 0; + m_free_id = 0; + m_current_id = GR_NULL_MIPMAP_HANDLE; +} + +void PGUTexture::Source( GrMipMapId_t id ) +{ + if ( ( id >=0 ) && ( id < MAX_MM ) && ( mm_info[ id ].valid ) ) + { + GrTexInfo info; + + info.aspectRatio = mm_info[ id ].aspect_ratio; + info.format = mm_info[ id ].format; + info.largeLod = mm_info[ id ].lod_max; + info.smallLod = mm_info[ id ].lod_min; + + int tmu = mm_info[ id ].tmu; + grTexSource( tmu, mm_start[ id ], mm_info[ id ].odd_even_mask, &info ); + grTexFilterMode( tmu, mm_info[ id ].minfilter_mode, mm_info[ id ].magfilter_mode ); + grTexMipMapMode( tmu, mm_info[ id ].mipmap_mode, mm_info[ id ].trilinear ); + grTexClampMode( tmu, mm_info[ id ].s_clamp_mode, mm_info[ id ].t_clamp_mode ); + grTexLodBiasValue( tmu, mm_info[ id ].lod_bias ); + // Download the ncc table + // @todo: the linux driver utilises both tables and optimises download + // -> No download, no texture recreation + grTexDownloadTable(tmu, GR_NCCTABLE_NCC0, &mm_info[ id ].ncc_table); + m_current_id = id; + } +#ifdef OGL_UTEX + else + { + GlideMsg( "TexSource failed\n" ); + } +#endif +} + +GrMipMapInfo *PGUTexture::GetMipMapInfo( GrMipMapId_t mmid ) +{ + return ( ( mmid >= 0 ) && ( mmid < MAX_MM ) && + ( mm_info[mmid].valid ) ? &( mm_info[ mmid ] ) : NULL ); +} + +FxBool PGUTexture::ChangeAttributes( GrMipMapId_t mmid, int width, int height, + GrTextureFormat_t fmt, GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minFilterMode, + GrTextureFilterMode_t magFilterMode ) +{ +#ifdef OGL_NOTDONE + GlideMsg("PGUTexture::ChangeAttributes(...)\n"); +#endif + + return FXFALSE; +} + +GrMipMapId_t PGUTexture::GetCurrentMipMap( GrChipID_t tmu ) const +{ + return m_current_id; +} + +FxU32 PGUTexture::MemQueryAvail( GrChipID_t tmu ) const +{ + return Textures->GetMemorySize( ) - m_free_mem; +} diff --git a/MacGLide/OpenGLide/PGUTexture.h b/MacGLide/OpenGLide/PGUTexture.h new file mode 100644 index 0000000..7056cc6 --- /dev/null +++ b/MacGLide/OpenGLide/PGUTexture.h @@ -0,0 +1,63 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* PGUTexture Class Definition +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __PGUTEXTURE_H__ +#define __PGUTEXTURE_H__ + +#include "sdk2_glide.h" + +class PGUTexture +{ +public: + FxU32 MemQueryAvail( GrChipID_t tmu ) const; + GrMipMapId_t GetCurrentMipMap( GrChipID_t tmu ) const; + FxBool ChangeAttributes( GrMipMapId_t mmid, int width, int height, + GrTextureFormat_t fmt, GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minFilterMode, + GrTextureFilterMode_t magFilterMode ); + GrMipMapInfo * GetMipMapInfo( GrMipMapId_t mmid ); + void Source( GrMipMapId_t id ); + void MemReset( void ); + void DownloadMipMapLevel( GrMipMapId_t mmid, GrLOD_t lod, const void **src ); + void DownloadMipMap( GrMipMapId_t mmid, const void *src, const GuNccTable *table ); + GrMipMapId_t AllocateMemory( GrChipID_t tmu, FxU8 odd_even_mask, int width, int height, + GrTextureFormat_t fmt, GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode, + float lod_bias, FxBool trilinear ); + + PGUTexture( void ); + virtual ~PGUTexture( void ); + + +private: + + enum { MAX_MM = 1024 }; + + GrMipMapInfo mm_info[ MAX_MM ]; + FxU32 mm_start[ MAX_MM ]; + FxU32 m_free_mem; + GrMipMapId_t m_free_id; + GrMipMapId_t m_current_id; +public: + GrMipMapId_t GetCurrentID() {return m_current_id;}; +}; + +extern PGUTexture UTextures; + +#endif diff --git a/MacGLide/OpenGLide/Precompile.h b/MacGLide/OpenGLide/Precompile.h new file mode 100644 index 0000000..fd161f0 --- /dev/null +++ b/MacGLide/OpenGLide/Precompile.h @@ -0,0 +1,39 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* file for including all precompiled headers +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +// stuff that should be precompiled + +// Setup +#include "System.h" +#include "Debug.h" +#include "Optimise.h" + +// clib +#include +#include +#include +#include +#include +#include +#include +#include + +// opengl +#include +#include +#include + +// openglide +#include "GlOgl.h" +#include "Glide.h" diff --git a/MacGLide/OpenGLide/System.h b/MacGLide/OpenGLide/System.h new file mode 100644 index 0000000..2e759b1 --- /dev/null +++ b/MacGLide/OpenGLide/System.h @@ -0,0 +1,80 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* file for including all platform specific stuff +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#if defined(__MWERKS__) + #if defined(macintosh) + #define OPENGLIDE_HOST_MAC + // Codewarrior specific + #define PP_Target_Carbon 0 + #define PP_Target_Classic (!PP_Target_Carbon) + #define TARGET_API_MAC_CARBON PP_Target_Carbon + #define TARGET_API_MAC_OS8 PP_Target_Classic +// # else if /* Carbon or MachO version */ +// # define OPENGLIDE_HOST_MAC +// # endif /* !macintosh */ + #else /* !macintosh */ + #error "Unknown MetroWerks target platform" + #endif /* !macintosh */ +#endif + +// Mac specific stuff +#ifdef OPENGLIDE_HOST_MAC + // use plain ASCII only + #define __NO_WIDE_CHAR + // headers + #include + // platform specific settings + // macos 9 doesn't provide linkage to fogcoord functions + #define OPENGLIDE_DOESN_T_HAVE_FOGCOORD + // macos 9 doesn't provide linkage to blendfunc seperate function + #define OPENGLIDE_DOESN_T_HAVE_BLENDFUNC_SEPERATE + // C and C++ standard calling convention (used on win32) + #define __cdecl + // #define __stdcall + #define __fastcall +#else + #define OPENGLIDE_SYSTEM_HAS_FOGCOORD + #define OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE +#endif + + +// Glide SDK +#include "sdk2_3dfx.h" +// This is used by CodeWarrior to just export the +// symbols needed for the 3DfxGlideLib2.x library +#if defined(__MWERKS__) + #pragma export on +#endif + #include "sdk2_glide.h" + #include "sdk2_glideutl.h" +#if defined(__MWERKS__) + #pragma export off +#endif +#include "sdk2_glidesys.h" +#include "sdk2_sst1vid.h" + +// Export some more functions needed by pre glide 2.4 games +// (for instance Quake 3dfx on the Mac) +#ifdef OPENGLIDE_HOST_MAC + #if defined(__MWERKS__) + #pragma export on + #endif + #include "grguMisc.h" + #include "grguSstGlide.h" + #include "grLfb.h" + #include "sst1.h" + #if defined(__MWERKS__) + #pragma export off + #endif +#endif diff --git a/MacGLide/OpenGLide/TexDB.cpp b/MacGLide/OpenGLide/TexDB.cpp new file mode 100644 index 0000000..2baec11 --- /dev/null +++ b/MacGLide/OpenGLide/TexDB.cpp @@ -0,0 +1,529 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* implementation of the TexDB class +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "TexDB.h" + +TexDB::Record* TexDB::Record::s_FreeRecords = NULL; +TexDB::RecordArray* TexDB::Record::s_RecordArrays = NULL; +TexDB::SubRecord* TexDB::SubRecord::s_FreeSubRecords = NULL; +int TexDB::RecordArraySize = 16; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +TexDB::TexDB(unsigned int MemorySize) +{ + numberOfTexSections = MemorySize >> 15; // ( 32 * 1024 ); + m_first = new Record*[ numberOfTexSections ]; + for ( unsigned int i = 0; i < numberOfTexSections; i++ ) + { + m_first[ i ] = NULL; + } + #ifdef OPTIMISE_TEXTURE_LOOKUP + // Allocate MemorySize / 2 record pointers, because + // a Glide texture can only be downloaded to 8-byte boundaries + m_texmem_2_record = static_cast(AllocBuffer(MemorySize >> 3, sizeof(Record*))); + memset(m_texmem_2_record, 0, (MemorySize >> 3) * sizeof(Record*)); + #endif + // Prealloc Reocrds proportional to the amount of tex memory + RecordArraySize = MemorySize / (1024 * 1024) * 256; // preallocate 256 records per mb + // Prealloc some texdb records to avoid out of memory problems later + TexDB::Record::Init(); +} + +TexDB::~TexDB( void ) +{ + Clear(); + delete[] m_first; + TexDB::SubRecord::Cleanup(); + #ifdef OPTIMISE_TEXTURE_LOOKUP + if (m_texmem_2_record) FreeBuffer(m_texmem_2_record); + #endif +} + +TexDB::Record* TexDB::Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const +{ + // Perform normal search + FxU32 sect = startAddress >> 15; // ( 32 * 1024 ); + Record* r; +#ifdef OPTIMISE_TEXTURE_LOOKUP + // We can start searching with the record found via the lookup, + // because it's the one added last to this address, + // and records are added to the front of the linked list + r = m_texmem_2_record[startAddress >> 3]; + // If the record has a palette hash, + // then we must find the right paletted texture + if (r == NULL || hash != r->hash) + { + if (r) + { + // Can start from the next record, because we've + // just checked that the current doesn't match + r = r->next; + } + else + { + // lookup empty, search from the beginning + r = m_first[sect]; + } +#else + r = m_first[sect]; +#endif + for (; r; r = r->next) + { + if (r->Match(startAddress, info, (pal_change == NULL) ? hash : 0)) + { + #ifdef OGL_UTEX + GlideMsg("Found tex %d\n", r->texNum); + #endif + break; + } + } +#ifdef OPTIMISE_TEXTURE_LOOKUP + } +#ifdef OGL_UTEX + else if (r) + { + GlideMsg("Found texmem_2_record tex %d\n", r->texNum); + } +#endif +#endif + if (r) + { + if (subtexcoords) + { +#ifdef OGL_UTEX + GlideMsg("Looking for subtexture: "); + GlideMsg("min/max(%g,%g)-(%g,%g), ", + subtexcoords->smin, + subtexcoords->smax, + subtexcoords->tmin, + subtexcoords->tmax); + GlideMsg("w/h(%g,%g), texture(%d,%d)-(%d,%d)\n", + subtexcoords->width, + subtexcoords->height, + subtexcoords->left, + subtexcoords->top, + subtexcoords->texImageWidth, + subtexcoords->texImageHeight); +#endif + // Lookup subrecord + SubRecord* s; + for (s = r->subrecords; s != NULL; s = s->next) + { + if (s->Match(subtexcoords)) + { + // bind textures + r->texNum = s->texNum; + r->tex2Num = s->tex2Num; + // The one we've found might have a greater texture than the one + // we're looking for so we have to update the size + subtexcoords->width = s->left; + subtexcoords->height = s->top; + subtexcoords->smin = s->left; + subtexcoords->tmin = s->top; + subtexcoords->texImageWidth = s->texImageWidth; + subtexcoords->texImageHeight = s->texImageHeight; + #ifdef OGL_UTEX + GlideMsg("Found subtex %d\n", s->texNum); + #endif + break; + } + } + if (s == NULL) + { +#ifdef OGL_UTEX + GlideMsg("Removing smaller subtextures in tex_record %d\n", r->texNum); +#endif + // remove any smaller version of the subtextures to avoid artefacts on snow tiles + // This is ok because we're about to create a new texture that contains all those + // smaller textures we're going to wipe + r->WipeInside(subtexcoords); + r = NULL; + } + } + // Palette changed? + if (( pal_change != NULL) && (r->hash != hash )) + { + r->hash = hash; + *pal_change = true; + } + } + return r; +} + +void TexDB::WipeRange(FxU32 startAddress, FxU32 endAddress, FxU32 hash) +{ + Record** p; + FxU32 stt_sect = startAddress >> 15; // ( 32 * 1024 ); + /* + * Textures can be as large as 128K, so + * one that starts 3 sections back can + * extend into this one. + */ + if (stt_sect < 4) + { + stt_sect = 0; + } + else + { + stt_sect -= 4; + } + FxU32 end_sect = endAddress >> 15; // ( 32 * 1024 ); + if (end_sect >= numberOfTexSections) + { + end_sect = numberOfTexSections - 1; + } + for(FxU32 i = stt_sect; i <= end_sect; i++) + { + p = &(m_first[i]); + while (*p != NULL) + { + Record* r = *p; + if ((startAddress < r->endAddress) && + (r->startAddress < endAddress) && + ((hash == 0) || (r->hash == hash))) + { + *p = r->next; +#ifdef OPTIMISE_TEXTURE_LOOKUP + m_texmem_2_record[(r->startAddress) >> 3] = NULL; +#endif + delete r; +#ifdef OGL_UTEX + if (hash) + { + GlideMsg("Wipe tex %d, hash 0x%x\n", r->texNum, r->hash); + } + else + { + GlideMsg("Wipe tex %d\n", r->texNum); + } +#endif + } + else + { + p = &(r->next); + } + } + } +} + +TexDB::Record* TexDB::Add(FxU32 startAddress, FxU32 endAddress, const GrTexInfo *info, FxU32 hash, TexDB::TextureMode texturemode, const SubTexCoord_t* subtexcoords) +{ + Record *r = NULL; + // Check for existing record + if (subtexcoords) + { +#ifdef OPTIMISE_TEXTURE_LOOKUP + // lookup record + r = m_texmem_2_record[startAddress >> 3]; + // needed by TR 1 Gold to work correctly + if (r == NULL || r->Match( startAddress, info, 0) == false) + { +#endif + // @todo: don't do it twice (here and in Find()) + FxU32 sect = startAddress >> 15; // ( 32 * 1024 ); + for (r = m_first[ sect ]; r != NULL; r = r->next ) + { + if ( r->Match( startAddress, info, 0 /*( pal_change == NULL ) ? hash : 0 )*/ )) + { + break; + } + } +#ifdef OPTIMISE_TEXTURE_LOOKUP + } +#endif + } + else + { +#ifdef OGL_UTEX +#ifdef OPTIMISE_TEXTURE_LOOKUP + // lookup record + r = m_texmem_2_record[startAddress >> 3]; + if (r) + { + GlideMsg("Warning: Existing TexRecord must be wiped first%d\n", r->texNum); + return NULL; + } +#endif +#endif + } + // Create new record? + if (r == NULL) + { + r = new Record(texturemode); + FxU32 sect = startAddress >> 15; // 32 * 1024 + r->startAddress = startAddress; + r->endAddress = endAddress; + r->info = *info; + r->hash = hash; + r->next = m_first[sect]; + m_first[sect] = r; + r->subrecords = NULL; +#ifdef OPTIMISE_TEXTURE_LOOKUP + // lookup record + m_texmem_2_record[startAddress >> 3] = r; +#endif +#ifdef OGL_UTEX + GlideMsg("Add tex %d\n", r->texNum); +#endif + } + if (subtexcoords) + { + SubRecord* s = new SubRecord(texturemode); + s->left = subtexcoords->left; + s->top = subtexcoords->top; + s->texImageWidth = subtexcoords->texImageWidth; + s->texImageHeight = subtexcoords->texImageHeight; + s->next = r->subrecords; + r->subrecords = s; + // The caller always queries r for texture names, thus we have to copy + // Note: For debugging the caching efficency, comment out the assignment + r->texNum = s->texNum; + r->tex2Num = s->tex2Num; +#ifdef OGL_UTEX + GlideMsg("Add subtex %d\n", s->texNum); +#endif + } + + return r; +} + +void TexDB::Clear( void ) +{ + Record* r; + for ( unsigned int i = 0; i < numberOfTexSections; i++ ) + { + r = m_first[ i ]; + while ( r != NULL ) + { + Record *tmp = r; + r = r->next; + #ifdef OPTIMISE_TEXTURE_LOOKUP + // lookup record + m_texmem_2_record[(tmp->startAddress) >> 3] = NULL; + #endif + delete tmp; + } + m_first[ i ] = NULL; + } +} + +/////////////////////////////////////////////////////////////////// +// TexDB::Record Class implementation +/////////////////////////////////////////////////////////////////// + +void TexDB::Record::Init() +{ + // Alloc a couple of records in advance + AllocRecords(); +} + +void TexDB::Record::Cleanup() +{ + RecordArray* ra = s_RecordArrays; + while (ra) + { + RecordArray* next = ra->next; + FreeObject(ra); +#ifdef OGL_UTEX_MEM + GlideMsg("Freed TexDB record array at 0x%x\n", ra); +#endif + ra = next; + } + s_RecordArrays = NULL; + s_FreeRecords = NULL; + return; +} + +void TexDB::Record::AllocRecords() +{ +#ifdef OGL_UTEX_MEM + GlideMsg("Allocating TexDB record array with %d entries\n", RecordArraySize); +#endif + RecordArray* next = s_RecordArrays ? s_RecordArrays->next : NULL; + s_RecordArrays = static_cast(AllocObject(sizeof(RecordArray) + (RecordArraySize -1) * sizeof(Record))); + s_RecordArrays->next = next; + for(int i = 0; i < RecordArraySize; i++) + { + s_RecordArrays->records[i].next = s_FreeRecords; + s_FreeRecords = &s_RecordArrays->records[i]; + } +} + +void* TexDB::Record::operator new(size_t s) +{ + Record* p; + if (s_FreeRecords == NULL) + { + AllocRecords(); + } + p = s_FreeRecords; + s_FreeRecords = p->next; +#ifdef OGL_UTEX_MEM + GlideMsg("Using TexDB record at 0x%x\n", p); +#endif + return p; +} + +void TexDB::Record::operator delete(void* p) +{ +#ifdef OGL_UTEX_MEM + GlideMsg("Moving TexDB record at 0x%x to free list\n", p); +#endif + reinterpret_cast(p)->next = s_FreeRecords; + s_FreeRecords = reinterpret_cast(p); +} + +TexDB::Record::Record(TexDB::TextureMode texturemode) +{ + if (texturemode <= Two) + { + GLfloat one; + glGenTextures(1, &texNum); + glPrioritizeTextures(1, &texNum, &one); + if (texturemode == TexDB::Two ) + { + glGenTextures(1, &tex2Num); + glPrioritizeTextures(1, &tex2Num, &one); + } + else + { + tex2Num = 0; + } + } +} + +TexDB::Record::~Record(void) +{ + if (subrecords == NULL) + { + glDeleteTextures(1, &texNum); + if (tex2Num != 0) + { + glDeleteTextures(1, &tex2Num); + } + } + else + { + SubRecord* next = this->subrecords; + for (SubRecord* s = next; next != NULL; s = next) + { + next = s->next; + delete s; + } + } +} + +void TexDB::Record::WipeInside(const SubTexCoord_t* subtexcoords) +{ + SubRecord** head = &subrecords; + SubRecord* s = *head; + while (s) + { + if (s->IsInside(subtexcoords)) + { +#ifdef OGL_UTEX + GlideMsg("Removing subtexture %d: ", s->texNum); + GlideMsg("texture(%d,%d)-(%d,%d)\n", + s->left, + s->top, + s->texImageWidth, + s->texImageHeight); +#endif + *head = s->next; + delete s; + s = *head; + } + else + { + head = &s->next; + s = s->next; + } + } +} + +/////////////////////////////////////////////////////////////////// +// TexDB::SubRecord Class implementation +/////////////////////////////////////////////////////////////////// + +TexDB::SubRecord::SubRecord(TexDB::TextureMode texturemode) +{ + glGenTextures(1, &texNum); + if (texturemode == TexDB::SubTextureTwo) + { + glGenTextures(1, &tex2Num); + } + else + { + tex2Num = 0; + } +} + +TexDB::SubRecord::~SubRecord( void ) +{ + glDeleteTextures(1, &texNum); + if (tex2Num != 0) + { + glDeleteTextures(1, &tex2Num); + } +} + +void* TexDB::SubRecord::operator new(size_t s) +{ + SubRecord* p; + if (s_FreeSubRecords == NULL) + { + p = reinterpret_cast(NewPtrSys(s)); +#ifdef OGL_UTEX_MEM + GlideMsg("Allocated TexDB subrecord at 0x%x\n", p); +#endif + } + else + { + p = s_FreeSubRecords; + s_FreeSubRecords = p->next; +#ifdef OGL_UTEX_MEM + GlideMsg("Using TexDB subrecord at 0x%x\n", p); +#endif + } + return p; +} + +void TexDB::SubRecord::operator delete(void* p) +{ +#ifdef OGL_UTEX_MEM + GlideMsg("Moving TexDB subrecord at 0x%x to free-list\n", p); +#endif +// reinterpret_cast(p)->next = s_FreeSubRecords; + SubRecord* s = reinterpret_cast(p); + s->next = s_FreeSubRecords; + s_FreeSubRecords = s; +} + +void TexDB::SubRecord::Cleanup() +{ + SubRecord* s = s_FreeSubRecords; + while (s) + { +#ifdef OGL_UTEX_MEM + GlideMsg("Deleting TexDB subrecord at 0x%x\n", s); +#endif + SubRecord* next = s->next; + DisposePtr(reinterpret_cast(s)); + s = next; + } + s_FreeSubRecords = NULL; + return; +} diff --git a/MacGLide/OpenGLide/TexDB.h b/MacGLide/OpenGLide/TexDB.h new file mode 100644 index 0000000..ee5e7b3 --- /dev/null +++ b/MacGLide/OpenGLide/TexDB.h @@ -0,0 +1,137 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* TexDB Class Definition +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef __TEXDB_H__ +#define __TEXDB_H__ + + struct SubTexCoord_t + { + GLfloat smin; // min max values rfor s & t + GLfloat smax; + GLfloat tmin; + GLfloat tmax; + GLfloat width; // size in OpenGL tex coords + GLfloat height; + unsigned int left; // Pixel origin of the sub texture + unsigned int top; + unsigned int texImageWidth; // power of two + unsigned int texImageHeight; // power of two + }; + +class TexDB +{ +public: + void Clear( void ); + enum TextureMode + { + One = 0, + Two = 1, + SubTextureOne = 2, + SubTextureTwo = 3 + }; + struct SubRecord + { + public: + SubRecord *next; + public: + GLuint texNum; + GLuint tex2Num; + unsigned int left; + unsigned int top; + unsigned int texImageWidth; + unsigned int texImageHeight; + SubRecord(TexDB::TextureMode texturemode); + ~SubRecord(void); + inline bool Match(const SubTexCoord_t* subtexcoords) const + { + return (subtexcoords->smin >= left && + subtexcoords->tmin >= top && + subtexcoords->smax <= left + texImageWidth && + subtexcoords->tmax <= top + texImageHeight); + }; + inline bool IsInside(const SubTexCoord_t* subtexcoords) const + { + return (subtexcoords->left > left && + subtexcoords->top > top && + subtexcoords->left + subtexcoords->texImageWidth < left + texImageWidth && + subtexcoords->top + subtexcoords->texImageHeight < top + texImageHeight); + }; + void* operator new(size_t s); + void operator delete(void* p); + static void Cleanup(); + static SubRecord* s_FreeSubRecords; + private: + void* operator new[](size_t s); // not used so we don't need an implementation + void operator delete[](void* p); + }; + + struct RecordArray; + class Record + { + protected: + static Record* s_FreeRecords; + static RecordArray* s_RecordArrays; + static void AllocRecords(); + public: + FxU32 startAddress; + FxU32 endAddress; + Record *next; + SubRecord *subrecords; + public: + GrTexInfo info; + FxU32 hash; + GLuint texNum; + GLuint tex2Num; + GLuint SClampMode; + GLuint TClampMode; + GLuint MinFilterMode; + GLuint MagFilterMode; + public: + Record(TexDB::TextureMode texturemode); + ~Record(void); + inline bool Match(FxU32 stt, const GrTexInfo *inf, FxU32 h) const + { + return ((startAddress == stt) && + (inf->largeLod == info.largeLod) && + (inf->aspectRatio == info.aspectRatio) && + (inf->format == info.format) && + ((hash == h) || (h == 0))); + } + void WipeInside(const SubTexCoord_t* subtexcoords); + void* operator new(size_t s); + void operator delete(void* p); + static void Init(); + static void Cleanup(); + private: + void* operator new[](size_t s); // not used so we don't need an implementation + void operator delete[](void* p); // not used so we don't need an implementation + }; + static int RecordArraySize; + struct RecordArray + { + RecordArray* next; + Record records[1]; + }; + Record* Add(FxU32 startAddress, FxU32 endAddress, const GrTexInfo *info, FxU32 hash, TexDB::TextureMode texturemode, const SubTexCoord_t* subtexcoords); + Record* Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const; + void WipeRange(FxU32 startAddress, FxU32 endAddress, FxU32 hash); + TexDB(unsigned int MemorySize); + virtual ~TexDB(void); +private: + unsigned int numberOfTexSections; + Record** m_first; + #ifdef OPTIMISE_TEXTURE_LOOKUP + Record** m_texmem_2_record; + #endif +}; + +#endif diff --git a/MacGLide/OpenGLide/amd3dx.h b/MacGLide/OpenGLide/amd3dx.h new file mode 100644 index 0000000..33d6f92 --- /dev/null +++ b/MacGLide/OpenGLide/amd3dx.h @@ -0,0 +1,1187 @@ +/****************************************************************************** + + Copyright (c) 1999 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com + +******************************************************************************* + + AMD3DX.H + + MACRO FORMAT + ============ + This file contains inline assembly macros that + generate AMD-3D instructions in binary format. + Therefore, C or C++ programmer can use AMD-3D instructions + without any penalty in their C or C++ source code. + + The macro's name and format conventions are as follow: + + + 1. First argument of macro is a destination and + second argument is a source operand. + ex) _asm PFCMPEQ (mm3, mm4) + | | + dst src + + 2. The destination operand can be m0 to m7 only. + The source operand can be any one of the register + m0 to m7 or _eax, _ecx, _edx, _ebx, _esi, or _edi + that contains effective address. + ex) _asm PFRCP (MM7, MM6) + ex) _asm PFRCPIT2 (mm0, mm4) + ex) _asm PFMUL (mm3, _edi) + + 3. The prefetch(w) takes one src operand _eax, ecx, _edx, + _ebx, _esi, or _edi that contains effective address. + ex) _asm PREFETCH (_edi) + + For WATCOM C/C++ users, when using #pragma aux instead if + _asm, all macro names should be prefixed by a p_ or P_. + Macros should not be enclosed in quotes. + ex) p_pfrcp (MM7,MM6) + + NOTE: Not all instruction macros, nor all possible + combinations of operands have been explicitely + tested. If any errors are found, please report + them. + + EXAMPLE + ======= + Following program doesn't do anything but it shows you + how to use inline assembly AMD-3D instructions in C. + Note that this will only work in flat memory model which + segment registers cs, ds, ss and es point to the same + linear address space total less than 4GB. + + Used Microsoft VC++ 5.0 + + #include + #include "amd3d.h" + + void main () + { + float x = (float)1.25; + float y = (float)1.25; + float z, zz; + + _asm { + movd mm1, x + movd mm2, y + pfmul (mm1, mm2) + movd z, mm1 + femms + } + + printf ("value of z = %f\n", z); + + // + // Demonstration of using the memory instead of + // multimedia register + // + _asm { + movd mm3, x + lea esi, y // load effective address of y + pfmul (mm3, _esi) + movd zz, mm3 + femms + } + + printf ("value of zz = %f\n", zz); + } + + #pragma aux EXAMPLE with WATCOM C/C++ v11.x + =========================================== + + extern void Add(float *__Dest, float *__A, float *__B); + #pragma aux Add = \ + p_femms \ + "movd mm6,[esi]" \ + p_pfadd(mm6,_edi) \ + "movd [ebx],mm6" \ + p_femms \ + parm [ebx] [esi] [edi]; + +*******************************************************************************/ + +#ifndef _K3DMACROSINCLUDED_ +#define _K3DMACROSINCLUDED_ + +#if defined (__WATCOMC__) + +// The WATCOM C/C++ version of the 3DNow! macros. +// +// The older, compbined register style for WATCOM C/C++ macros is not +// supported. + +/* Operand defines for instructions two operands */ +#define _k3d_mm0_mm0 0xc0 +#define _k3d_mm0_mm1 0xc1 +#define _k3d_mm0_mm2 0xc2 +#define _k3d_mm0_mm3 0xc3 +#define _k3d_mm0_mm4 0xc4 +#define _k3d_mm0_mm5 0xc5 +#define _k3d_mm0_mm6 0xc6 +#define _k3d_mm0_mm7 0xc7 +#define _k3d_mm0_eax 0x00 +#define _k3d_mm0_ecx 0x01 +#define _k3d_mm0_edx 0x02 +#define _k3d_mm0_ebx 0x03 +#define _k3d_mm0_esi 0x06 +#define _k3d_mm0_edi 0x07 +#define _k3d_mm1_mm0 0xc8 +#define _k3d_mm1_mm1 0xc9 +#define _k3d_mm1_mm2 0xca +#define _k3d_mm1_mm3 0xcb +#define _k3d_mm1_mm4 0xcc +#define _k3d_mm1_mm5 0xcd +#define _k3d_mm1_mm6 0xce +#define _k3d_mm1_mm7 0xcf +#define _k3d_mm1_eax 0x08 +#define _k3d_mm1_ecx 0x09 +#define _k3d_mm1_edx 0x0a +#define _k3d_mm1_ebx 0x0b +#define _k3d_mm1_esi 0x0e +#define _k3d_mm1_edi 0x0f +#define _k3d_mm2_mm0 0xd0 +#define _k3d_mm2_mm1 0xd1 +#define _k3d_mm2_mm2 0xd2 +#define _k3d_mm2_mm3 0xd3 +#define _k3d_mm2_mm4 0xd4 +#define _k3d_mm2_mm5 0xd5 +#define _k3d_mm2_mm6 0xd6 +#define _k3d_mm2_mm7 0xd7 +#define _k3d_mm2_eax 0x10 +#define _k3d_mm2_ecx 0x11 +#define _k3d_mm2_edx 0x12 +#define _k3d_mm2_ebx 0x13 +#define _k3d_mm2_esi 0x16 +#define _k3d_mm2_edi 0x17 +#define _k3d_mm3_mm0 0xd8 +#define _k3d_mm3_mm1 0xd9 +#define _k3d_mm3_mm2 0xda +#define _k3d_mm3_mm3 0xdb +#define _k3d_mm3_mm4 0xdc +#define _k3d_mm3_mm5 0xdd +#define _k3d_mm3_mm6 0xde +#define _k3d_mm3_mm7 0xdf +#define _k3d_mm3_eax 0x18 +#define _k3d_mm3_ecx 0x19 +#define _k3d_mm3_edx 0x1a +#define _k3d_mm3_ebx 0x1b +#define _k3d_mm3_esi 0x1e +#define _k3d_mm3_edi 0x1f +#define _k3d_mm4_mm0 0xe0 +#define _k3d_mm4_mm1 0xe1 +#define _k3d_mm4_mm2 0xe2 +#define _k3d_mm4_mm3 0xe3 +#define _k3d_mm4_mm4 0xe4 +#define _k3d_mm4_mm5 0xe5 +#define _k3d_mm4_mm6 0xe6 +#define _k3d_mm4_mm7 0xe7 +#define _k3d_mm4_eax 0x20 +#define _k3d_mm4_ecx 0x21 +#define _k3d_mm4_edx 0x22 +#define _k3d_mm4_ebx 0x23 +#define _k3d_mm4_esi 0x26 +#define _k3d_mm4_edi 0x27 +#define _k3d_mm5_mm0 0xe8 +#define _k3d_mm5_mm1 0xe9 +#define _k3d_mm5_mm2 0xea +#define _k3d_mm5_mm3 0xeb +#define _k3d_mm5_mm4 0xec +#define _k3d_mm5_mm5 0xed +#define _k3d_mm5_mm6 0xee +#define _k3d_mm5_mm7 0xef +#define _k3d_mm5_eax 0x28 +#define _k3d_mm5_ecx 0x29 +#define _k3d_mm5_edx 0x2a +#define _k3d_mm5_ebx 0x2b +#define _k3d_mm5_esi 0x2e +#define _k3d_mm5_edi 0x2f +#define _k3d_mm6_mm0 0xf0 +#define _k3d_mm6_mm1 0xf1 +#define _k3d_mm6_mm2 0xf2 +#define _k3d_mm6_mm3 0xf3 +#define _k3d_mm6_mm4 0xf4 +#define _k3d_mm6_mm5 0xf5 +#define _k3d_mm6_mm6 0xf6 +#define _k3d_mm6_mm7 0xf7 +#define _k3d_mm6_eax 0x30 +#define _k3d_mm6_ecx 0x31 +#define _k3d_mm6_edx 0x32 +#define _k3d_mm6_ebx 0x33 +#define _k3d_mm6_esi 0x36 +#define _k3d_mm6_edi 0x37 +#define _k3d_mm7_mm0 0xf8 +#define _k3d_mm7_mm1 0xf9 +#define _k3d_mm7_mm2 0xfa +#define _k3d_mm7_mm3 0xfb +#define _k3d_mm7_mm4 0xfc +#define _k3d_mm7_mm5 0xfd +#define _k3d_mm7_mm6 0xfe +#define _k3d_mm7_mm7 0xff +#define _k3d_mm7_eax 0x38 +#define _k3d_mm7_ecx 0x39 +#define _k3d_mm7_edx 0x3a +#define _k3d_mm7_ebx 0x3b +#define _k3d_mm7_esi 0x3e +#define _k3d_mm7_edi 0x3f + +#define _k3d_name_xlat_m0 _mm0 +#define _k3d_name_xlat_m1 _mm1 +#define _k3d_name_xlat_m2 _mm2 +#define _k3d_name_xlat_m3 _mm3 +#define _k3d_name_xlat_m4 _mm4 +#define _k3d_name_xlat_m5 _mm5 +#define _k3d_name_xlat_m6 _mm6 +#define _k3d_name_xlat_m7 _mm7 +#define _k3d_name_xlat_M0 _mm0 +#define _k3d_name_xlat_M1 _mm1 +#define _k3d_name_xlat_M2 _mm2 +#define _k3d_name_xlat_M3 _mm3 +#define _k3d_name_xlat_M4 _mm4 +#define _k3d_name_xlat_M5 _mm5 +#define _k3d_name_xlat_M6 _mm6 +#define _k3d_name_xlat_M7 _mm7 +#define _k3d_name_xlat_mm0 _mm0 +#define _k3d_name_xlat_mm1 _mm1 +#define _k3d_name_xlat_mm2 _mm2 +#define _k3d_name_xlat_mm3 _mm3 +#define _k3d_name_xlat_mm4 _mm4 +#define _k3d_name_xlat_mm5 _mm5 +#define _k3d_name_xlat_mm6 _mm6 +#define _k3d_name_xlat_mm7 _mm7 +#define _k3d_name_xlat_MM0 _mm0 +#define _k3d_name_xlat_MM1 _mm1 +#define _k3d_name_xlat_MM2 _mm2 +#define _k3d_name_xlat_MM3 _mm3 +#define _k3d_name_xlat_MM4 _mm4 +#define _k3d_name_xlat_MM5 _mm5 +#define _k3d_name_xlat_MM6 _mm6 +#define _k3d_name_xlat_MM7 _mm7 +#define _k3d_name_xlat_eax _eax +#define _k3d_name_xlat_ebx _ebx +#define _k3d_name_xlat_ecx _ecx +#define _k3d_name_xlat_edx _edx +#define _k3d_name_xlat_esi _esi +#define _k3d_name_xlat_edi _edi +#define _k3d_name_xlat_ebp _ebp +#define _k3d_name_xlat_EAX _eax +#define _k3d_name_xlat_EBX _ebx +#define _k3d_name_xlat_ECX _ecx +#define _k3d_name_xlat_EDX _edx +#define _k3d_name_xlat_ESI _esi +#define _k3d_name_xlat_EDI _edi +#define _k3d_name_xlat_EBP _ebp +#define _k3d_name_xlat__eax _eax +#define _k3d_name_xlat__ebx _ebx +#define _k3d_name_xlat__ecx _ecx +#define _k3d_name_xlat__edx _edx +#define _k3d_name_xlat__esi _esi +#define _k3d_name_xlat__edi _edi +#define _k3d_name_xlat__ebp _ebp +#define _k3d_name_xlat__EAX _eax +#define _k3d_name_xlat__EBX _ebx +#define _k3d_name_xlat__ECX _ecx +#define _k3d_name_xlat__EDX _edx +#define _k3d_name_xlat__ESI _esi +#define _k3d_name_xlat__EDI _edi +#define _k3d_name_xlat__EBP _ebp + +#define _k3d_xglue3(a,b,c) a##b##c +#define _k3d_glue3(a,b,c) _k3d_xglue3(a,b,c) +#define _k3d_MODRM(dst, src) _k3d_glue3(_k3d,_k3d_name_xlat_##dst,_k3d_name_xlat_##src) + +/* Operand defines for prefetch and prefetchw */ + +#define _k3d_pref_eax 0x00 +#define _k3d_pref_ecx 0x01 +#define _k3d_pref_edx 0x02 +#define _k3d_pref_ebx 0x03 +#define _k3d_pref_esi 0x06 +#define _k3d_pref_edi 0x07 +#define _k3d_pref_EAX 0x00 +#define _k3d_pref_ECX 0x01 +#define _k3d_pref_EDX 0x02 +#define _k3d_pref_EBX 0x03 +#define _k3d_pref_ESI 0x06 +#define _k3d_pref_EDI 0x07 +#define _k3d_prefw_eax 0x08 +#define _k3d_prefw_ecx 0x09 +#define _k3d_prefw_edx 0x0A +#define _k3d_prefw_ebx 0x0B +#define _k3d_prefw_esi 0x0E +#define _k3d_prefw_edi 0x0F +#define _k3d_prefw_EAX 0x08 +#define _k3d_prefw_ECX 0x09 +#define _k3d_prefw_EDX 0x0A +#define _k3d_prefw_EBX 0x0B +#define _k3d_prefw_ESI 0x0E +#define _k3d_prefw_EDI 0x0F + +/* Defines for 3DNow! instructions */ +#define PF2ID(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x1d +#define PFACC(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xae +#define PFADD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9e +#define PFCMPEQ(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb0 +#define PFCMPGE(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x90 +#define PFCMPGT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa0 +#define PFMAX(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa4 +#define PFMIN(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x94 +#define PFMUL(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb4 +#define PFRCP(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x96 +#define PFRCPIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa6 +#define PFRCPIT2(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb6 +#define PFRSQRT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x97 +#define PFRSQIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa7 +#define PFSUB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9a +#define PFSUBR(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xaa +#define PI2FD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x0d +#define FEMMS db 0x0f, 0x0e +#define PAVGUSB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xbf +#define PMULHRW(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb7 +#define PREFETCH(src) db 0x0f, 0x0d, _k3d_pref_##src +#define PREFETCHW(src) db 0x0f, 0x0d, _k3d_prefw_##src +#define CPUID db 0x0f, 0xa2 + +/* Defines for new, K7 opcodes */ +#define PFNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8a +#define FPPNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8e +#define PSWAPD(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0xbb +#define PMINUB(dst,src) db 0x0f, 0xda, _k3d_MODRM(dst,src) +#define PMAXUB(dst,src) db 0x0f, 0xde, _k3d_MODRM(dst,src) +#define PMINSW(dst,src) db 0x0f, 0xea, _k3d_MODRM(dst,src) +#define PMAXSW(dst,src) db 0x0f, 0xee, _k3d_MODRM(dst,src) +#define PMULHUW(dst,src) db 0x0f, 0xe4, _k3d_MODRM(dst,src) +#define PAVGB(dst,src) db 0x0f, 0xe0, _k3d_MODRM(dst,src) +#define PAVGW(dst,src) db 0x0f, 0xe3, _k3d_MODRM(dst,src) +#define PSADBW(dst,src) db 0x0f, 0xf6, _k3d_MODRM(dst,src) +#define PMOVMSKB(dst,src) db 0x0f, 0xd7, _k3d_MODRM(dst,src) +#define PMASKMOVQ(dst,src) db 0x0f, 0xf7, _k3d_MODRM(dst,src) +#define PINSRW(dst,src,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src), msk +#define PEXTRW(dst,src,msk) db 0x0f, 0xc5, _k3d_MODRM(dst,src), msk +#define PSHUFW(dst,src,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src), msk +#define MOVNTQ(dst,src) db 0x0f, 0xe7, _k3d_MODRM(src,dst) +#define SFENCE db 0x0f, 0xae, 0xf8 + +/* Memory/offset versions of the opcodes */ +#define PF2IDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x1d +#define PFACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xae +#define PFADDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9e +#define PFCMPEQM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb0 +#define PFCMPGEM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x90 +#define PFCMPGTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa0 +#define PFMAXM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa4 +#define PFMINM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x94 +#define PFMULM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb4 +#define PFRCPM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x96 +#define PFRCPIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa6 +#define PFRCPIT2M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb6 +#define PFRSQRTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x97 +#define PFRSQIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa7 +#define PFSUBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9a +#define PFSUBRM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xaa +#define PI2FDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x0d +#define PAVGUSBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbf +#define PMULHRWM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb7 + + +/* Memory/offset versions of the new, K7 opcodes */ +#define PFNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8a +#define FPPNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8e +#define PSWAPDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbb +#define PMINUBM(dst,src,off) db 0x0f, 0xda, _k3d_MODRM(dst,src) | 0x40, off +#define PMAXUBM(dst,src,off) db 0x0f, 0xde, _k3d_MODRM(dst,src) | 0x40, off +#define PMINSWM(dst,src,off) db 0x0f, 0xea, _k3d_MODRM(dst,src) | 0x40, off +#define PMAXSWM(dst,src,off) db 0x0f, 0xee, _k3d_MODRM(dst,src) | 0x40, off +#define PMULHUWM(dst,src,off) db 0x0f, 0xe4, _k3d_MODRM(dst,src) | 0x40, off +#define PAVGBM(dst,src,off) db 0x0f, 0xe0, _k3d_MODRM(dst,src) | 0x40, off +#define PAVGWM(dst,src,off) db 0x0f, 0xe3, _k3d_MODRM(dst,src) | 0x40, off +#define PSADBWM(dst,src,off) db 0x0f, 0xf6, _k3d_MODRM(dst,src) | 0x40, off +#define PMOVMSKBM(dst,src,off) db 0x0f, 0xd7, _k3d_MODRM(dst,src) | 0x40, off +#define PMASKMOVQM(dst,src,off) db 0x0f, 0xf7, _k3d_MODRM(dst,src) | 0x40, off +#define MOVNTQM(dst,src,off) db 0x0f, 0xe7, _k3d_MODRM(src,dst) | 0x40, off +#define PINSRWM(dst,src,off,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src) | 0x40, off, msk +#define PSHUFWM(dst,src,off,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src) | 0x40, off, msk + + +/* Defines for 3DNow! instructions for use in pragmas */ +#define p_pf2id(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x1d +#define p_pfacc(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xae +#define p_pfadd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9e +#define p_pfcmpeq(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb0 +#define p_pfcmpge(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x90 +#define p_pfcmpgt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa0 +#define p_pfmax(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa4 +#define p_pfmin(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x94 +#define p_pfmul(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb4 +#define p_pfrcp(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x96 +#define p_pfrcpit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa6 +#define p_pfrcpit2(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb6 +#define p_pfrsqrt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x97 +#define p_pfrsqit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa7 +#define p_pfsub(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9a +#define p_pfsubr(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xaa +#define p_pi2fd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x0d +#define p_femms 0x0f 0x0e +#define p_pavgusb(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xbf +#define p_pmulhrw(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb7 +#define p_prefetch(src) 0x0f 0x0d _k3d_pref_##src +#define p_prefetchw(src) 0x0f 0x0d _k3d_prefw_##src +#define P_PFNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a +#define P_FPPNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e +#define P_PSWAPD(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb +#define P_PMINUB(dst,src) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXUB(dst,src) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMINSW(dst,src) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXSW(dst,src) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMULHUW(dst,src) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGB(dst,src) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGW(dst,src) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PSADBW(dst,src) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMOVMSKB(dst,src) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMASKMOVQ(dst,src) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PINSRW(dst,src,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PEXTRW(dst,src,msk) 0x0f 0xc5 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PSHUFW(dst,src,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_MOVNTQ(dst,src) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off + +#define P_PF2IDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x1d +#define P_PFACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xae +#define P_PFADDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9e +#define P_PFCMPEQM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb0 +#define P_PFCMPGEM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x90 +#define P_PFCMPGTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa0 +#define P_PFMAXM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa4 +#define P_PFMINM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x94 +#define P_PFMULM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb4 +#define P_PFRCPM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x96 +#define P_PFRCPIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa6 +#define P_PFRCPIT2M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb6 +#define P_PFRSQRTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x97 +#define P_PFRSQIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa7 +#define P_PFSUBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9a +#define P_PFSUBRM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xaa +#define P_PI2FDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x0d +#define P_PAVGUSBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbf +#define P_PMULHRWM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb7 +#define P_PFNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a +#define P_FPPNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e +#define P_PSWAPDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb +#define P_PMINUBM(dst,src,off) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXUBM(dst,src,off) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMINSWM(dst,src,off) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMAXSWM(dst,src,off) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMULHUWM(dst,src,off) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGBM(dst,src,off) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PAVGWM(dst,src,off) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PSADBWM(dst,src,off) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PMOVMSKBM(dst,src,off) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_MOVNTQM(dst,src,off) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off +#define P_PMASKMOVQM(dst,src,off) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off +#define P_PINSRWM(dst,src,off,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk +#define P_PSHUFWM(dst,src,off,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk + + +#define P_PF2ID(dst,src) p_pf2id(dst,src) +#define P_PFACC(dst,src) p_pfacc(dst,src) +#define P_PFADD(dst,src) p_pfadd(dst,src) +#define P_PFCMPEQ(dst,src) p_pfcmpeq(dst,src) +#define P_PFCMPGE(dst,src) p_pfcmpge(dst,src) +#define P_PFCMPGT(dst,src) p_pfcmpgt(dst,src) +#define P_PFMAX(dst,src) p_pfmax(dst,src) +#define P_PFMIN(dst,src) p_pfmin(dst,src) +#define P_PFMUL(dst,src) p_pfmul(dst,src) +#define P_PFRCP(dst,src) p_pfrcp(dst,src) +#define P_PFRCPIT1(dst,src) p_pfrcpit1(dst,src) +#define P_PFRCPIT2(dst,src) p_pfrcpit2(dst,src) +#define P_PFRSQRT(dst,src) p_pfrsqrt(dst,src) +#define P_PFRSQIT1(dst,src) p_pfrsqit1(dst,src) +#define P_PFSUB(dst,src) p_pfsub(dst,src) +#define P_PFSUBR(dst,src) p_pfsubr(dst,src) +#define P_PI2FD(dst,src) p_pi2fd(dst,src) +#define P_FEMMS p_femms +#define P_PAVGUSB(dst,src) p_pavgusb(dst,src) +#define P_PMULHRW(dst,src) p_pmulhrw(dst,src) +#define P_PREFETCH(src) p_prefetch(src) +#define P_PREFETCHW(src) p_prefetchw(src) +#define p_CPUID 0x0f 0xa2 +#define p_pf2idm(dst,src,off) P_PF2IDM(dst,src,off) +#define p_pfaccm(dst,src,off) P_PFACCM(dst,src,off) +#define p_pfaddm(dst,src,off) P_PFADDM(dst,src,off) +#define p_pfcmpeqm(dst,src,off) P_PFCMPEQM(dst,src,off) +#define p_pfcmpgem(dst,src,off) P_PFCMPGEM(dst,src,off) +#define p_pfcmpgtm(dst,src,off) P_PFCMPGTM(dst,src,off) +#define p_pfmaxm(dst,src,off) P_PFMAXM(dst,src,off) +#define p_pfminm(dst,src,off) P_PFMINM(dst,src,off) +#define p_pfmulm(dst,src,off) P_PFMULM(dst,src,off) +#define p_pfrcpm(dst,src,off) P_PFRCPM(dst,src,off) +#define p_pfrcpit1m(dst,src,off) P_PFRCPIT1M(dst,src,off) +#define p_pfrcpit2m(dst,src,off) P_PFRCPIT2M(dst,src,off) +#define p_pfrsqrtm(dst,src,off) P_PFRSQRTM(dst,src,off) +#define p_pfrsqit1m(dst,src,off) P_PFRSQIT1M(dst,src,off) +#define p_pfsubm(dst,src,off) P_PFSUBM(dst,src,off) +#define p_pfsubrm(dst,src,off) P_PFSUBRM(dst,src,off) +#define p_pi2fdm(dst,src,off) P_PI2FDM(dst,src,off) +#define p_pavgusbm(dst,src,off) P_PAVGUSBM(dst,src,off) +#define p_pmulhrwm(dst,src,off) P_PMULHRWM(dst,src,off) + +#define P_PFNACC(dst,src) p_pfnacc(dst,src) +#define P_FPPNACC(dst,src) p_pfpnacc(dst,src) +#define P_PSWAPD(dst,src) p_pswapd(dst,src) +#define P_PMINUB(dst,src) p_pminub(dst,src) +#define P_PMAXUB(dst,src) p_pmaxub(dst,src) +#define P_PMINSW(dst,src) p_pminsw(dst,src) +#define P_PMAXSW(dst,src) p_pmaxsw(dst,src) +#define P_PMULHUW(dst,src) p_pmulhuw(dst,src) +#define P_PAVGB(dst,src) p_pavgb(dst,src) +#define P_PAVGW(dst,src) p_avgw(dst,src) +#define P_PSADBW(dst,src) p_psadbw(dst,src) +#define P_PMOVMSKB(dst,src) p_pmovmskb(dst,src) +#define P_PMASKMOVQ(dst,src) p_pmaskmovq(dst,src) +#define P_PINSRW(dst,src,msk) p_pinsrw(dst,src) +#define P_PEXTRW(dst,src,msk) p_pextrw(dst,src) +#define P_PSHUFW(dst,src,msk) p_pshufw(dst,src) +#define P_MOVNTQ(dst,src) p_movntq(dst,src) + +#define P_PFNACCM(dst,src,off) p_pfnaccm(dst,src,off) +#define P_FPPNACCM(dst,src,off) p_pfpnaccm(dst,src,off) +#define P_PSWAPDM(dst,src,off) p_pswapdm(dst,src,off) +#define P_PMINUBM(dst,src,off) p_pminubm(dst,src,off) +#define P_PMAXUBM(dst,src,off) p_pmaxubm(dst,src,off) +#define P_PMINSWM(dst,src,off) p_pminswm(dst,src,off) +#define P_PMAXSWM(dst,src,off) p_pmaxswm(dst,src,off) +#define P_PMULHUWM(dst,src,off) p_pmulhuwm(dst,src,off) +#define P_PAVGBM(dst,src,off) p_pavgbm(dst,src,off) +#define P_PAVGWM(dst,src,off) p_avgwm(dst,src,off) +#define P_PSADBWM(dst,src,off) p_psadbwm(dst,src,off) +#define P_PMOVMSKBM(dst,src,off) p_pmovmskbm(dst,src,off) +#define P_PMASKMOVQM(dst,src,off) p_pmaskmovqm(dst,src,off) +#define P_PINSRWM(dst,src,off,msk) p_pinsrwm(dst,src,off,msk) +#define P_PSHUFWM(dst,src,off,msk) p_pshufwm(dst,src,off,msk) +#define P_MOVNTQM(dst,src,off) p_movntqm(dst,src,off) + +#elif defined (_MSC_VER) && !defined (__MWERKS__) +// The Microsoft Visual C++ version of the 3DNow! macros. + +// Stop the "no EMMS" warning, since it doesn't detect FEMMS properly +#pragma warning(disable:4799) + +// Defines for operands. +#define _K3D_MM0 0xc0 +#define _K3D_MM1 0xc1 +#define _K3D_MM2 0xc2 +#define _K3D_MM3 0xc3 +#define _K3D_MM4 0xc4 +#define _K3D_MM5 0xc5 +#define _K3D_MM6 0xc6 +#define _K3D_MM7 0xc7 +#define _K3D_mm0 0xc0 +#define _K3D_mm1 0xc1 +#define _K3D_mm2 0xc2 +#define _K3D_mm3 0xc3 +#define _K3D_mm4 0xc4 +#define _K3D_mm5 0xc5 +#define _K3D_mm6 0xc6 +#define _K3D_mm7 0xc7 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 + +// These defines are for compatibility with the previous version of the header file. +#define _K3D_M0 0xc0 +#define _K3D_M1 0xc1 +#define _K3D_M2 0xc2 +#define _K3D_M3 0xc3 +#define _K3D_M4 0xc4 +#define _K3D_M5 0xc5 +#define _K3D_M6 0xc6 +#define _K3D_M7 0xc7 +#define _K3D_m0 0xc0 +#define _K3D_m1 0xc1 +#define _K3D_m2 0xc2 +#define _K3D_m3 0xc3 +#define _K3D_m4 0xc4 +#define _K3D_m5 0xc5 +#define _K3D_m6 0xc6 +#define _K3D_m7 0xc7 +#define _K3D__EAX 0x00 +#define _K3D__ECX 0x01 +#define _K3D__EDX 0x02 +#define _K3D__EBX 0x03 +#define _K3D__ESI 0x06 +#define _K3D__EDI 0x07 +#define _K3D__eax 0x00 +#define _K3D__ecx 0x01 +#define _K3D__edx 0x02 +#define _K3D__ebx 0x03 +#define _K3D__esi 0x06 +#define _K3D__edi 0x07 + +// General 3DNow! instruction format that is supported by +// these macros. Note that only the most basic form of memory +// operands are supported by these macros. + +#define InjK3DOps(dst,src,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0f \ + _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ + _asm _emit _3DNowOpcode##inst \ +} + +#define InjK3DMOps(dst,src,off,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0f \ + _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ + _asm _emit off \ + _asm _emit _3DNowOpcode##inst \ +} + +#define InjMMXOps(dst,src,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit _3DNowOpcode##inst \ + _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ +} + +#define InjMMXMOps(dst,src,off,inst) \ +{ \ + _asm _emit 0x0f \ + _asm _emit _3DNowOpcode##inst \ + _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ + _asm _emit off \ +} + +#define _3DNowOpcodePF2ID 0x1d +#define _3DNowOpcodePFACC 0xae +#define _3DNowOpcodePFADD 0x9e +#define _3DNowOpcodePFCMPEQ 0xb0 +#define _3DNowOpcodePFCMPGE 0x90 +#define _3DNowOpcodePFCMPGT 0xa0 +#define _3DNowOpcodePFMAX 0xa4 +#define _3DNowOpcodePFMIN 0x94 +#define _3DNowOpcodePFMUL 0xb4 +#define _3DNowOpcodePFRCP 0x96 +#define _3DNowOpcodePFRCPIT1 0xa6 +#define _3DNowOpcodePFRCPIT2 0xb6 +#define _3DNowOpcodePFRSQRT 0x97 +#define _3DNowOpcodePFRSQIT1 0xa7 +#define _3DNowOpcodePFSUB 0x9a +#define _3DNowOpcodePFSUBR 0xaa +#define _3DNowOpcodePI2FD 0x0d +#define _3DNowOpcodePAVGUSB 0xbf +#define _3DNowOpcodePMULHRW 0xb7 +#define _3DNowOpcodePFNACC 0x8a +#define _3DNowOpcodeFPPNACC 0x8e +#define _3DNowOpcodePSWAPD 0xbb +#define _3DNowOpcodePMINUB 0xda +#define _3DNowOpcodePMAXUB 0xde +#define _3DNowOpcodePMINSW 0xea +#define _3DNowOpcodePMAXSW 0xee +#define _3DNowOpcodePMULHUW 0xe4 +#define _3DNowOpcodePAVGB 0xe0 +#define _3DNowOpcodePAVGW 0xe3 +#define _3DNowOpcodePSADBW 0xf6 +#define _3DNowOpcodePMOVMSKB 0xd7 +#define _3DNowOpcodePMASKMOVQ 0xf7 +#define _3DNowOpcodePINSRW 0xc4 +#define _3DNowOpcodePEXTRW 0xc5 +#define _3DNowOpcodePSHUFW 0x70 +#define _3DNowOpcodeMOVNTQ 0xe7 +#define _3DNowOpcodePREFETCHT 0x18 + + +#define PF2ID(dst,src) InjK3DOps(dst, src, PF2ID) +#define PFACC(dst,src) InjK3DOps(dst, src, PFACC) +#define PFADD(dst,src) InjK3DOps(dst, src, PFADD) +#define PFCMPEQ(dst,src) InjK3DOps(dst, src, PFCMPEQ) +#define PFCMPGE(dst,src) InjK3DOps(dst, src, PFCMPGE) +#define PFCMPGT(dst,src) InjK3DOps(dst, src, PFCMPGT) +#define PFMAX(dst,src) InjK3DOps(dst, src, PFMAX) +#define PFMIN(dst,src) InjK3DOps(dst, src, PFMIN) +#define PFMUL(dst,src) InjK3DOps(dst, src, PFMUL) +#define PFRCP(dst,src) InjK3DOps(dst, src, PFRCP) +#define PFRCPIT1(dst,src) InjK3DOps(dst, src, PFRCPIT1) +#define PFRCPIT2(dst,src) InjK3DOps(dst, src, PFRCPIT2) +#define PFRSQRT(dst,src) InjK3DOps(dst, src, PFRSQRT) +#define PFRSQIT1(dst,src) InjK3DOps(dst, src, PFRSQIT1) +#define PFSUB(dst,src) InjK3DOps(dst, src, PFSUB) +#define PFSUBR(dst,src) InjK3DOps(dst, src, PFSUBR) +#define PI2FD(dst,src) InjK3DOps(dst, src, PI2FD) +#define PAVGUSB(dst,src) InjK3DOps(dst, src, PAVGUSB) +#define PMULHRW(dst,src) InjK3DOps(dst, src, PMULHRW) + +#define FEMMS \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0e \ +} + +#define PREFETCH(src) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (_K3D_##src & 0x07) \ +} + +/* Prefetch with a short offset, < 127 or > -127 + Carefull! Doesn't check for your offset being + in range. */ + +#define PREFETCHM(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x40 | (_K3D_##src & 0x07)) \ + _asm _emit off \ +} + +/* Prefetch with a long offset */ + +#define PREFETCHMLONG(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x80 | (_K3D_##src & 0x07)) \ + _asm _emit (off & 0x000000ff) \ + _asm _emit (off & 0x0000ff00) >> 8 \ + _asm _emit (off & 0x00ff0000) >> 16 \ + _asm _emit (off & 0xff000000) >> 24 \ +} + +#define PREFETCHW(src) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit (0x08 | (_K3D_##src & 0x07)) \ +} + +#define PREFETCHWM(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit 0x48 | (_K3D_##src & 0x07) \ + _asm _emit off \ +} + +#define PREFETCHWMLONG(src,off) \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0x0d \ + _asm _emit 0x88 | (_K3D_##src & 0x07) \ + _asm _emit (off & 0x000000ff) \ + _asm _emit (off & 0x0000ff00) >> 8 \ + _asm _emit (off & 0x00ff0000) >> 16 \ + _asm _emit (off & 0xff000000) >> 24 \ +} + +#define CPUID \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0xa2 \ +} + + +/* Defines for new, K7 opcodes */ +#define SFENCE \ +{ \ + _asm _emit 0x0f \ + _asm _emit 0xae \ + _asm _emit 0xf8 \ +} + +#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) +#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) +#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) +#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) +#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) +#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) +#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) +#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) +#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) +#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) +#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) +#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) +#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) +#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) _asm _emit msk +#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) _asm _emit msk +#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) _asm _emit msk +#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) +#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) +#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) +#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) +#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) + + +/* Memory/offset versions of the opcodes */ +#define PAVGUSBM(dst,src,off) InjK3DMOps(dst,src,off,PAVGUSB) +#define PF2IDM(dst,src,off) InjK3DMOps(dst,src,off,PF2ID) +#define PFACCM(dst,src,off) InjK3DMOps(dst,src,off,PFACC) +#define PFADDM(dst,src,off) InjK3DMOps(dst,src,off,PFADD) +#define PFCMPEQM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPEQ) +#define PFCMPGEM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGE) +#define PFCMPGTM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGT) +#define PFMAXM(dst,src,off) InjK3DMOps(dst,src,off,PFMAX) +#define PFMINM(dst,src,off) InjK3DMOps(dst,src,off,PFMIN) +#define PFMULM(dst,src,off) InjK3DMOps(dst,src,off,PFMUL) +#define PFRCPM(dst,src,off) InjK3DMOps(dst,src,off,PFRCP) +#define PFRCPIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT1) +#define PFRCPIT2M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT2) +#define PFRSQRTM(dst,src,off) InjK3DMOps(dst,src,off,PFRSQRT) +#define PFRSQIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRSQIT1) +#define PFSUBM(dst,src,off) InjK3DMOps(dst,src,off,PFSUB) +#define PFSUBRM(dst,src,off) InjK3DMOps(dst,src,off,PFSUBR) +#define PI2FDM(dst,src,off) InjK3DMOps(dst,src,off,PI2FD) +#define PMULHRWM(dst,src,off) InjK3DMOps(dst,src,off,PMULHRW) + + +/* Memory/offset versions of the K7 opcodes */ +#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) +#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) +#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) +#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) +#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) +#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) +#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) +#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) +#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) +#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) +#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) +#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) +#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) +#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW) _asm _emit msk +#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW) _asm _emit msk +#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) +#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) +#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) +#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) +#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) + + +#else + +/* Assume built-in support for 3DNow! opcodes, replace macros with opcodes */ +#define PAVGUSB(dst,src) pavgusb dst,src +#define PF2ID(dst,src) pf2id dst,src +#define PFACC(dst,src) pfacc dst,src +#define PFADD(dst,src) pfadd dst,src +#define PFCMPEQ(dst,src) pfcmpeq dst,src +#define PFCMPGE(dst,src) pfcmpge dst,src +#define PFCMPGT(dst,src) pfcmpgt dst,src +#define PFMAX(dst,src) pfmax dst,src +#define PFMIN(dst,src) pfmin dst,src +#define PFMUL(dst,src) pfmul dst,src +#define PFRCP(dst,src) pfrcp dst,src +#define PFRCPIT1(dst,src) pfrcpit1 dst,src +#define PFRCPIT2(dst,src) pfrcpit2 dst,src +#define PFRSQRT(dst,src) pfrsqrt dst,src +#define PFRSQIT1(dst,src) pfrsqit1 dst,src +#define PFSUB(dst,src) pfsub dst,src +#define PFSUBR(dst,src) pfsubr dst,src +#define PI2FD(dst,src) pi2fd dst,src +#define PMULHRW(dst,src) pmulhrw dst,src +#define PREFETCH(src) prefetch src +#define PREFETCHW(src) prefetchw src + +#define PAVGUSBM(dst,src,off) pavgusb dst,[src+off] +#define PF2IDM(dst,src,off) PF2ID dst,[src+off] +#define PFACCM(dst,src,off) PFACC dst,[src+off] +#define PFADDM(dst,src,off) PFADD dst,[src+off] +#define PFCMPEQM(dst,src,off) PFCMPEQ dst,[src+off] +#define PFCMPGEM(dst,src,off) PFCMPGE dst,[src+off] +#define PFCMPGTM(dst,src,off) PFCMPGT dst,[src+off] +#define PFMAXM(dst,src,off) PFMAX dst,[src+off] +#define PFMINM(dst,src,off) PFMIN dst,[src+off] +#define PFMULM(dst,src,off) PFMUL dst,[src+off] +#define PFRCPM(dst,src,off) PFRCP dst,[src+off] +#define PFRCPIT1M(dst,src,off) PFRCPIT1 dst,[src+off] +#define PFRCPIT2M(dst,src,off) PFRCPIT2 dst,[src+off] +#define PFRSQRTM(dst,src,off) PFRSQRT dst,[src+off] +#define PFRSQIT1M(dst,src,off) PFRSQIT1 dst,[src+off] +#define PFSUBM(dst,src,off) PFSUB dst,[src+off] +#define PFSUBRM(dst,src,off) PFSUBR dst,[src+off] +#define PI2FDM(dst,src,off) PI2FD dst,[src+off] +#define PMULHRWM(dst,src,off) PMULHRW dst,[src+off] + + +#if defined (__MWERKS__) +// At the moment, CodeWarrior does not support these opcodes, so hand-assemble them + +// Defines for operands. +#define _K3D_MM0 0xc0 +#define _K3D_MM1 0xc1 +#define _K3D_MM2 0xc2 +#define _K3D_MM3 0xc3 +#define _K3D_MM4 0xc4 +#define _K3D_MM5 0xc5 +#define _K3D_MM6 0xc6 +#define _K3D_MM7 0xc7 +#define _K3D_mm0 0xc0 +#define _K3D_mm1 0xc1 +#define _K3D_mm2 0xc2 +#define _K3D_mm3 0xc3 +#define _K3D_mm4 0xc4 +#define _K3D_mm5 0xc5 +#define _K3D_mm6 0xc6 +#define _K3D_mm7 0xc7 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 +#define _K3D_EAX 0x00 +#define _K3D_ECX 0x01 +#define _K3D_EDX 0x02 +#define _K3D_EBX 0x03 +#define _K3D_ESI 0x06 +#define _K3D_EDI 0x07 +#define _K3D_eax 0x00 +#define _K3D_ecx 0x01 +#define _K3D_edx 0x02 +#define _K3D_ebx 0x03 +#define _K3D_esi 0x06 +#define _K3D_edi 0x07 + +#define InjK3DOps(dst,src,inst) \ + db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src), _3DNowOpcode##inst + +#define InjK3DMOps(dst,src,off,inst) \ + db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off, _3DNowOpcode##inst + +#define InjMMXOps(dst,src,inst) \ + db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src) + +#define InjMMXMOps(dst,src,off,inst) \ + db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off + +#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) +#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) +#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) +#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) +#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) +#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) +#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) +#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) +#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) +#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) +#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) +#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) +#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) +#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) db msk +#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) db msk +#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) db msk +#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) +#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) +#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) +#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) +#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) + + +/* Memory/offset versions of the K7 opcodes */ +#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) +#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) +#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) +#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) +#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) +#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) +#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) +#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) +#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) +#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) +#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) +#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) +#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) +#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW), msk +#define PEXTRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PEXTRW), msk +#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW), msk +#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) +#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) +#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) +#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) +#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) + + +#else + +#define PFNACC(dst,src) PFNACC dst,src +#define PFPNACC(dst,src) PFPNACC dst,src +#define PSWAPD(dst,src) PSWAPD dst,src +#define PMINUB(dst,src) PMINUB dst,src +#define PMAXUB(dst,src) PMAXUB dst,src +#define PMINSW(dst,src) PMINSW dst,src +#define PMAXSW(dst,src) PMAXSW dst,src +#define PMULHUW(dst,src) PMULHUW dst,src +#define PAVGB(dst,src) PAVGB dst,src +#define PAVGW(dst,src) PAVGW dst,src +#define PSADBW(dst,src) PSADBW dst,src +#define PMOVMSKB(dst,src) PMOVMSKB dst,src +#define PMASKMOVQ(dst,src) PMASKMOVQ dst,src +#define PINSRW(dst,src,msk) PINSRW dst,src,msk +#define PEXTRW(dst,src,msk) PEXTRW dst,src,msk +#define PSHUFW(dst,src,msk) PSHUFW dst,src,msk +#define MOVNTQ(dst,src) MOVNTQ dst,src + +#define PFNACCM(dst,src,off) PFNACC dst,[src+off] +#define PFPNACCM(dst,src,off) PFPNACC dst,[src+off] +#define PSWAPDM(dst,src,off) PSWAPD dst,[src+off] +#define PMINUBM(dst,src,off) PMINUB dst,[src+off] +#define PMAXUBM(dst,src,off) PMAXUB dst,[src+off] +#define PMINSWM(dst,src,off) PMINSW dst,[src+off] +#define PMAXSWM(dst,src,off) PMAXSW dst,[src+off] +#define PMULHUWM(dst,src,off) PMULHUW dst,[src+off] +#define PAVGBM(dst,src,off) PAVGB dst,[src+off] +#define PAVGWM(dst,src,off) PAVGW dst,[src+off] +#define PSADBWM(dst,src,off) PSADBW dst,[src+off] +#define PMOVMSKBM(dst,src,off) PMOVMSKB dst,[src+off] +#define PMASKMOVQM(dst,src,off) PMASKMOVQ dst,[src+off] +#define PINSRWM(dst,src,off,msk) PINSRW dst,[src+off],msk +#define PEXTRWM(dst,src,off,msk) PEXTRW dst,[src+off],msk +#define PSHUFWM(dst,src,off,msk) PSHUFW dst,[src+off],msk +#define MOVNTQM(dst,src,off) MOVNTQ dst,[src+off] + +#endif + +#endif + +/* Just to deal with lower case. */ +#define pf2id(dst,src) PF2ID(dst,src) +#define pfacc(dst,src) PFACC(dst,src) +#define pfadd(dst,src) PFADD(dst,src) +#define pfcmpeq(dst,src) PFCMPEQ(dst,src) +#define pfcmpge(dst,src) PFCMPGE(dst,src) +#define pfcmpgt(dst,src) PFCMPGT(dst,src) +#define pfmax(dst,src) PFMAX(dst,src) +#define pfmin(dst,src) PFMIN(dst,src) +#define pfmul(dst,src) PFMUL(dst,src) +#define pfrcp(dst,src) PFRCP(dst,src) +#define pfrcpit1(dst,src) PFRCPIT1(dst,src) +#define pfrcpit2(dst,src) PFRCPIT2(dst,src) +#define pfrsqrt(dst,src) PFRSQRT(dst,src) +#define pfrsqit1(dst,src) PFRSQIT1(dst,src) +#define pfsub(dst,src) PFSUB(dst,src) +#define pfsubr(dst,src) PFSUBR(dst,src) +#define pi2fd(dst,src) PI2FD(dst,src) +#define femms FEMMS +#define pavgusb(dst,src) PAVGUSB(dst,src) +#define pmulhrw(dst,src) PMULHRW(dst,src) +#define prefetch(src) PREFETCH(src) +#define prefetchw(src) PREFETCHW(src) + +#define prefetchm(src,off) PREFETCHM(src,off) +#define prefetchmlong(src,off) PREFETCHMLONG(src,off) +#define prefetchwm(src,off) PREFETCHWM(src,off) +#define prefetchwmlong(src,off) PREFETCHWMLONG(src,off) + +#define pfnacc(dst,src) PFNACC(dst,src) +#define pfpnacc(dst,src) PFPNACC(dst,src) +#define pswapd(dst,src) PSWAPD(dst,src) +#define pminub(dst,src) PMINUB(dst,src) +#define pmaxub(dst,src) PMAXUB(dst,src) +#define pminsw(dst,src) PMINSW(dst,src) +#define pmaxsw(dst,src) PMAXSW(dst,src) +#define pmulhuw(dst,src) PMULHUW(dst,src) +#define pavgb(dst,src) PAVGB(dst,src) +#define pavgw(dst,src) PAVGW(dst,src) +#define psadbw(dst,src) PSADBW(dst,src) +#define pmovmskb(dst,src) PMOVMSKB(dst,src) +#define pmaskmovq(dst,src) PMASKMOVQ(dst,src) +#define pinsrw(dst,src,msk) PINSRW(dst,src,msk) +#define pextrw(dst,src,msk) PEXTRW(dst,src,msk) +#define pshufw(dst,src,msk) PSHUFW(dst,src,msk) +#define movntq(dst,src) MOVNTQ(dst,src) +#define prefetchnta(mem) PREFETCHNTA(mem) +#define prefetcht0(mem) PREFETCHT0(mem) +#define prefetcht1(mem) PREFETCHT1(mem) +#define prefetcht2(mem) PREFETCHT2(mem) + + +#define pavgusbm(dst,src,off) PAVGUSBM(dst,src,off) +#define pf2idm(dst,src,off) PF2IDM(dst,src,off) +#define pfaccm(dst,src,off) PFACCM(dst,src,off) +#define pfaddm(dst,src,off) PFADDM(dst,src,off) +#define pfcmpeqm(dst,src,off) PFCMPEQM(dst,src,off) +#define pfcmpgem(dst,src,off) PFCMPGEM(dst,src,off) +#define pfcmpgtm(dst,src,off) PFCMPGTM(dst,src,off) +#define pfmaxm(dst,src,off) PFMAXM(dst,src,off) +#define pfminm(dst,src,off) PFMINM(dst,src,off) +#define pfmulm(dst,src,off) PFMULM(dst,src,off) +#define pfrcpm(dst,src,off) PFRCPM(dst,src,off) +#define pfrcpit1m(dst,src,off) PFRCPIT1M(dst,src,off) +#define pfrcpit2m(dst,src,off) PFRCPIT2M(dst,src,off) +#define pfrsqrtm(dst,src,off) PFRSQRTM(dst,src,off) +#define pfrsqit1m(dst,src,off) PFRSQIT1M(dst,src,off) +#define pfsubm(dst,src,off) PFSUBM(dst,src,off) +#define pfsubrm(dst,src,off) PFSUBRM(dst,src,off) +#define pi2fdm(dst,src,off) PI2FDM(dst,src,off) +#define pmulhrwm(dst,src,off) PMULHRWM(dst,src,off) +#define cpuid CPUID +#define sfence SFENCE + +#define pfnaccm(dst,src,off) PFNACCM(dst,src,off) +#define pfpnaccm(dst,src,off) PFPNACCM(dst,src,off) +#define pswapdm(dst,src,off) PSWAPDM(dst,src,off) +#define pminubm(dst,src,off) PMINUBM(dst,src,off) +#define pmaxubm(dst,src,off) PMAXUBM(dst,src,off) +#define pminswm(dst,src,off) PMINSWM(dst,src,off) +#define pmaxswm(dst,src,off) PMAXSWM(dst,src,off) +#define pmulhuwm(dst,src,off) PMULHUWM(dst,src,off) +#define pavgbm(dst,src,off) PAVGBM(dst,src,off) +#define pavgwm(dst,src,off) PAVGWM(dst,src,off) +#define psadbwm(dst,src,off) PSADBWM(dst,src,off) +#define pmovmskbm(dst,src,off) PMOVMSKBM(dst,src,off) +#define pmaskmovqm(dst,src,off) PMASKMOVQM(dst,src,off) +#define pinsrwm(dst,src,off,msk) PINSRWM(dst,src,off,msk) +#define pextrwm(dst,src,off,msk) PEXTRWM(dst,src,off,msk) +#define pshufwm(dst,src,off,msk) PSHUFWM(dst,src,off,msk) +#define movntqm(dst,src,off) MOVNTQM(dst,src,off) +#define prefetchntam(mem,off) PREFETCHNTA(mem,off) +#define prefetcht0m(mem,off) PREFETCHT0(mem,off) +#define prefetcht1m(mem,off) PREFETCHT1(mem,off) +#define prefetcht2m(mem,off) PREFETCHT2(mem,off) + +#endif diff --git a/MacGLide/OpenGLide/grLfb.cpp b/MacGLide/OpenGLide/grLfb.cpp new file mode 100644 index 0000000..16b2f8f --- /dev/null +++ b/MacGLide/OpenGLide/grLfb.cpp @@ -0,0 +1,59 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* pre-glide22 buffer access interface +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "grLfb.h" + +// These are the functions for the obsolete linear frame buffer interface (pre 2.2) +FX_ENTRY void grLfbBegin(void) +{ + // Todo: implment linear framebuffer interface + assert(false); +} + +FX_ENTRY void grLfbBypassMode(GrLfbBypassMode_t mode) +{ + // Todo: implment linear framebuffer interface + assert(false); +} + +FX_ENTRY void GrLfbEnd() +{ + // Todo: implment linear framebuffer interface + assert(false); +} + +FX_ENTRY const FxU32* grLfbGetReadPtr(GrBuffer_t buffer) +{ + // Todo: implment linear framebuffer interface + assert(false); + return NULL; +} + +FX_ENTRY void* grLfbGetWritePtr(GrBuffer_t buffer) +{ + // Todo: implment linear framebuffer interface + assert(false); + return NULL; +} + +FX_ENTRY void* grLfbOrigin(GrOriginLocation_t origin) +{ + // Todo: implment linear framebuffer interface + assert(false); + return NULL; +} + +FX_ENTRY void grLfbWriteMode(GrLfbWriteMode_t mode) +{ + // Todo: implment linear framebuffer interface + assert(false); +} diff --git a/MacGLide/OpenGLide/grLfb.h b/MacGLide/OpenGLide/grLfb.h new file mode 100644 index 0000000..b256bf8 --- /dev/null +++ b/MacGLide/OpenGLide/grLfb.h @@ -0,0 +1,35 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* pre-glide24 sst1 functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "sdk2_3dfx.h" +#include "sdk2_glide.h" + +// prototypes for obsolete sst1-board functions + +#ifdef __cplusplus +extern "C" { +#endif + +// These are the functions for the obsolete linear frame buffer interface (pre 2.2) +FX_ENTRY void grLfbBegin(void); +FX_ENTRY void grLfbBypassMode(GrLfbBypassMode_t mode); +FX_ENTRY void GrLfbEnd(); +FX_ENTRY const FxU32* grLfbGetReadPtr(GrBuffer_t buffer); +FX_ENTRY void* grLfbGetWritePtr(GrBuffer_t buffer); +FX_ENTRY void* grLfbOrigin(GrOriginLocation_t origin); +FX_ENTRY void grLfbWriteMode(GrLfbWriteMode_t mode); + +#ifdef __cplusplus +} +#endif diff --git a/MacGLide/OpenGLide/grgu3df.cpp b/MacGLide/OpenGLide/grgu3df.cpp new file mode 100644 index 0000000..0cc0dfd --- /dev/null +++ b/MacGLide/OpenGLide/grgu3df.cpp @@ -0,0 +1,356 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* 3DF functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "OGLTables.h" + +//************************************************* +FxU32 GetTexSize( const int Lod, const int aspectRatio, const int format ) +{ + /* + ** If the format is one of these: + ** GR_TEXFMT_RGB_332 + ** GR_TEXFMT_YIQ_422 + ** GR_TEXFMT_ALPHA_8 + ** GR_TEXFMT_INTENSITY_8 + ** GR_TEXFMT_ALPHA_INTENSITY_44 + ** GR_TEXFMT_P_8 + ** Reduces the size by 2 + */ + return nSquareLod[ format > GR_TEXFMT_RSVD1 ][ aspectRatio ][ Lod ]; +} + +// prototypes +int Read3dfHeader( const char *filename, Gu3dfInfo *data ); + +//************************************************* +FX_ENTRY FxBool FX_CALL +gu3dfGetInfo( const char *filename, Gu3dfInfo *info ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "gu3dfGetInfo( %s, --- )\n", filename ); +#endif + + if ( Read3dfHeader( filename, info ) ) + { +#ifdef OGL_DEBUG + GlideMsg( "==========================================\n" ); + GlideMsg( "3df file Header: %s\n", filename ); + GlideMsg( "Texture Format = %d\n", info->header.format ); + GlideMsg( "Aspect = %d\n", info->header.aspect_ratio ); + GlideMsg( "LargeLod = %d\nSmall Lod = %d\n", info->header.large_lod, info->header.small_lod ); + GlideMsg( "Width = %d Height = %d\n", info->header.width, info->header.height ); + GlideMsg( "MemRequired = %d\n", info->mem_required ); + GlideMsg( "==========================================\n" ); +#endif + return FXTRUE; + } + else + { + return FXFALSE; + } +} + + +static FxU32 ReadDataLong( FILE *fp ) +{ + FxU32 data; + FxU8 byte[4]; + + fread( byte, 4, 1, fp ); + data = (((FxU32) byte[ 0 ]) << 24) | + (((FxU32) byte[ 1 ]) << 16) | + (((FxU32) byte[ 2 ]) << 8) | + ((FxU32) byte[ 3 ]); + + return data; +} + +static FxU32 ReadDataShort( FILE *fp ) +{ + FxU32 data; + FxU8 byte[2]; + + fread( byte, 2, 1, fp ); + data = (((FxU32) byte[ 0 ]) << 8) | + ((FxU32) byte[ 1 ]); + + return data; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +gu3dfLoad( const char *filename, Gu3dfInfo *data ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "gu3dfLoad( %s, --- )\n", filename ); +#endif + + FILE * file3df; + int jump = Read3dfHeader( filename, data ); + +#ifdef OGL_DEBUG + GlideMsg( "Start of Data (Offset) = %d\n", jump ); + GlideMsg( "Total Bytes to be Read = %d\n", data->mem_required ); +#endif + + file3df = fopen( filename, "rb" ); + + fseek( file3df, jump, SEEK_SET ); + + if ( ( data->header.format == GR_TEXFMT_P_8 ) || + ( data->header.format == GR_TEXFMT_AP_88 ) ) + { + for( int i = 0; i < 256; i++ ) + { + data->table.palette.data[i] = ReadDataLong( file3df ); + } +#ifdef OGL_DEBUG + GlideMsg( "Reading Palette\n" ); +#endif + } + + if ( ( data->header.format == GR_TEXFMT_YIQ_422 ) || + ( data->header.format == GR_TEXFMT_AYIQ_8422 ) ) + { + int i; + int pi; + FxU32 pack; + + GuNccTable *ncc = &(data->table.nccTable); + + for ( i = 0; i < 16; i++ ) + { + ncc->yRGB[i] = (FxU8) ReadDataShort( file3df ); + } + + for ( i = 0; i < 4; i++ ) + { + /* Masking with 0x1ff is strange but correct apparently */ + ncc->iRGB[i][0] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + ncc->iRGB[i][1] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + ncc->iRGB[i][2] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + } + + for ( i = 0; i < 4; i++ ) + { + ncc->qRGB[i][0] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + ncc->qRGB[i][1] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + ncc->qRGB[i][2] = (FxI16) ( ReadDataShort( file3df ) & 0x1ff ); + } + + pi = 0; + + for ( i = 0; i < 4; i++ ) + { + pack = ( ncc->yRGB[i*4 + 0] ); + pack |= ( ncc->yRGB[i*4 + 1] << 8 ); + pack |= ( ncc->yRGB[i*4 + 2] << 16 ); + pack |= ( ncc->yRGB[i*4 + 3] << 24 ); + + ncc->packed_data[pi++] = pack; + } + + for ( i = 0; i < 4; i++ ) + { + pack = ( ncc->iRGB[i][0] << 18 ); + pack |= ( ncc->iRGB[i][1] << 9 ); + pack |= ( ncc->iRGB[i][2] ); + + ncc->packed_data[pi++] = pack; + } + + for ( i = 0; i < 4; i++ ) + { + pack = ( ncc->qRGB[i][0] << 18 ); + pack |= ( ncc->qRGB[i][1] << 9 ); + pack |= ( ncc->qRGB[i][2] ); + + ncc->packed_data[pi++] = pack; + } + } + + switch ( data->header.format ) + { + case GR_TEXFMT_RGB_565: + case GR_TEXFMT_ARGB_8332: + case GR_TEXFMT_ARGB_1555: + case GR_TEXFMT_AYIQ_8422: + case GR_TEXFMT_ARGB_4444: + case GR_TEXFMT_ALPHA_INTENSITY_88: + case GR_TEXFMT_AP_88: + { + FxU16 *d = (FxU16 *) (data->data); + int i; + + for ( i = data->mem_required; i > 0; i -= 2 ) + { + *d++ = (FxU16) ReadDataShort( file3df ); + } + } + break; + + default: + fread( data->data, sizeof( FxU8 ), data->mem_required, file3df ); + break; + } + + fclose( file3df ); + + return FXTRUE; +} + +GrTextureFormat_t ParseTextureFormat( const char * text ) +{ + if ( !strcmp( text, "argb1555\n" ) ) + { + return GR_TEXFMT_ARGB_1555; + } + if ( !strcmp( text, "argb4444\n" ) ) + { + return GR_TEXFMT_ARGB_4444; + } + if ( !strcmp( text, "rgb565\n" ) ) + { + return GR_TEXFMT_RGB_565; + } + if ( !strcmp( text, "rgb332\n" ) ) + { + return GR_TEXFMT_RGB_332; + } + if ( !strcmp( text, "argb8332\n" ) ) + { + return GR_TEXFMT_ARGB_8332; + } + if ( !strcmp( text, "p8\n" ) ) + { + return GR_TEXFMT_P_8; + } + if ( !strcmp( text, "ap88\n" ) ) + { + return GR_TEXFMT_AP_88; + } + if ( !strcmp( text, "ai44\n" ) ) + { + return GR_TEXFMT_ALPHA_INTENSITY_44; + } + if ( !strcmp( text, "yiq\n" ) ) + { + return GR_TEXFMT_YIQ_422; + } + if ( !strcmp( text, "ayiq8422\n" ) ) + { + return GR_TEXFMT_AYIQ_8422; + } + + return 0; +} + +int ParseLod( int Lod ) +{ + switch( Lod ) + { + case 256: return GR_LOD_256; + case 128: return GR_LOD_128; + case 64: return GR_LOD_64; + case 32: return GR_LOD_32; + case 16: return GR_LOD_16; + case 8: return GR_LOD_8; + case 4: return GR_LOD_4; + case 2: return GR_LOD_2; + case 1: return GR_LOD_1; + } + + return -1; +} + +GrAspectRatio_t ParseAspect( int h, int v ) +{ + switch ( h ) + { + case 8: return GR_ASPECT_8x1; + case 4: return GR_ASPECT_4x1; + case 2: return GR_ASPECT_2x1; + case 1: + switch ( v ) + { + case 8: return GR_ASPECT_1x8; + case 4: return GR_ASPECT_1x4; + case 2: return GR_ASPECT_1x2; + case 1: return GR_ASPECT_1x1; + } + } + + return 0; +} + +int Read3dfHeader( const char *filename, Gu3dfInfo *data ) +{ + FILE * file3df; + char buffer[255]; + int temp1, + temp2, + lod1, + lod2, + nWidth, + nHeight; + + file3df = fopen( filename, "rb" ); + + if ( file3df == NULL ) + { + return 0; + } + + fgets( buffer, 255, file3df ); + fgets( buffer, 255, file3df ); + + data->header.format = ParseTextureFormat( buffer ); + + fgets( buffer, 255, file3df ); + sscanf( buffer, "lod range: %d %d\n", &lod1, &lod2 ); + + data->header.small_lod = ParseLod( lod1 ); + data->header.large_lod = ParseLod( lod2 ); + + fgets( buffer, 255, file3df ); + sscanf( buffer, "aspect ratio: %d %d\n", &temp1, &temp2 ); + + data->header.aspect_ratio = ParseAspect( temp1, temp2 ); + + switch ( data->header.aspect_ratio ) + { + case GR_ASPECT_8x1: nWidth = lod2; nHeight = lod2 >> 3; break; + case GR_ASPECT_4x1: nWidth = lod2; nHeight = lod2 >> 2; break; + case GR_ASPECT_2x1: nWidth = lod2; nHeight = lod2 >> 1; break; + case GR_ASPECT_1x1: nWidth = lod2; nHeight = lod2; break; + case GR_ASPECT_1x2: nWidth = lod2 >> 1; nHeight = lod2; break; + case GR_ASPECT_1x4: nWidth = lod2 >> 2; nHeight = lod2; break; + case GR_ASPECT_1x8: nWidth = lod2 >> 3; nHeight = lod2; break; + } + + data->header.width = nWidth; + data->header.height = nHeight; + + { + GrLOD_t l; + + data->mem_required = 0; + + for ( l = data->header.large_lod; l <= data->header.small_lod; l++ ) + data->mem_required += GetTexSize( l, data->header.aspect_ratio, data->header.format ); + } + + temp1 = ftell( file3df ); + fclose( file3df ); + + return temp1; +} diff --git a/MacGLide/OpenGLide/grguBuffer.cpp b/MacGLide/OpenGLide/grguBuffer.cpp new file mode 100644 index 0000000..35aaccd --- /dev/null +++ b/MacGLide/OpenGLide/grguBuffer.cpp @@ -0,0 +1,270 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Buffer functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "FormatConversion.h" +#include "Framebuffer.h" +#include "Glide.h" +#include "GLRender.h" +#include "GLRenderUpdateState.h" +#include "GLUtil.h" + + +//************************************************* +//* Clear buffer +//************************************************* +FX_ENTRY void FX_CALL +grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU16 depth ) +{ +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "grBufferClear( %d, %d, %d )\n", color, alpha, depth ); +#endif + glReportErrors("grBufferClear"); + + RenderDrawTriangles( ); + s_Framebuffer.OnBeforeBufferClear(); + + unsigned int Bits = 0; + if ( Glide.State.ColorMask ) + { + Bits = GL_COLOR_BUFFER_BIT; + float r, g, b, a; + ConvertColorF(color, r, g, b, a); + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + Bits |= GL_STENCIL_BUFFER_BIT; + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Debug) + { + // By making the background green, + // holes in the geometry are easy to spot + g = 1.0f; + } + } + glClearColor(r, g, b, a); + glReportError(); + } + + if ( Glide.State.DepthBufferWritting) + { + glClearDepth( depth * D1OVER65535 ); + glReportError(); + Bits |= GL_DEPTH_BUFFER_BIT; + } + + if ( ! OpenGL.Clipping ) + { + glClear( Bits ); + glReportError(); + } + else + { + glEnable( GL_SCISSOR_TEST ); + glClear( Bits ); + glReportError(); + glDisable( GL_SCISSOR_TEST ); + } + glReportError(); +} + +//************************************************* +//* Swaps front and back Buffer +//************************************************* +FX_ENTRY void FX_CALL +grBufferSwap( int swap_interval ) +{ +#if defined( OGL_DONE ) || defined( OGL_COMBINE ) + GlideMsg( "grBufferSwap( %d )\n", swap_interval ); +#endif + glReportErrors("grBufferSwap"); + + RenderDrawTriangles( ); + +#ifdef OGL_DEBUG + static float Temp = 1.0f; + if ( OGLRender.FrameTriangles > OGLRender.MaxTriangles ) + { + OGLRender.MaxTriangles = OGLRender.FrameTriangles; + } + OGLRender.FrameTriangles = 0; +#endif + + // Flush the framebuffer + s_Framebuffer.OnBeforeBufferSwap(); + + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + // Disable the cull mode + glDisable(GL_CULL_FACE); + // Disable clip volume hint manually to avoid recursion + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); + } + // Blend + glDisable(GL_BLEND); + SetBlendState(); + // Alpha + glDisable(GL_ALPHA_TEST); + SetChromaKeyAndAlphaState(); + // disable depth buffer + glDepthMask(false); + // Enable colormask + glColorMask(true, true, true, false); + // Needed for displaying in-game menus + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glDisable(GL_DEPTH_TEST); + } + if (InternalConfig.EXT_secondary_color) + { + glDisable(GL_COLOR_SUM_EXT); + } + if (OpenGL.Fog) + { + glActiveTextureARB(GL_TEXTURE2_ARB); + glDisable(GL_TEXTURE_2D); + SetFogModeState(); + } + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glDisable(GL_TEXTURE_2D); + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = false; + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; + } + SetTextureState(); + SetColorCombineState(); + SetAlphaCombineState(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); + + glStencilFunc(GL_NOTEQUAL, 0x02, 0x03); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glReportError(); + GLfloat clearcolor[] = + { + 0.0f, 0.0f, 0.0f, 0.0f + }; + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) + { + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Debug) + { + // By making the gaps red, they're easily to spot + clearcolor[0] = 1.0f; + } + } + GLfloat depth = 1.0f; + glBegin(GL_QUADS); + glColor4fv(clearcolor); + glVertex3f(Glide.State.ClipMinX, Glide.State.ClipMinY, depth); + glColor4fv(clearcolor); + glVertex3f(Glide.State.ClipMaxX, Glide.State.ClipMinY, depth); + glColor4fv(clearcolor); + glVertex3f(Glide.State.ClipMaxX, Glide.State.ClipMaxY, depth); + glColor4fv(clearcolor); + glVertex3f(Glide.State.ClipMinX, Glide.State.ClipMaxY, depth); + glEnd(); + glStencilFunc(GL_ALWAYS, 0x02, 0x03); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + // Restore state + switch (Glide.State.CullMode) + { + case GR_CULL_DISABLE: + break; + case GR_CULL_NEGATIVE: + case GR_CULL_POSITIVE: + glEnable(GL_CULL_FACE); + break; + } + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); + } + // restore previous state + if (OpenGL.DepthBufferWritting) + { + glDepthMask(true); + } + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glEnable(GL_DEPTH_TEST); + } + // Restore colormask + bool rgb = Glide.State.ColorMask; + glColorMask(rgb, rgb, rgb, Glide.State.AlphaMask); + if (InternalConfig.EXT_secondary_color) + { + glEnable( GL_COLOR_SUM_EXT ); + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); + } + + // @todo: setting the swap interval doesn't seem to work + // - the 3dfx splash animation appears a bit to fast + // and using higher values doesn't work + // -> might be a bug in Classic + GLint swap = swap_interval; + aglSetInteger(pWindowInfo->aglContext, AGL_SWAP_INTERVAL, &swap); + aglReportError(); +#if defined (OGL_DONE) || defined (OGL_PARTDONE) || defined (OGL_NOTDONE) || defined(OGL_OPTIMISE_DEBUG) + GlideMsg("Calling aglSwapBuffers() with swapinterval %d\n", swap); +#endif + // swap buffers + aglSwapBuffers(pWindowInfo->aglContext); + s_Framebuffer.OnAfterBufferSwap(); + +#ifdef OGL_DEBUG +// RDTSC( FinalTick ); +// Temp = (float)(FinalTick - InitialTick); +// FpsAux += Temp; +// Frame++; +// RDTSC( InitialTick ); +#endif +} + +//************************************************* +//* Return the number of queued buffer swap requests +//* Always 0, never pending +//************************************************* +FX_ENTRY int FX_CALL +grBufferNumPending( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grBufferNumPending( ) = 0\n" ); +#endif + + RenderDrawTriangles(); + // s_Framebuffer.OnBufferNumPending(); + return 0; +} + +//************************************************* +//* Defines the Buffer to Render +//************************************************* +FX_ENTRY void FX_CALL +grRenderBuffer( GrBuffer_t dwBuffer ) +{ +#ifdef OGL_DONE + GlideMsg( "grRenderBuffer( %d )\n", dwBuffer ); +#endif + glReportErrors("grRenderBuffer"); + + RenderDrawTriangles( ); + Glide.State.RenderBuffer = dwBuffer; + // Valid parameters are only FRONT and BACK ( 0x0 and 0x1 ) + OpenGL.RenderBuffer = GL_FRONT + dwBuffer; + glDrawBuffer( OpenGL.RenderBuffer ); + glReportError(); +} + diff --git a/MacGLide/OpenGLide/grguColorAlpha.cpp b/MacGLide/OpenGLide/grguColorAlpha.cpp new file mode 100644 index 0000000..b8a5b47 --- /dev/null +++ b/MacGLide/OpenGLide/grguColorAlpha.cpp @@ -0,0 +1,668 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Color and Alpha File +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideDisplay.h" +#include "GLColorAlphaCombineEnvTables.h" +#include "GLExtensions.h" +#include "GLRender.h" +#include "GLUtil.h" +#include "GLRenderUpdateState.h" +#include "OGLTables.h" +#include "PGTexture.h" + +//************************************************* +//* Sets the Dithering Mode 24->16 bits +//************************************************* +FX_ENTRY void FX_CALL +grDitherMode( GrDitherMode_t mode ) +{ + CHECK_STATE_CHANGED(Glide.State.DitherMode == mode); + +#ifdef OGL_DONE + GlideMsg( "grDitherMode( %d )\n", mode ); +#endif + glReportErrors("grDitherMode"); + + RenderDrawTriangles( ); + Glide.State.DitherMode = mode; + if ( mode != GR_DITHER_DISABLE ) + { + // GR_DITHER_2x2 or GR_DITHER_4x4 + glEnable( GL_DITHER ); + } + else + { + glDisable( GL_DITHER ); + } + glReportError(); +} + +//************************************************* +//* Sets the Constant color +//************************************************* +FX_ENTRY void FX_CALL +grConstantColorValue( GrColor_t value ) +{ + CHECK_STATE_CHANGED(Glide.State.ConstantColorValue == value); + +#ifdef OGL_DONE + GlideMsg( "grConstantColorValue( 0x%X )\n", value ); +#endif + + RenderDrawTriangles(); + + Glide.State.ConstantColorValue = value; + ConvertColorF(value, + OpenGL.ConstantColor[ 0 ], + OpenGL.ConstantColor[ 1 ], + OpenGL.ConstantColor[ 2 ], + OpenGL.ConstantColor[ 3 ]); + + SetConstantColorValueState(); +} + +//************************************************* +//* Sets the Constant color - obsolete in 2.4 +//************************************************* +FX_ENTRY void FX_CALL +grConstantColorValue4( float a, float r, float g, float b ) +{ + CHECK_STATE_CHANGED(r == Glide.State.Delta0ModeColor[0] && + g == Glide.State.Delta0ModeColor[1] && + b == Glide.State.Delta0ModeColor[2] && + a == Glide.State.Delta0ModeColor[3]); + +#ifdef OGL_DONE + GlideMsg( "grConstantColorValue4( %f, %f, %f, %f )\n", a, r, g, b ); +#endif + + RenderDrawTriangles(); + + Glide.State.Delta0ModeColor[0] = r; + Glide.State.Delta0ModeColor[1] = g; + Glide.State.Delta0ModeColor[2] = b; + Glide.State.Delta0ModeColor[3] = a; + + OpenGL.Delta0Color[0] = r * D1OVER255; + OpenGL.Delta0Color[1] = g * D1OVER255; + OpenGL.Delta0Color[2] = b * D1OVER255; + // according to the linux driver src, + // alpha is completely ignored + // Glide.State.Delta0ModeColor[3] = a * D10255; + // Thus, alpha is take from grConstantColorValue() + OpenGL.Delta0Color[3] = OpenGL.ConstantColor[3]; + + SetConstantColorValue4State(); +} + +//************************************************* +//* Sets the Color and Alpha mask +//************************************************* +FX_ENTRY void FX_CALL +grColorMask( FxBool rgb, FxBool a ) +{ +#ifdef OGL_DONE + GlideMsg( "grColorMask( %s, %s )\n", + rgb ? "TRUE" : "FALSE", a ? "TRUE" : "FALSE" ); +#endif + glReportErrors("grColorMask"); + + RenderDrawTriangles( ); + + Glide.State.ColorMask = rgb; + Glide.State.AlphaMask = a; + glColorMask( rgb, rgb, rgb, a ); + glReportError(); +} + +FX_ENTRY void FX_CALL +grColorCombine( GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert ) +{ + glReportErrors("grColorCombine"); + + CHECK_STATE_CHANGED(Glide.State.ColorCombineFunction == function + && Glide.State.ColorCombineFactor == factor + && Glide.State.ColorCombineLocal == local + && Glide.State.ColorCombineOther == other + && Glide.State.ColorCombineInvert == invert); + +#if defined( OGL_DONE ) || defined( OGL_COMBINE ) + GlideMsg( "grColorCombine( %d, %d, %d, %d, %s )\n", + function, factor, local, other, invert ? "TRUE" : "FALSE" ); +#endif + + RenderDrawTriangles( ); + + // May need to turn the fog texture unit on/off + if ( Glide.State.ColorCombineInvert != invert) + { + SetColorInvertState(); + } + Glide.State.ColorCombineFunction = function; + Glide.State.ColorCombineFactor = factor; + Glide.State.ColorCombineLocal = local; + Glide.State.ColorCombineOther = other; + Glide.State.ColorCombineInvert = invert; + + // Used by the simple coloralpha model but also to determine whether textures are used + Glide.CLocal = colorCombineTable[ factor ][ function ].local; + Glide.COther = colorCombineTable[ factor ][ function ].other; + if ( colorCombineTable[ factor ][ function ].alocal ) + { + Glide.ALocal = true; + } + if ( colorCombineTable[ factor ][ function ].aother ) + { + Glide.AOther = true; + } + ColorFunctionFunc = colorCombineTable[ factor ][ function ].func; + ColorFactor3Func = colorCombineTable[ factor ][ function ].factorfunc; + + SetColorTextureState(); + SetTextureState(); + SetColorCombineState(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +inline void _grColorCombineDelta0Mode(bool delta0mode) +{ + CHECK_STATE_CHANGED(delta0mode == Glide.State.Delta0Mode); + +#if defined(OGL_DONE) + GlideMsg( "_grColorCombineDelta0Mode(%s)\n", delta0mode ? "TRUE" : "FALSE"); +#endif + + Glide.State.Delta0Mode = delta0mode; + if (delta0mode) + { + SetConstantColorValue4State(); + } + else + { + SetConstantColorValueState(); + } +} + +//************************************************* +FX_ENTRY void FX_CALL +guColorCombineFunction( GrColorCombineFnc_t fnc ) +{ +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "guColorCombineFunction( %d )\n", fnc ); +#endif + + // @todo: Analyse driver source to find out about ITRGB_DELTA0 + // color alpha render modes (in /glide/src/gu.c) + // So far it seems to ignore to iterate the vertex colors (right?) + /* gross hack to get ITRGB_DELTA0 modes working */ + // _grColorCombineDelta0Mode( FXFALSE ); + bool delta0mode = FXFALSE; + + switch ( fnc ) + { + case GR_COLORCOMBINE_ZERO: //0x0 + grColorCombine( GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_NONE, FXFALSE ); + break; + + case GR_COLORCOMBINE_CCRGB: //0x1 + grColorCombine( GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE ); + break; + + case GR_COLORCOMBINE_ITRGB: //0x2 + grColorCombine( GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, FXFALSE ); + break; + + case GR_COLORCOMBINE_DECAL_TEXTURE: //0x4 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_CCRGB: //0x5 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB: //0x6 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_ADD_ALPHA: //0x8 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA: //0x9 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL_ALPHA, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA_ADD_ITRGB: //0xa + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_ADD_ITRGB: //0xb + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_TEXTURE_SUB_ITRGB: //0xc + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_DIFF_SPEC_A: //0xe + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_DIFF_SPEC_B: //0xf + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_ONE: //0x10 + grColorCombine( GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, FXTRUE ); + break; + + case GR_COLORCOMBINE_ITRGB_DELTA0: //0x3 + // _grColorCombineDelta0Mode(FXTRUE); + delta0mode = FXTRUE; + grColorCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_CONSTANT, FXFALSE); + break; + + case GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_DELTA0: //0x7 + // @todo: May not be correct, as the 3dfx 2.4 pgm doesn't discuss this function. + // Using GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB with constant colors instead. + // In the Glide-Driver src its almost the same, but _grColorCombineDelta0Mode(FXTRUE) + // is called in advance to do something about the iterated colors. At least, this fixes, + // the problems with colors and skidmarks in Carmageddon (Splatpack), so it can't be that bad :^) + // _grColorCombineDelta0Mode(FXTRUE); + delta0mode = FXTRUE; + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_COLORCOMBINE_CCRGB_BLEND_ITRGB_ON_TEXALPHA: //0xd + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT, FXFALSE); + break; + } + + _grColorCombineDelta0Mode(delta0mode); +} + +//************************************************* +//* Sets the Alpha Test Reference Value +//************************************************* +FX_ENTRY void FX_CALL +grAlphaTestReferenceValue( GrAlpha_t value ) +{ + CHECK_STATE_CHANGED(Glide.State.AlphaReferenceValue == value); + +#ifdef OGL_DONE + GlideMsg( "grAlphaTestReferenceValue( %d )\n", value ); +#endif + + RenderDrawTriangles( ); + + Glide.State.AlphaReferenceValue = value; + OpenGL.AlphaReferenceValue = value * D1OVER255; + // Only call if the state needs to be changed +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + // alpha reference value applies only when the following conditons are true + if ((!OpenGL.ChromaKey || !OpenGL.Texture || OpenGL.Blend) + && Glide.State.AlphaOther == GR_COMBINE_OTHER_TEXTURE + && Glide.State.AlphaTestFunction != GR_CMP_ALWAYS) +#endif + SetChromaKeyAndAlphaState(); +} + +//************************************************* +//* Sets the Alpha Test Function +//************************************************* +FX_ENTRY void FX_CALL +grAlphaTestFunction( GrCmpFnc_t function ) +{ + CHECK_STATE_CHANGED(Glide.State.AlphaTestFunction == function); + +#ifdef OGL_DONE + GlideMsg( "grAlphaTestFunction( %d )\n", function ); +#endif + + RenderDrawTriangles( ); + + Glide.State.AlphaTestFunction = function; + + // We can do this just because we know the constant values for both OpenGL and Glide + // To port it to anything else than OpenGL we NEED to change this code + OpenGL.AlphaTestFunction = GL_NEVER + function; + +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + if ((Glide.State.AlphaOther == GR_COMBINE_OTHER_TEXTURE) + && (!OpenGL.ChromaKey || OpenGL.Blend || !OpenGL.Texture)) +#endif + { + SetChromaKeyAndAlphaState(); + } +} + +//************************************************* +FX_ENTRY void FX_CALL +grAlphaBlendFunction( GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, + GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df ) +{ + glReportErrors("grAlphaBlendFunction"); + + CHECK_STATE_CHANGED(Glide.State.AlphaBlendRgbSf == rgb_sf + && Glide.State.AlphaBlendRgbDf == rgb_df + && Glide.State.AlphaBlendAlphaSf == alpha_sf + && Glide.State.AlphaBlendAlphaDf == alpha_df); + +#ifdef OGL_PARTDONE + GlideMsg( "grAlphaBlendFunction( %d, %d, %d, %d )\n", + rgb_sf, rgb_df, alpha_sf, alpha_df ); +#endif + +#ifndef OGL_PARTDONE +#ifdef OGL_NOTDONE + // Unhandled glBlendFuncSeperateEXT emulation error + if (Glide.State.AlphaBlendRgbSf != Glide.State.AlphaBlendAlphaSf + || Glide.State.AlphaBlendRgbDf != Glide.State.AlphaBlendAlphaDf) + { + GlideMsg( "grAlphaBlendFunction( %d, %d, %d, %d ): emulation for sepearate alpha blend function not implemented\n", + rgb_sf, rgb_df, alpha_sf, alpha_df ); + } +#endif +#endif + + RenderDrawTriangles( ); + + Glide.State.AlphaBlendRgbSf = rgb_sf; + Glide.State.AlphaBlendRgbDf = rgb_df; + Glide.State.AlphaBlendAlphaSf = alpha_sf; + Glide.State.AlphaBlendAlphaDf = alpha_df; + + switch ( rgb_sf ) + { + case GR_BLEND_ZERO: OpenGL.SrcBlend = GL_ZERO; break; + case GR_BLEND_ONE: OpenGL.SrcBlend = GL_ONE; break; + case GR_BLEND_DST_COLOR: OpenGL.SrcBlend = GL_DST_COLOR; break; + case GR_BLEND_ONE_MINUS_DST_COLOR: OpenGL.SrcBlend = GL_ONE_MINUS_DST_COLOR; break; + case GR_BLEND_SRC_ALPHA: OpenGL.SrcBlend = GL_SRC_ALPHA; break; + case GR_BLEND_ONE_MINUS_SRC_ALPHA: OpenGL.SrcBlend = GL_ONE_MINUS_SRC_ALPHA; break; + case GR_BLEND_DST_ALPHA: OpenGL.SrcBlend = GL_DST_ALPHA; break; + case GR_BLEND_ONE_MINUS_DST_ALPHA: OpenGL.SrcBlend = GL_ONE_MINUS_DST_ALPHA; break; + case GR_BLEND_ALPHA_SATURATE: OpenGL.SrcBlend = GL_SRC_ALPHA_SATURATE; break; + +#ifdef OGL_DEBUG + default: + GlideMsg( "grAlphaBlendFunction: Unknown RGB source blend factor.\n" ); + OpenGL.SrcBlend = GL_ONE; + break; +#endif + } + + switch ( rgb_df ) + { + case GR_BLEND_ZERO: OpenGL.DstBlend = GL_ZERO; break; + case GR_BLEND_ONE: OpenGL.DstBlend = GL_ONE; break; + case GR_BLEND_SRC_COLOR: OpenGL.DstBlend = GL_SRC_COLOR; break; + case GR_BLEND_ONE_MINUS_SRC_COLOR: OpenGL.DstBlend = GL_ONE_MINUS_SRC_COLOR; break; + case GR_BLEND_SRC_ALPHA: OpenGL.DstBlend = GL_SRC_ALPHA; break; + case GR_BLEND_ONE_MINUS_SRC_ALPHA: OpenGL.DstBlend = GL_ONE_MINUS_SRC_ALPHA; break; + case GR_BLEND_DST_ALPHA: OpenGL.DstBlend = GL_DST_ALPHA; break; + case GR_BLEND_ONE_MINUS_DST_ALPHA: OpenGL.DstBlend = GL_ONE_MINUS_DST_ALPHA; break; + case GR_BLEND_PREFOG_COLOR: OpenGL.DstBlend = GL_ONE; break; + +#ifdef OGL_DEBUG + default: + GlideMsg( "grAlphaBlendFunction: Unknown RGB destination blend factor.\n" ); + OpenGL.DstBlend = GL_ZERO; + break; +#endif + } + + switch ( alpha_sf ) + { + case GR_BLEND_ZERO: OpenGL.SrcAlphaBlend = GL_ZERO; break; + case GR_BLEND_ONE: OpenGL.SrcAlphaBlend = GL_ONE; break; + case GR_BLEND_DST_COLOR: OpenGL.SrcAlphaBlend = GL_DST_COLOR; break; + case GR_BLEND_ONE_MINUS_DST_COLOR: OpenGL.SrcAlphaBlend = GL_ONE_MINUS_DST_COLOR; break; + case GR_BLEND_SRC_ALPHA: OpenGL.SrcAlphaBlend = GL_SRC_ALPHA; break; + case GR_BLEND_ONE_MINUS_SRC_ALPHA: OpenGL.SrcAlphaBlend = GL_ONE_MINUS_SRC_ALPHA; break; + case GR_BLEND_DST_ALPHA: OpenGL.SrcAlphaBlend = GL_DST_ALPHA; break; + case GR_BLEND_ONE_MINUS_DST_ALPHA: OpenGL.SrcAlphaBlend = GL_ONE_MINUS_DST_ALPHA; break; + case GR_BLEND_ALPHA_SATURATE: OpenGL.SrcAlphaBlend = GL_SRC_ALPHA_SATURATE; break; + } + + switch ( alpha_df ) + { + case GR_BLEND_ZERO: OpenGL.DstAlphaBlend = GL_ZERO; break; + case GR_BLEND_ONE: OpenGL.DstAlphaBlend = GL_ONE; break; + case GR_BLEND_SRC_COLOR: OpenGL.DstAlphaBlend = GL_SRC_COLOR; break; + case GR_BLEND_ONE_MINUS_SRC_COLOR: OpenGL.DstAlphaBlend = GL_ONE_MINUS_SRC_COLOR; break; + case GR_BLEND_SRC_ALPHA: OpenGL.DstAlphaBlend = GL_SRC_ALPHA; break; + case GR_BLEND_ONE_MINUS_SRC_ALPHA: OpenGL.DstAlphaBlend = GL_ONE_MINUS_SRC_ALPHA; break; + case GR_BLEND_DST_ALPHA: OpenGL.DstAlphaBlend = GL_DST_ALPHA; break; + case GR_BLEND_ONE_MINUS_DST_ALPHA: OpenGL.DstAlphaBlend = GL_ONE_MINUS_DST_ALPHA; break; + case GR_BLEND_PREFOG_COLOR: OpenGL.DstAlphaBlend = GL_ONE; break; + } + + OpenGL.Blend = !(( rgb_sf == GR_BLEND_ONE ) && ( rgb_df == GR_BLEND_ZERO )); + SetTextureState(); + SetBlendState(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +//************************************************* +FX_ENTRY void FX_CALL +grAlphaCombine( GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert ) +{ + glReportErrors("grAlphaCombine"); + + CHECK_STATE_CHANGED( Glide.State.AlphaFunction == function + && Glide.State.AlphaFactor == factor + && Glide.State.AlphaLocal == local + && Glide.State.AlphaOther == other + && Glide.State.AlphaInvert == invert); + +#if defined( OGL_DONE ) || defined( OGL_COMBINE ) + GlideMsg( "grAlphaCombine( %d, %d, %d, %d, %s )\n", + function, factor, local, other, invert ? "TRUE" : "FALSE" ); +#endif + + RenderDrawTriangles(); + + // If OPTIMISE_OPENGL_STATE_CHANGES is not defined, + // the update will always be executed +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + // When the local or other alpha changes, + // the color combine state may need an update + bool bUpdateColorCombineState = (OpenGL.ColorAlphaUnit2 && + ((local != Glide.State.AlphaLocal + && (Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_LOCAL_ALPHA + || Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA)) + || (other != Glide.State.AlphaOther + && (Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_OTHER_ALPHA + || Glide.State.ColorCombineFactor == GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA)) + )); +#endif + // May need to turn the fog texture unit on/off + if ( Glide.State.AlphaInvert != invert) + { + SetAlphaInvertState(); + } + + Glide.State.AlphaFunction = function; + Glide.State.AlphaFactor = factor; + Glide.State.AlphaLocal = local; + Glide.State.AlphaOther = other; + Glide.State.AlphaInvert = invert; + + // Used by the simple coloralpha model but also to determine whether textures are used + Glide.ALocal = alphaCombineTable[ factor ][ function ].local; + Glide.AOther = alphaCombineTable[ factor ][ function ].other; + AlphaFactorFunc = alphaCombineTable[ factor ][ function ].func; + + SetAlphaTextureState(); + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + SetTextureState(); + +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + if (bUpdateColorCombineState) + { +#endif + if (OpenGL.ColorAlphaUnit2) SetColorCombineState(); +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + } +#endif + + // Update chroma key and alpha because both + // Blend and Texture state might have changed +#ifdef OPTIMISE_OPENGL_STATE_CHANGES + if (OpenGL.ChromaKey && OpenGL.Texture) + { + // Without blend, changing the alpha combine has no effect when chromakeying is enabled + if (OpenGL.Blend) + { + SetChromaKeyAndAlphaState(); + SetAlphaCombineState(); + } + } + else + { + // If chromakeying is disabled, then everything is already setup correctly, + // and we have just to update the alpha combine setting + SetAlphaCombineState(); + } +#else + SetChromaKeyAndAlphaState(); + SetAlphaCombineState(); +#endif + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +//************************************************* +FX_ENTRY void FX_CALL +grAlphaControlsITRGBLighting( FxBool enable ) +{ +#ifdef OGL_NOTDONE + GlideMsg("grAlphaControlsITRGBALighting( %s )\n", enable ? "TRUE" : "FALSE" ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +guAlphaSource( GrAlphaSource_t dwMode ) +{ +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "guAlphaSource( %d )\n", dwMode ); +#endif + + switch ( dwMode ) + { + case GR_ALPHASOURCE_CC_ALPHA: //0x00 + grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE ); + break; + + case GR_ALPHASOURCE_ITERATED_ALPHA: //0x01 + grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, FXFALSE ); + break; + + case GR_ALPHASOURCE_TEXTURE_ALPHA: //0x02 + grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + + case GR_ALPHASOURCE_TEXTURE_ALPHA_TIMES_ITERATED_ALPHA: //0x03 + grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + break; + } +} + +//************************************************* +//* Sets the ChromaKey Value for comparision +//************************************************* +FX_ENTRY void FX_CALL +grChromakeyValue( GrColor_t value ) +{ + CHECK_STATE_CHANGED(Glide.State.ChromakeyValue == value); + +#ifdef OGL_PARTDONE + GlideMsg( "grChromakeyValue( 0x%X )\n", value ); +#endif + + RenderDrawTriangles( ); + + ConvertColor4B( value, OpenGL.ChromaColor.C ); + Textures->ChromakeyValue( OpenGL.ChromaColor.C ); + + Glide.State.ChromakeyValue = value; + s_Framebuffer.OnChromaKeyValueChanged(); +} + +//************************************************* +//* Sets the ChromaKey Mode +//************************************************* +FX_ENTRY void FX_CALL +grChromakeyMode(GrChromakeyMode_t mode) +{ + CHECK_STATE_CHANGED(Glide.State.ChromaKeyMode == mode); + +#ifdef OGL_PARTDONE + GlideMsg( "grChromakeyMode( %s )\n", mode ? "TRUE" : "FALSE" ); +#endif + + RenderDrawTriangles(); + Textures->ChromakeyMode(mode); + Glide.State.ChromaKeyMode = mode; + if (mode == GR_CHROMAKEY_ENABLE) + { + OpenGL.ChromaKey = true; + } + else + { + OpenGL.ChromaKey = false; + } + // State changes are detected in RenderUpdateState() +} + +//************************************************* +FX_ENTRY void FX_CALL +grGammaCorrectionValue( float value ) +{ +#ifdef OGL_DONE + GlideMsg( "grGammaCorrectionValue( %f )\n", value ); +#endif + + Glide.State.Gamma = value; + DisplayManager_SetGlideDisplayGamma(value); +} + diff --git a/MacGLide/OpenGLide/grguDepth.cpp b/MacGLide/OpenGLide/grguDepth.cpp new file mode 100644 index 0000000..cd55f1e --- /dev/null +++ b/MacGLide/OpenGLide/grguDepth.cpp @@ -0,0 +1,160 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Depth (Z/W-Buffer) Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GLRender.h" + +//************************************************* +//* Changes Depth Buffer Mode +//************************************************* +FX_ENTRY void FX_CALL +grDepthBufferMode( GrDepthBufferMode_t mode ) +{ + CHECK_STATE_CHANGED(Glide.State.DepthBufferMode == mode); + +#ifdef OGL_DONE + GlideMsg( "grDepthBufferMode( %d )\n", mode ); +#endif + glReportErrors("grDepthBufferMode"); + + RenderDrawTriangles( ); + + Glide.State.DepthBufferMode = mode; + /* + * In AddTriangle etc. Use of z or w for + * depth buffering is determined by the + * value of OpenGL.DepthBufferType. So + * I set it here. + */ + switch ( mode ) + { + case GR_DEPTHBUFFER_DISABLE: + OpenGL.DepthBufferType = 0; + glDisable( GL_DEPTH_TEST ); + return; + case GR_DEPTHBUFFER_ZBUFFER: + case GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS: + OpenGL.DepthBufferType = 1; + OpenGL.ZNear = ZBUFFERNEAR; + OpenGL.ZFar = ZBUFFERFAR; + break; + case GR_DEPTHBUFFER_WBUFFER: + case GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS: + OpenGL.DepthBufferType = 0; + OpenGL.ZNear = WBUFFERNEAR; + OpenGL.ZFar = WBUFFERFAR; + break; + } + glEnable( GL_DEPTH_TEST ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + if ( Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT ) + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMinY, Glide.State.ClipMaxY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + // Used for the buffer clearing + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + else + { + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMaxY, Glide.State.ClipMinY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + glMatrixMode( GL_MODELVIEW ); + + glReportError(); +} + +//************************************************* +//* Enables or Disables Depth Buffer Writting +//************************************************* +FX_ENTRY void FX_CALL +grDepthMask( FxBool enable ) +{ + CHECK_STATE_CHANGED(Glide.State.DepthBufferWritting == enable); + +#ifdef OGL_DONE + GlideMsg( "grDepthMask( %d )\n", enable ); +#endif + + glReportErrors("grDepthMask"); + RenderDrawTriangles( ); + Glide.State.DepthBufferWritting = + OpenGL.DepthBufferWritting = enable; + glDepthMask( OpenGL.DepthBufferWritting ); + glReportError(); +} + +//************************************************* +//* Sets the Depth Function to use +//************************************************* +FX_ENTRY void FX_CALL +grDepthBufferFunction( GrCmpFnc_t func ) +{ +#ifdef OGL_DONE + GlideMsg( "grDepthBufferFunction( %d )\n", func ); +#endif + glReportErrors("grDepthBufferFunction"); + + RenderDrawTriangles( ); + Glide.State.DepthFunction = func; + // We can do this just because we know the constant values for both OpenGL and Glide + // To port it to anything else than OpenGL we NEED to change this code + OpenGL.DepthFunction = GL_NEVER + func; + glDepthFunc( OpenGL.DepthFunction ); + + glReportError(); +} + +//************************************************* +//* Set the depth bias level +//************************************************* +FX_ENTRY void FX_CALL +grDepthBiasLevel( FxI16 level ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grDepthBiasLevel( %d )\n", level ); +#endif + glReportErrors("grDepthBiasLevel"); + + RenderDrawTriangles( ); + Glide.State.DepthBiasLevel = level; + //OpenGL.DepthBiasLevel = level * D1OVER65536; + OpenGL.DepthBiasLevel = level * 10.0f; + glPolygonOffset( 1.0f, OpenGL.DepthBiasLevel ); + if ( level != 0 ) + { + glEnable( GL_POLYGON_OFFSET_FILL ); + } + else + { + glDisable( GL_POLYGON_OFFSET_FILL ); + } + glReportError(); +} + diff --git a/MacGLide/OpenGLide/grguDraw.cpp b/MacGLide/OpenGLide/grguDraw.cpp new file mode 100644 index 0000000..6f9ae34 --- /dev/null +++ b/MacGLide/OpenGLide/grguDraw.cpp @@ -0,0 +1,322 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Drawing Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GLRender.h" +#include "GLRenderUpdateState.h" + +//************************************************* +//* Draws a Triangle on the screen +//************************************************* +FX_ENTRY void FX_CALL +grDrawTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grDrawTriangle( ---, ---, --- )\n" ); +#endif + + SetClipVerticesState(false); + + RenderAddTriangle( a, b, c, true ); + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +//************************************************* +//* Draws a planar polygon on the screen +//************************************************* +FX_ENTRY void FX_CALL +grDrawPlanarPolygonVertexList( int nVertices, const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg("grDrawPlanarPolygonVertexList( %d, --- )\n", nVertices ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nVertices; i++ ) + { + RenderAddTriangle( &vlist[ 0 ], &vlist[ i - 1 ], &vlist[ i ], true ); + } + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +//************************************************* +//* Draws a Line on the screen +//************************************************* +FX_ENTRY void FX_CALL +grDrawLine( const GrVertex *a, const GrVertex *b ) +{ +#ifdef OGL_CRITICAL + GlideMsg("grDrawLine( ---, --- )\n"); +#endif + + SetClipVerticesState(false); + + RenderAddLine( a, b, true ); +} + +//************************************************* +//* Draws a Point on the screen +//************************************************* +FX_ENTRY void FX_CALL +grDrawPoint( const GrVertex *a ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grDrawPoint( --- )\n" ); +#endif + + SetClipVerticesState(false); + + RenderAddPoint( a, true ); +} + +//************************************************* +//* Draw a convex non-planar polygon +//************************************************* +FX_ENTRY void FX_CALL +grDrawPolygon( int nverts, const int ilist[], const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grDrawPolygon( %d, ---, --- )\n" ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nverts; i++ ) + { + RenderAddTriangle( &vlist[ ilist[ 0 ] ], + &vlist[ ilist[ i - 1 ] ], + &vlist[ ilist[ i ] ], + true ); + } + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +//************************************************* +//* Draw a convex planar polygon +//************************************************* +FX_ENTRY void FX_CALL +grDrawPlanarPolygon( int nverts, const int ilist[], const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grDrawPlanarPolygon( %d, ---, --- )\n", nverts ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nverts; i++ ) + { + RenderAddTriangle( &vlist[ ilist[ 0 ] ], + &vlist[ ilist[ i - 1 ] ], + &vlist[ ilist[ i ] ], + true ); + } + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +//************************************************* +//* Draw a convex non-planar polygon +//************************************************* +FX_ENTRY void FX_CALL +grDrawPolygonVertexList( int nVertices, const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grDrawPolygonVertexList( %d, --- )\n", nVertices ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nVertices; i++ ) + { + RenderAddTriangle( &vlist[ 0 ], + &vlist[ i - 1 ], + &vlist[ i ], + true ); + } + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +guAADrawTriangleWithClip( const GrVertex *a, const GrVertex *b, + const GrVertex *c ) +{ +#ifdef OGL_CRITICAL + GlideMsg("guAADrawTriangleWithClip( ---, ---, --- )\n"); +#endif + + SetClipVerticesState(true); + + RenderAddTriangle( a, b, c, false ); + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +guDrawTriangleWithClip( const GrVertex *a, + const GrVertex *b, + const GrVertex *c ) +{ +#ifdef OGL_CRITICAL + GlideMsg("guDrawTriangleWithClip( ---, ---, --- )\n"); +#endif + + SetClipVerticesState(true); + + RenderAddTriangle( a, b, c, false ); + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +guDrawPolygonVertexListWithClip( int nVertices, const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "guDrawPolygonVertexListWithClip( %d, --- )\n", nVertices ); +#endif + + SetClipVerticesState(true); + + for ( int i = 2; i < nVertices; i++ ) + { + RenderAddTriangle( &vlist[ 0 ], + &vlist[ i - 1 ], + &vlist[ i ], + false ); + } + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +grAADrawLine( const GrVertex *a, const GrVertex *b ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grAADrawLine( ---, --- )\n" ); +#endif + + SetClipVerticesState(false); + + RenderAddLine( a, b, true ); +} + +FX_ENTRY void FX_CALL +grAADrawPoint(const GrVertex *a ) +{ +#ifdef OGL_CRITICAL + GlideMsg("grAADrawPoint( --- )\n"); +#endif + + SetClipVerticesState(false); + + RenderAddPoint( a, true ); +} + +FX_ENTRY void FX_CALL +grAADrawPolygon( const int nverts, const int ilist[], const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grAADrawPolygon( %d, ---, --- )\n", nverts ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nverts; i++ ) + { + RenderAddTriangle( &vlist[ ilist[ 0 ] ], + &vlist[ ilist[ i - 1 ] ], + &vlist[ ilist[ i ] ], + true ); + } + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +grAADrawPolygonVertexList( const int nverts, const GrVertex vlist[] ) +{ +#ifdef OGL_CRITICAL + GlideMsg( "grAADrawPolygonVertexList( %d, --- )\n", nverts ); +#endif + + SetClipVerticesState(false); + + for ( int i = 2; i < nverts; i++ ) + { + RenderAddTriangle( &vlist[ 0 ], + &vlist[ i - 1 ], + &vlist[ i ], + true ); + } + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} + +FX_ENTRY void FX_CALL +grAADrawTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c, + FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias ) +{ +#ifdef OGL_CRITICAL + GlideMsg("grAADrawTriangle( ---, ---, ---, %d, %d, %d )\n", + ab_antialias, bc_antialias, ca_antialias ); +#endif + + SetClipVerticesState(false); + + RenderAddTriangle( a, b, c, true ); + + if ( Glide.State.RenderBuffer == GR_BUFFER_FRONTBUFFER ) + { + RenderDrawTriangles( ); + glFlush( ); + } +} diff --git a/MacGLide/OpenGLide/grguFog.cpp b/MacGLide/OpenGLide/grguFog.cpp new file mode 100644 index 0000000..c5fada1 --- /dev/null +++ b/MacGLide/OpenGLide/grguFog.cpp @@ -0,0 +1,229 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Fog Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideSettings.h" +#include "GLRender.h" +#include "GLUtil.h" +#include "GLRenderUpdateState.h" +#include "OGLTables.h" + +//************************************************* +//* download a fog table +//* Fog is applied after color combining and before alpha blending. +//************************************************* +FX_ENTRY void FX_CALL +grFogTable( const GrFog_t *ft ) +{ +#ifdef OGL_DONE + GlideMsg( "grFogTable( --- )\n" ); +#endif + + if ( InternalConfig.FogMode > OpenGLideFogEmulation_None ) + { + memcpy( Glide.FogTable, ft, GR_FOG_TABLE_SIZE * sizeof( FxU8 ) ); + Glide.FogTable[ GR_FOG_TABLE_SIZE ] = 255; + + for ( FxU32 i = 0; i < GR_FOG_TABLE_SIZE; i++ ) + { + for ( FxU32 j = intStartEnd[ i ]; j < intStartEnd[ i + 1 ]; j++ ) + { + OpenGL.FogTable[ j ] = (FxU8)( Glide.FogTable[ i ] + + ( Glide.FogTable[ i + 1 ] - Glide.FogTable[ i ] ) * ( j - intStartEnd[ i ] ) / + intEndMinusStart[ i ] ); + } + } + } +} + +//************************************************* +FX_ENTRY void FX_CALL +grFogColorValue( GrColor_t fogcolor ) +{ + glReportErrors("grFogColorValue"); +#ifdef OGL_PARTDONE + GlideMsg( "grFogColorValue( %x )\n", fogcolor ); +#endif + + RenderDrawTriangles(); + Glide.State.FogColorValue = fogcolor; + ConvertColorF(fogcolor, + OpenGL.FogColor[0], + OpenGL.FogColor[1], + OpenGL.FogColor[2], + OpenGL.FogColor[3]); + SetFogColorState(); +} + +//************************************************* +FX_ENTRY void FX_CALL +grFogMode( GrFogMode_t mode ) +{ + glReportErrors("grFogMode"); + + CHECK_STATE_CHANGED(mode == Glide.State.FogMode); + +#ifdef OGL_PARTDONE + GlideMsg( "grFogMode( %d )\n", mode ); +#endif + + RenderDrawTriangles(); + + Glide.State.FogMode = mode; + OpenGL.Fog = mode & (GR_FOG_WITH_ITERATED_ALPHA | GR_FOG_WITH_TABLE); + SetFogModeState(); +} + +//************************************************* +FX_ENTRY void FX_CALL +guFogGenerateExp( GrFog_t *fogtable, float density ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "guFogGenerateExp( ---, %-4.2f )\n", density ); +#endif + glReportErrors("guFogGenerateExp"); + + float f; + float scale; + float dp; + + dp = density * guFogTableIndexToW( GR_FOG_TABLE_SIZE - 1 ); + scale = 255.0F / ( 1.0F - (float) exp( -dp ) ); + + for ( int i = 0; i < GR_FOG_TABLE_SIZE; i++ ) + { + dp = density * guFogTableIndexToW( i ); + f = ( 1.0F - (float) exp( -dp ) ) * scale; + + if ( f > 255.0F ) + { + f = 255.0F; + } + else if ( f < 0.0F ) + { + f = 0.0F; + } + + fogtable[ i ] = (GrFog_t) f; + } + + if (InternalConfig.FogMode == OpenGLideFogEmulation_Simple) + { + glFogf( GL_FOG_MODE, GL_EXP ); + glReportError(); + glFogf( GL_FOG_DENSITY, density ); + glReportError(); + } +} + +//************************************************* +FX_ENTRY void FX_CALL +guFogGenerateExp2( GrFog_t *fogtable, float density ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "guFogGenerateExp2( ---, %-4.2f )\n", density ); +#endif + + glReportErrors("guFogGenerateExp2"); + + float Temp; + + for ( int i = 0; i < GR_FOG_TABLE_SIZE; i++ ) + { + Temp = ( 1.0f - (float) exp( ( -density) * guFogTableIndexToW( i ) ) * + (float)exp( (-density) * guFogTableIndexToW( i ) ) ) * 255.0f; + fogtable[ i ] = (FxU8) Temp; + } + + if (InternalConfig.FogMode == OpenGLideFogEmulation_Simple) + { + glFogf( GL_FOG_MODE, GL_EXP2 ); + glReportError(); + glFogf( GL_FOG_DENSITY, density ); + glReportError(); + } +} + +//************************************************* +FX_ENTRY void FX_CALL +guFogGenerateLinear( GrFog_t *fogtable, + float nearZ, float farZ ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "guFogGenerateLinear( ---, %-4.2f, %-4.2f )\n", nearZ, farZ ); +#endif + + glReportErrors("guFogGenerateLinear"); + + int Start, + End, + i; + + for( Start = 0; Start < GR_FOG_TABLE_SIZE; Start++ ) + { + if ( guFogTableIndexToW( Start ) >= nearZ ) + { + break; + } + } + for( End = 0; End < GR_FOG_TABLE_SIZE; End++ ) + { + if ( guFogTableIndexToW( End ) >= farZ ) + { + break; + } + } + + memset( fogtable, 0, GR_FOG_TABLE_SIZE ); + for( i = Start; i <= End; i++ ) + { + fogtable[ i ] = (FxU8)((float)( End - Start ) / 255.0f * (float)( i - Start )); + } + + for( i = End; i < GR_FOG_TABLE_SIZE; i++ ) + { + fogtable[ i ] = 255; + } + + if (InternalConfig.FogMode == OpenGLideFogEmulation_Simple) + { + glFogf( GL_FOG_MODE, GL_LINEAR ); + glReportError(); + glFogf( GL_FOG_START, nearZ ); + glReportError(); + glFogf( GL_FOG_END, farZ ); + glReportError(); + if (nearZ <0 || farZ > 1.0) + { + GlideMsg("Warning: guFogGenerateLinear( ---, %-4.2f, %-4.2f ) values out of expected range\n", nearZ, farZ); + } + } +} + +//************************************************* +//* convert a fog table index to a floating point eye-space w value +//************************************************* +FX_ENTRY float FX_CALL +guFogTableIndexToW( int i ) +{ +#ifdef OGL_DONE + GlideMsg( "guFogTableIndexToW( %d )\n", i ); +#endif +#ifdef OGL_DEBUG + if ( ( i < 0 ) || + ( i >= GR_FOG_TABLE_SIZE ) ) + { + GlideError( "Error on guFogTableIndexToW( %d )\n", i ); + } +#endif + + return tableIndexToW[ i ]; +} diff --git a/MacGLide/OpenGLide/grguLfb.cpp b/MacGLide/OpenGLide/grguLfb.cpp new file mode 100644 index 0000000..0aff62d --- /dev/null +++ b/MacGLide/OpenGLide/grguLfb.cpp @@ -0,0 +1,616 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Linear Frame Buffer Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideApplication.h" +#include "FormatConversion.h" +#include "GLExtensions.h" +#include "GLRender.h" +#include "GLUtil.h" + + +//************************************************* +FX_ENTRY FxBool FX_CALL +grLfbLock( GrLock_t dwType, + GrBuffer_t dwBuffer, + GrLfbWriteMode_t dwWriteMode, + GrOriginLocation_t dwOrigin, + FxBool bPixelPipeline, + GrLfbInfo_t *lfbInfo ) +{ +#if defined(OGL_CRITICAL) || defined(OGL_FRAMEBUFFER) + GlideMsg("grLfbLock( %d, %d, %d, %d, %d, 0x%x )\n", + dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline, lfbInfo); +#endif + +#ifdef OGL_NOTDONE + if (dwWriteMode != GR_LFBWRITEMODE_565 + && dwWriteMode != GR_LFBWRITEMODE_1555 + && dwWriteMode != GR_LFBWRITEMODE_888 + && dwWriteMode != GR_LFBWRITEMODE_ANY) + { + GlideMsg("grLfbLock() - dwWriteMode %d not supported\n", dwWriteMode); + } +#endif + + glReportErrors("grLfbLock"); + + dwWriteMode = (dwWriteMode == GR_LFBWRITEMODE_ANY) ? GR_LFBWRITEMODE_565 : dwWriteMode; + lfbInfo->strideInBytes = Glide.WindowWidth * (dwWriteMode >= GR_LFBWRITEMODE_888 ? 4 : 2); + lfbInfo->writeMode = dwWriteMode; + lfbInfo->origin = dwOrigin; + if ( dwType & GR_LFB_WRITE_ONLY ) + { + lfbInfo->lfbPtr = Glide.FrameBuffer.Address; + s_Framebuffer.OnBufferLockStartWrite(dwType, dwBuffer, dwWriteMode, dwOrigin, bPixelPipeline); + } + else if (OpenGL.WinOpen == false && Glide.ReadBuffer.Address) + { + BufferStruct* targetbuffer = Glide.ReadBuffer.Address ? &Glide.ReadBuffer : &Glide.TempBuffer; + lfbInfo->lfbPtr = targetbuffer->Address; + lfbInfo->origin = GR_ORIGIN_UPPER_LEFT; + } + else + { + // finish rendering + RenderDrawTriangles(); + glFinish(); + glReportError(); + // Alloc readbuffer + if (Glide.ReadBuffer.Address == NULL) + { + Glide.ReadBuffer.Address = (FxU16*) AllocFrameBuffer(Glide.WindowWidth * Glide.WindowHeight, sizeof(FxU16)); +#ifdef OPENGL_DEBUG + GlideMsg("Allocated Readbuffer(%dx%d) at 0x%x\n", + Glide.WindowWidth, Glide.WindowHeight, Glide.ReadBuffer.Address); +#endif + } + // select main memory buffers + BufferStruct* targetbuffer = Glide.ReadBuffer.Address ? &Glide.ReadBuffer : &Glide.TempBuffer; + BufferStruct* sourcebuffer = Glide.ReadBuffer.Address ? &Glide.TempBuffer : &Glide.FrameBuffer; + if (s_Framebuffer.GetRenderBufferChangedForRead() == true) + { + // select buffer size + unsigned long bufferwidth = Glide.ReadBuffer.Address ? OpenGL.WindowWidth : Glide.WindowWidth; + unsigned long bufferheight = Glide.ReadBuffer.Address ? OpenGL.WindowHeight : Glide.WindowHeight; + glReadBuffer(dwBuffer == GR_BUFFER_BACKBUFFER ? GL_BACK : GL_FRONT); + glReportError(); + bool scale = bufferwidth != Glide.WindowWidth || bufferheight != Glide.WindowHeight; + GLint glWriteMode; + switch (dwWriteMode) + { + case GR_LFBWRITEMODE_1555: glWriteMode = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; + case GR_LFBWRITEMODE_565: glWriteMode = GL_UNSIGNED_SHORT_5_6_5; break; + default: glWriteMode = GL_UNSIGNED_SHORT_5_6_5; break; + } + void* destination = (!scale && dwOrigin == GR_ORIGIN_LOWER_LEFT) ? targetbuffer->Address : sourcebuffer->Address; +#ifdef OPENGL_DEBUG + GlideMsg("Calling glReadPixels(%d, %d, 0x%x)\n", bufferwidth, bufferheight, destination); +#endif + glReadPixels(0, 0, + bufferwidth, bufferheight, + (dwWriteMode == GR_LFBWRITEMODE_1555) ? GL_RGBA : GL_RGB, + glWriteMode, + destination); + glReportError(); +#ifdef OPENGL_DEBUG + if (scale) + GlideMsg("Scaling to (%d, %d) from 0x%x to 0x%x\n", + Glide.WindowWidth, Glide.WindowHeight, sourcebuffer->Address, targetbuffer->Address); +#endif + if (dwOrigin == GR_ORIGIN_UPPER_LEFT) + { + // When the OpenGL resolution differs from the Glide resolution, + // the content of the read buffer must be scaled + if (scale) + { + // size/copy from OpenGL-sized buffer to Glide-sized buffer? + FxU16* src; + FxU16* dst = targetbuffer->Address; + int xratio = (bufferwidth << 16) / (Glide.WindowWidth); + int yratio = (bufferheight << 16) / (Glide.WindowHeight); + int u; + int v = 0; + int x; + int y; + for(y = 0; y < Glide.WindowHeight; y++) + { + src = sourcebuffer->Address + (bufferheight -1 - (v >> 16)) * bufferwidth; + u = 0; + for(x = 0;x < Glide.WindowWidth; x++) + { + *dst++ = src[u >> 16]; + u += xratio; + } + v += yratio; + } + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Copying/Vertical mirroring pixels to destination buffer from 0x%x to 0x%x\n", + sourcebuffer->Address, targetbuffer->Address); +#endif + // Swap pixels during copy from temp to read buffer + for ( int j = 0; j < Glide.WindowHeight; j++ ) + { + memcpy(targetbuffer->Address + (j * Glide.WindowWidth), + sourcebuffer->Address + ((bufferheight - 1 - j) * bufferwidth), + 2 * Glide.WindowWidth); + } + } + } + else if (scale) // GR_ORIGIN_LOWER_LEFT + { + // size/copy from OpenGL-sized buffer to Glide-sized buffer? + if (scale) + { + // Copy and scale + FxU16* src; + FxU16* dst = targetbuffer->Address; + int xratio = (bufferwidth << 16) / Glide.WindowWidth; + int yratio = (bufferheight << 16) / Glide.WindowHeight; + int u; + int v = 0; + int x; + int y; + for(y = 0; y < Glide.WindowHeight; y++) + { + src = sourcebuffer->Address + (v >> 16) * bufferwidth; + u = 0; + for(x = 0;x < Glide.WindowWidth; x++) + { + *dst++ = src[u >> 16]; + u += xratio; + } + v += yratio; + } + } + else + { +#ifdef OPENGL_DEBUG + GlideMsg("Copying/Vertical mirroring not necessary - pixels already in the right orientation\n"); +#endif + } + } + // Update with current framebuffer pixels not yet written to vram + // (Obmitting causes incomplete screenshots in Falcon 4.0) + s_Framebuffer.CopyFrameBuffer(targetbuffer->Address); + s_Framebuffer.ResetRenderBufferChangedForRead(); + } + // Update buffer struct + targetbuffer->Lock = true; + targetbuffer->Type = dwType; + targetbuffer->Buffer = dwBuffer; + targetbuffer->WriteMode = dwWriteMode; + targetbuffer->PixelPipeline = bPixelPipeline; + lfbInfo->lfbPtr = targetbuffer->Address; + } + return FXTRUE; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grLfbUnlock( GrLock_t dwType, GrBuffer_t dwBuffer ) +{ +#if defined(OGL_CRITICAL) || defined(OGL_FRAMEBUFFER) + GlideMsg("grLfbUnlock( %d, %d )\n", dwType, dwBuffer ); +#endif + + if ( dwType & GR_LFB_WRITE_ONLY ) + { + if ( ! Glide.FrameBuffer.Lock ) + { + return FXFALSE; + } + s_Framebuffer.OnBufferUnlockEndWrite(dwBuffer); + Glide.FrameBuffer.Lock = false; + return FXTRUE; + } + else + { + BufferStruct* targetbuffer = Glide.ReadBuffer.Address ? &Glide.ReadBuffer : &Glide.TempBuffer; + if (targetbuffer->Lock) + { + // We're not interested in keeping track of unlocks since this breaks + // Framebuffer updates when moving the cursor in Carmageddon movie mode + // (because grLfbReadRegion() is called) + // @todo: -> Doesn't solve the issue + targetbuffer->Lock = false; + return FXTRUE; + } + else + { + return FXFALSE; + } + } +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grLfbReadRegion( GrBuffer_t src_buffer, + FxU32 src_x, FxU32 src_y, + FxU32 src_width, FxU32 src_height, + FxU32 dst_stride, void *dst_data ) +{ +#if defined(OGL_DONE) || defined(OGL_FRAMEBUFFER) + GlideMsg("grLfbReadRegion( %d, %d, %d, %d, %d, %d, 0x%x )\n", + src_buffer, src_x, src_y, src_width, src_height, dst_stride, dst_data); +#endif + + if (s_GlideApplication.GetType() == GlideApplication::Carmageddon) + { + RenderDrawTriangles(); + s_Framebuffer.OnLfbReadRegion(); + // To render the cursor in Movie-mode correctly, the region + // must be filled with the framebuffer's chromakey color. + // But Carmageddon seems to write a column filled with the + // endian-swapped chromakey value into the framebuffer. + // Workaround: + // Using an endian-symetric chromakey value (outch) + // Also one more pixel than expected must be set in order to + // avoid a black dot in the lower right corner of the cursor. + // All of this could be avoided with PedanticFrameBufferEmulation. + const unsigned jump_dst = ((dst_stride >> 1) - src_width); + unsigned long jump = jump_dst; + const unsigned long pixels = src_width * src_height + 1; + FxU16* d = reinterpret_cast(dst_data); + FxU16 chromakey = s_Framebuffer.GetChromaKeyValue(); + swapshort(&chromakey); + for(unsigned int i = 0; i < pixels; i+=1) + { + d[i] = chromakey; + jump--; + if (jump == 0) + { + jump = jump_dst; + i += jump; + } + } + return FXTRUE; + } + + // Copied from the linux sst1 driver src + FxBool rv = FXTRUE; + GrLfbInfo_t info; + +//#if (GLIDE_PLATFORM & GLIDE_HW_SST1) +// gc->lfbSliOk = 1; + info.size = sizeof( info ); + if ( grLfbLock( GR_LFB_READ_ONLY, + src_buffer, + GR_LFBWRITEMODE_ANY, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info ) ) { + FxU32 *srcData; /* Tracking Source Pointer */ + FxU32 *dstData; /* Tracking Destination Pointer */ + FxU32 *end; /* Demarks End of each Scanline */ + FxU32 srcJump; /* bytes to next scanline */ + FxU32 dstJump; /* bytes to next scanline */ + FxU32 length; /* bytes to copy in scanline */ + FxU32 scanline; /* scanline number */ + int aligned; /* word aligned? */ + FxU32 odd; /* is src_y odd? ( for sli ) */ + + dstData = ( FxU32 * ) dst_data; + srcData = ( FxU32 * ) ( ((char*)info.lfbPtr)+ + (src_y*info.strideInBytes) + + (src_x<<1) ); + scanline = src_height; + length = src_width * 2; + dstJump = dst_stride - length; + srcJump = info.strideInBytes - length; + aligned = !((int)srcData&0x2); + odd = (src_y+src_height) & 0x1; + + if ( aligned ) { + while( scanline-- ) { + end = (FxU32*)((char*)srcData + length - 2); +/* + if(gc->scanline_interleaved == FXTRUE) { + if((scanline+odd) & 0x1) + sst1InitSliPciOwner(gc->base_ptr, SST_SLI_MASTER_OWNPCI); + else + sst1InitSliPciOwner(gc->base_ptr, SST_SLI_SLAVE_OWNPCI); + } +*/ + while( srcData < end ) + *dstData++ = *srcData++; + + if ( ((int)length) & 0x2 ) { + (*(FxU16*)dstData) = (*(FxU16*)srcData); + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + } + + dstData = (FxU32*)(((char*)dstData)+dstJump); + srcData = (FxU32*)(((char*)srcData)+srcJump); + } + } else { + while( scanline-- ) { + end = (FxU32*)((char*)srcData + length - 2); +/* + if(gc->scanline_interleaved == FXTRUE) { + if((scanline+odd) & 0x1) + sst1InitSliPciOwner(gc->base_ptr, SST_SLI_MASTER_OWNPCI); + else + sst1InitSliPciOwner(gc->base_ptr, SST_SLI_SLAVE_OWNPCI); + } +*/ + (*(FxU16*)dstData) = (*(FxU16*)srcData); + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + + while( srcData < end ) + *dstData++ = *srcData++; + + if ( !(((int)length) & 0x2) ) { + (*(FxU16*)dstData) = (*(FxU16*)srcData); + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + } + + dstData = (FxU32*)(((char*)dstData)+dstJump); + srcData = (FxU32*)(((char*)srcData)+srcJump); + } + } + grLfbUnlock( GR_LFB_READ_ONLY, src_buffer ); + /* + if ( gc->scanline_interleaved ) + sst1InitSliPciOwner( gc->base_ptr, SST_SLI_MASTER_OWNPCI ); + */ + } else { + rv = FXFALSE; + } + return rv; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grLfbWriteRegion( GrBuffer_t dst_buffer, + FxU32 dst_x, FxU32 dst_y, + GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, + FxI32 src_stride, void *src_data ) +{ +#if defined(OGL_DONE) || defined(OGL_FRAMEBUFFER) + GlideMsg("grLfbWriteRegion( %d, %d, %d, %d, %d, %d, %d, 0x%x )\n", + dst_buffer, dst_x, dst_y, src_format, src_width, src_height, src_stride, src_data); +#endif + + // Copied from the linux sst1 driver src + FxBool rv = FXTRUE; + GrLfbInfo_t info; + GrLfbWriteMode_t writeMode; + + /* + GR_BEGIN_NOFIFOCHECK("grLfbWriteRegion",82); + GDBG_INFO_MORE((gc->myLevel, + "(0x%x,%d,%d,%d,%d,%d,%d,0x%x)\n", + dst_buffer, dst_x, dst_y, + src_format, src_width, src_height, + src_stride, src_data )); + */ + +// #if ( GLIDE_PLATFORM & GLIDE_HW_SST1 ) + if ( src_format == GR_LFB_SRC_FMT_RLE16 ) + writeMode = GR_LFBWRITEMODE_565; + else + writeMode = src_format; + + info.size = sizeof( info ); + + if ( grLfbLock( GR_LFB_WRITE_ONLY | GR_LFB_NOIDLE, + dst_buffer, + writeMode, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info ) ) { + FxU32 *srcData; /* Tracking Source Pointer */ + FxU32 *dstData; /* Tracking Destination Pointer */ + FxU32 *end; /* Demarks End of each Scanline */ + FxI32 srcJump; /* bytes to next scanline */ + FxU32 dstJump; /* bytes to next scanline */ + FxU32 length; /* bytes to copy in scanline */ + FxU32 scanline; /* scanline number */ + int aligned; /* word aligned? */ + + + srcData = ( FxU32 * ) src_data; + dstData = ( FxU32 * ) ( ((char*)info.lfbPtr)+ + (dst_y*info.strideInBytes) ); + scanline = src_height; + + switch( src_format ) { + /* 16-bit aligned */ + case GR_LFB_SRC_FMT_565: + case GR_LFB_SRC_FMT_555: + case GR_LFB_SRC_FMT_1555: + case GR_LFB_SRC_FMT_ZA16: + dstData = (FxU32*)(((FxU16*)dstData) + dst_x); + length = src_width * 2; + aligned = !((int)dstData&0x2); + srcJump = src_stride - length; + dstJump = info.strideInBytes - length; + if ( aligned ) + { + while( scanline-- ) + { + // GR_SET_EXPECTED_SIZE(length); + end = (FxU32*)((char*)srcData + length - 2); + while( srcData < end ) + { + // GR_SET( dstData[0], srcData[0] ); +#ifdef OPENGLIDE_HOST_MAC + swaplong(dstData, srcData); +#else + *dstData = *srcData; +#endif + dstData++; + srcData++; + } + + if ( ((int)length) & 0x2 ) + { + /* + GR_SET16( (*(FxU16*)&(dstData[0])), + (*(FxU16*)&(srcData[0])) ); + */ + (*(FxU16*)&(dstData[0])) = (*(FxU16*)&(srcData[0])); + + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + } + + dstData = (FxU32*)(((char*)dstData)+dstJump); + srcData = (FxU32*)(((char*)srcData)+srcJump); + // GR_CHECK_SIZE_SLOPPY(); + } + } + else + { + while( scanline-- ) { + // GR_SET_EXPECTED_SIZE(length); + end = (FxU32*)((char*)srcData + length - 2); + /* + GR_SET16( (*(FxU16*)&(dstData[0])), + (*(FxU16*)&(srcData[0])) ); + */ +#ifdef OPENGLIDE_HOST_MAC + swapshort(dstData, srcData); +#else + (*(FxU16*)&(dstData[0])) = (*(FxU16*)&(srcData[0])); +#endif + + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + + while( srcData < end ) { + // GR_SET( dstData[0], srcData[0] ); +#ifdef OPENGLIDE_HOST_MAC + swaplong(dstData, srcData); +#else + *dstData = *srcData; +#endif + dstData++; + srcData++; + } + + if ( !(length & 0x2) ) + { + /* + GR_SET16( (*(FxU16*)&(dstData[0])), + (*(FxU16*)&(srcData[0])) ); + */ +#ifdef OPENGLIDE_HOST_MAC + swapshort(dstData, srcData); +#else + (*(FxU16*)&(dstData[0])) = (*(FxU16*)&(srcData[0])); +#endif + + dstData = (FxU32*)(((FxU16*)dstData) + 1 ); + srcData = (FxU32*)(((FxU16*)srcData) + 1 ); + } + + dstData = (FxU32*)(((char*)dstData)+dstJump); + srcData = (FxU32*)(((char*)srcData)+srcJump); + // GR_CHECK_SIZE_SLOPPY(); + } + } + break; + /* 32-bit aligned */ + case GR_LFB_SRC_FMT_888: + case GR_LFB_SRC_FMT_8888: + case GR_LFB_SRC_FMT_565_DEPTH: + case GR_LFB_SRC_FMT_555_DEPTH: + case GR_LFB_SRC_FMT_1555_DEPTH: + dstData = ((FxU32*)dstData) + dst_x; + length = src_width * 4; + srcJump = src_stride - length; + dstJump = info.strideInBytes - length; + while( scanline-- ) { + // GR_SET_EXPECTED_SIZE(length); + end = (FxU32*)((char*)srcData + length); + while( srcData < end ) { + // GR_SET( dstData[0], srcData[0] ); +#ifdef OPENGLIDE_HOST_MAC + swaplong(dstData, srcData); +#else + *dstData = *srcData; +#endif + dstData++; + srcData++; + } + dstData = (FxU32*)(((char*)dstData)+dstJump); + srcData = (FxU32*)(((char*)srcData)+srcJump); + // GR_CHECK_SIZE_SLOPPY(); + } + break; + case GR_LFB_SRC_FMT_RLE16: + /* needs to be implemented */ + rv = FXFALSE; + break; + } + grLfbUnlock( GR_LFB_WRITE_ONLY, dst_buffer ); + } else { + rv = FXFALSE; + } + return rv; +} + +FX_ENTRY void FX_CALL +grLfbConstantAlpha( GrAlpha_t alpha ) +{ +#ifdef /* OGL_CRITICAL*/ OGL_DONE + GlideMsg("grLfbConstantAlpha( %lu )\n", alpha ); +#endif + s_Framebuffer.SetAlpha(alpha); +} + +FX_ENTRY void FX_CALL +grLfbConstantDepth( FxU16 depth ) +{ +#ifdef /* OGL_CRITICAL*/ OGL_DONE + GlideMsg("grLfbConstantDepth( %u )\n", depth ); +#endif + if (OpenGL.DepthBufferType == 1) // == GR_DEPTHBUFFER_ZBUFFER) + { + // map depth to range (0.0, 1.0) + s_Framebuffer.SetDepth(depth * D1OVER65535); + } + else + { + // depth is a float value +#ifdef /* OGL_CRITICAL*/ OGL_DONE + GlideMsg("grLfbConstantDepth( %u ) wbuffer not done\n", depth ); +#endif + s_Framebuffer.SetDepth(depth * D1OVER65535); + } +} + +FX_ENTRY void FX_CALL +grLfbWriteColorSwizzle( FxBool swizzleBytes, FxBool swapFxU16s ) +{ +#ifdef /* OGL_CRITICAL*/ OGL_NOTDONE + GlideMsg("grLfbWriteColorSwizzle( %d, %d )\n", + swizzleBytes, swapFxU16s ); +#endif +} + +FX_ENTRY void FX_CALL +grLfbWriteColorFormat( GrColorFormat_t colorFormat ) +{ +#ifdef /* OGL_CRITICAL */ OGL_NOTDONE + GlideMsg("grLfbWriteColorFormat( %u )\n", colorFormat ); +#endif +} diff --git a/MacGLide/OpenGLide/grguMisc.cpp b/MacGLide/OpenGLide/grguMisc.cpp new file mode 100644 index 0000000..b755aaf --- /dev/null +++ b/MacGLide/OpenGLide/grguMisc.cpp @@ -0,0 +1,325 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Other Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GLRender.h" +#include "GLRenderUpdateState.h" + +// Error Function variable +GLIDEERRORFUNCTION ExternErrorFunction; + +//************************************************* +//* Sets the External Error Function to call if +//* Glides Generates and Error +//************************************************* +FX_ENTRY void FX_CALL +grErrorSetCallback( void (*function)(const char *string, FxBool fatal) ) +{ +#ifdef OGL_DONE + GlideMsg( "grErrorSetCallback( --- )\n" ); +#endif + + ExternErrorFunction = function; +} + +//************************************************* +//* Sets the Cull Mode +//************************************************* +FX_ENTRY void FX_CALL +grCullMode( GrCullMode_t mode ) +{ +#ifdef OGL_DONE + GlideMsg( "grCullMode( %d )\n", mode ); +#endif + + glReportErrors("grCullMode"); + + RenderDrawTriangles( ); + + Glide.State.CullMode = mode; + + switch ( Glide.State.CullMode ) + { + case GR_CULL_DISABLE: + glDisable( GL_CULL_FACE ); + glCullFace( GL_BACK ); // This will be called in initialization + break; + case GR_CULL_NEGATIVE: + glEnable( GL_CULL_FACE ); + if ( Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT ) + { + glFrontFace( GL_CCW ); + } + else + { + glFrontFace( GL_CW ); + } + break; + case GR_CULL_POSITIVE: + glEnable( GL_CULL_FACE ); + if ( Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT ) + { + glFrontFace( GL_CW ); + } + else + { + glFrontFace( GL_CCW ); + } + break; + } + glReportError(); +} + +//************************************************* +//* Set the size and location of the hardware clipping window +//************************************************* +FX_ENTRY void FX_CALL +grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy ) +{ + CHECK_STATE_CHANGED(Glide.State.ClipMinX == minx + && Glide.State.ClipMinY == miny + && Glide.State.ClipMaxX == maxx + && Glide.State.ClipMaxY == maxy); + +#ifdef OGL_PARTDONE + GlideMsg( "grClipWindow( %d, %d, %d, %d )\n", minx, miny, maxx, maxy ); +#endif + + RenderDrawTriangles( ); + s_Framebuffer.OnClipWindow(); + // Store the Glide clipping coords + Glide.State.ClipMinX = minx; + Glide.State.ClipMaxX = maxx; + Glide.State.ClipMinY = miny; + Glide.State.ClipMaxY = maxy; + // calculate the corresponding OpenGL coords + // (the multiplication has to come first because the values are integers) + OpenGL.ClipMinX = OpenGL.WindowWidth * minx / Glide.WindowWidth; + OpenGL.ClipMaxX = OpenGL.WindowWidth * maxx / Glide.WindowWidth; + OpenGL.ClipMinY = OpenGL.WindowHeight * miny / Glide.WindowHeight; + OpenGL.ClipMaxY = OpenGL.WindowHeight * maxy / Glide.WindowHeight; + bool clip = ((Glide.State.ClipMinX != 0) || + (Glide.State.ClipMinY != 0) || + (Glide.State.ClipMaxX != Glide.WindowWidth) || + (Glide.State.ClipMaxY != Glide.WindowHeight)); + OpenGL.Clipping = clip; + SetClipVerticesState(clip); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + if ( Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT ) + { + // Used for geometry clipping + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMinY, Glide.State.ClipMaxY, + OpenGL.ZNear, OpenGL.ZFar); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + // Used for the buffer clearing + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + else + { + // Used for geometry clipping + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMaxY, Glide.State.ClipMinY, + OpenGL.ZNear, OpenGL.ZFar ); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + // Used for the buffer clearing + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + } + glMatrixMode( GL_MODELVIEW ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grDisableAllEffects( void ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grDisableAllEffects( )\n" ); +#endif + + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO ); + grAlphaTestFunction( GR_CMP_ALWAYS ); + grChromakeyMode( GR_CHROMAKEY_DISABLE ); + grDepthBufferMode( GR_DEPTHBUFFER_DISABLE ); + grFogMode( GR_FOG_DISABLE ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grResetTriStats( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grResetTriStats( )\n" ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grTriStats( FxU32 *trisProcessed, FxU32 *trisDrawn ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grTriStats( )\n" ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grHints( GrHint_t hintType, FxU32 hintMask ) +{ + switch( hintType ) + { + case GR_HINT_STWHINT: + CHECK_STATE_CHANGED(Glide.State.STWHint == hintMask); + #ifdef OGL_PARTDONE + GlideMsg("grHints( %d, %d )\n", hintType, hintMask); + #endif + RenderDrawTriangles(); + Glide.State.STWHint = hintMask; + break; + default: + #ifdef OGL_NOTDONE + GlideMsg("grHints( %d, %d )\n", hintType, hintMask); + #endif + break; + } +} + +/* +//************************************************* +FX_ENTRY void FX_CALL +grSplash( float x, float y, float width, float height, FxU32 frame ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSplash( %-4.2f, %-4.2f, %-4.2f, %-4.2f, %lu )\n", + x, y, width, height, frame ); +#endif +} +*/ + +//************************************************* +FX_ENTRY void FX_CALL +ConvertAndDownloadRle( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + FxU8 *bm_data, + long bm_h, + FxU32 u0, + FxU32 v0, + FxU32 width, + FxU32 height, + FxU32 dest_width, + FxU32 dest_height, + FxU16 *tlut ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "ConvertAndDownloadRle( %d, %lu, %d, %d, %d, %d, %d, ---, %l, %lu, %lu, %lu, %lu, %lu, %lu, --- )\n", + tmu, startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, bm_h, u0, v0, width, height, + dest_width, dest_height ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grCheckForRoom( FxI32 n ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grCheckForRoom( %l )\n", n ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grParameterData( FxU32 param, FxU32 components, FxU32 type, FxI32 offset ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grParameterData( %lu, %lu, %lu, %l )\n", + param, components, type, offset ); +#endif +} + +//************************************************* +FX_ENTRY int FX_CALL +guEncodeRLE16( void *dst, + void *src, + FxU32 width, + FxU32 height ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "guEncodeRLE16( ---, ---, %lu, %lu ) = 1\n", width, height ); +#endif + + return 1; +} + +//************************************************* +FX_ENTRY FxU32 FX_CALL +guEndianSwapFxU16s( FxU32 value ) +{ +#ifdef OGL_DONE + GlideMsg( "guEndianSwapFxU16s( %lu )\n", value ); +#endif + + return ( value << 16 ) | ( value >> 16 ); +} + +//************************************************* +FX_ENTRY FxU16 FX_CALL +guEndianSwapBytes( FxU16 value ) +{ +#ifdef OGL_DONE + GlideMsg( "guEndianSwapBytes( %u )\n", value ); +#endif + + return ( value << 8 ) | ( value >> 8 ); +} + +FX_ENTRY void FX_CALL +guMovieStart( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "guMovieStart( ) - Not Supported\n" ); +#endif +} + +FX_ENTRY void FX_CALL +guMovieStop( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "guMovieStop( ) - Not Supported\n" ); +#endif +} + +FX_ENTRY void FX_CALL +guMovieSetName( const char *name ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "guMovieSetName( ) - Not Supported\n" ); +#endif +} + diff --git a/MacGLide/OpenGLide/grguMisc.h b/MacGLide/OpenGLide/grguMisc.h new file mode 100644 index 0000000..c72f8b8 --- /dev/null +++ b/MacGLide/OpenGLide/grguMisc.h @@ -0,0 +1,34 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Other Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef GRGUMISC_H_ +#define GRGUMISC_H_ + +typedef void (*GLIDEERRORFUNCTION)( const char *string, FxBool fatal ); +extern GLIDEERRORFUNCTION ExternErrorFunction; + +// functions not defined in the SDK but part of either +// - earlier versions of Glide 2.4 +// - Part of the GLide 3 interface +#ifdef __cplusplus +extern "C" { +#endif + FX_ENTRY void FX_CALL guMovieStart(void); + FX_ENTRY void FX_CALL guMovieStop(void); + FX_ENTRY void FX_CALL guMovieSetName(const char *name); + FX_ENTRY void FX_CALL grParameterData(FxU32 param, FxU32 components, FxU32 type, FxI32 offset); + FX_ENTRY FxU32 FX_CALL guEndianSwapFxU16s(FxU32 value); +#ifdef __cplusplus +} +#endif + +#endif /*GRGUMISC_H_*/ diff --git a/MacGLide/OpenGLide/grguSstGlide.cpp b/MacGLide/OpenGLide/grguSstGlide.cpp new file mode 100644 index 0000000..39a796c --- /dev/null +++ b/MacGLide/OpenGLide/grguSstGlide.cpp @@ -0,0 +1,854 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Sst Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "Glide.h" +#include "GlideApplication.h" +#include "GlideDisplay.h" +#include "GlideSettings.h" +#include "GLExtensions.h" +#include "GLRender.h" +#include "GLUtil.h" +#include "OGLTables.h" +#include "PGTexture.h" + + +//************************************************* +//* Returns the current Glide Version +//************************************************* +FX_ENTRY void FX_CALL +grGlideGetVersion( char version[80] ) +{ +#ifdef OGL_DONE + GlideMsg( "grGlideGetVersion( --- )\n" ); +#endif + sprintf(version, "Glide 2.45 - %s %s", OpenGLideProductName, OpenGLideVersion); +} + +//************************************************* +//* Initializes what is needed +//************************************************* +FX_ENTRY void FX_CALL +grGlideInit( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grGlideInit( )\n" ); +#endif + + if ( OpenGL.GlideInit ) + { + grGlideShutdown( ); + } + memset( &Glide, 0, sizeof( GlideStruct ) ); + memset( &OpenGL, 0, sizeof( OpenGLStruct ) ); + Glide.ActiveVoodoo = 0; + Glide.State.VRetrace = FXTRUE; + ExternErrorFunction = NULL; +/* +#ifdef OGL_DEBUG + RDTSC( FinalTick ); + RDTSC( InitialTick ); + Fps = FpsAux = Frame = 0; +#endif +*/ + OpenGL.GlideInit = true; + Glide.TextureMemory = UserConfig.TextureMemorySize * 1024 * 1024; + Textures = new PGTexture( Glide.TextureMemory ); + if ( Textures == NULL ) + { + GlideError( "Cannot allocate enough memory for Texture Buffer in User setting, using default" ); + } + Glide.TexMemoryMaxPosition = (FxU32)Glide.TextureMemory; +} + +//************************************************* +//* Finishes everything +//************************************************* +FX_ENTRY void FX_CALL +grGlideShutdown( void ) +{ + if ( !OpenGL.GlideInit ) + { + return; + } + OpenGL.GlideInit = false; + +#ifdef OGL_DEBUG + RDTSC( FinalTick ); +#endif +#ifdef OGL_DONE + GlideMsg( "grGlideShutdown()\n" ); +#endif + + grSstWinClose( ); + if (Textures) delete Textures; +} + +//************************************************* +//* Sets all Glide State Variables +//************************************************* +FX_ENTRY void FX_CALL +grGlideSetState( const GrState *state ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grGlideSetState( --- )\n" ); +#endif + + // Ensure the state size is not too large + assert(sizeof(GlideState) < sizeof(GrState)); + + GlideState StateTemp; + memcpy( &StateTemp, state, sizeof( GlideState ) ); + Glide.State.ColorFormat = StateTemp.ColorFormat; + grRenderBuffer( StateTemp.RenderBuffer ); + grDepthBufferMode( StateTemp.DepthBufferMode ); + grDepthBufferFunction( StateTemp.DepthFunction ); + grDepthMask( StateTemp.DepthBufferWritting ); + grDepthBiasLevel( StateTemp.DepthBiasLevel ); + grDitherMode( StateTemp.DitherMode ); + grChromakeyValue( StateTemp.ChromakeyValue ); + grChromakeyMode( StateTemp.ChromaKeyMode ); + grAlphaTestReferenceValue( StateTemp.AlphaReferenceValue ); + grAlphaTestFunction( StateTemp.AlphaTestFunction ); + grColorMask( StateTemp.ColorMask, StateTemp.AlphaMask ); + grConstantColorValue( StateTemp.ConstantColorValue ); + grFogColorValue( StateTemp.FogColorValue ); + grFogMode( StateTemp.FogMode ); + grCullMode( StateTemp.CullMode ); + grTexClampMode( GR_TMU0, StateTemp.SClampMode, StateTemp.TClampMode ); + grTexFilterMode( GR_TMU0, StateTemp.MinFilterMode, StateTemp.MagFilterMode ); + grTexMipMapMode( GR_TMU0, StateTemp.MipMapMode, StateTemp.LodBlend ); + grColorCombine( StateTemp.ColorCombineFunction, StateTemp.ColorCombineFactor, + StateTemp.ColorCombineLocal, StateTemp.ColorCombineOther, StateTemp.ColorCombineInvert ); + grAlphaCombine( StateTemp.AlphaFunction, StateTemp.AlphaFactor, StateTemp.AlphaLocal, StateTemp.AlphaOther, StateTemp.AlphaInvert ); + grTexCombine( GR_TMU0, StateTemp.TextureCombineCFunction, StateTemp.TextureCombineCFactor, + StateTemp.TextureCombineAFunction, StateTemp.TextureCombineAFactor, + StateTemp.TextureCombineRGBInvert, StateTemp.TextureCombineAInvert ); + grAlphaBlendFunction( StateTemp.AlphaBlendRgbSf, StateTemp.AlphaBlendRgbDf, StateTemp.AlphaBlendAlphaSf, StateTemp.AlphaBlendAlphaDf ); + grClipWindow( StateTemp.ClipMinX, StateTemp.ClipMinY, StateTemp.ClipMaxX, StateTemp.ClipMaxY ); + grSstOrigin( StateTemp.OriginInformation ); + grTexSource( GR_TMU0, StateTemp.TexSource.StartAddress, StateTemp.TexSource.EvenOdd, &StateTemp.TexSource.Info ); + grTexLodBiasValue(GR_TMU0, StateTemp.LodBias); +} + +//************************************************* +//* Gets all Glide State Variables +//************************************************* +FX_ENTRY void FX_CALL +grGlideGetState( GrState *state ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grGlideGetState( --- )\n" ); +#endif + + // Ensure the state size is not too large + assert(sizeof(GlideState) < sizeof(GrState)); + + memcpy( state, &Glide.State, sizeof( GlideState ) ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grGlideShamelessPlug( const FxBool on ) +{ +#ifdef OGL_DONE + GlideMsg( "grGlideShamelessPlug( %d )\n", on ); +#endif + InternalConfig.ShamelessPlug = on; +} + +//************************************************* +//* Returns the number of Voodoo Boards Instaled +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstQueryBoards( GrHwConfiguration *hwConfig ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstQueryBoards( --- )\n" ); +#endif + + memset(hwConfig, 0, sizeof(GrHwConfiguration)); + hwConfig->num_sst = 1; + + return FXTRUE; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstWinOpen(FxU32 hwnd, + GrScreenResolution_t res, + GrScreenRefresh_t ref, + GrColorFormat_t cformat, + GrOriginLocation_t org_loc, + int num_buffers, + int num_aux_buffers) +{ + if ( OpenGL.WinOpen ) + { + grSstWinClose( ); + } + + // Some games read from the buffer after the window has been closed + // As a result, freeing the read buffer must be deferred until the + // next call to grSstWinOpen() or unloading the library + if (Glide.ReadBuffer.Address) + { + FreeFrameBuffer(Glide.ReadBuffer.Address); + Glide.ReadBuffer.Address = NULL; + } + + #ifdef OGL_DONE + GlideMsg( "grSstWinOpen( %d, %d, %d, %d, %d, %d, %d )\n", + hwnd, res, ref, cformat, org_loc, num_buffers, num_aux_buffers ); + #endif + + Glide.Resolution = res; + + #ifdef OGL_DEBUG + if ( Glide.Resolution > GR_RESOLUTION_400x300 ) + { + GlideError( "grSstWinOpen: res = GR_RESOLUTION_NONE\n" ); + return FXFALSE; + } + if ( Glide.Refresh > GR_REFRESH_120Hz ) + { + GlideError( "grSstWinOpen: Refresh Incorrect\n" ); + return FXFALSE; + } + #endif + + Glide.WindowWidth = windowDimensions[ Glide.Resolution ].width; + Glide.WindowHeight = windowDimensions[ Glide.Resolution ].height; + // Set the size of the opengl window (might be different from Glide window size) + if (UserConfig.Resolution == 0) + { + // Does only work if the library is loaded at startup, before the game changes the screen resolution + if (DisplayManager_GetDesktopDisplayResolution(OpenGL.WindowWidth, OpenGL.WindowHeight) != noErr) + { + // Use the resuolution requested by the game + OpenGL.WindowWidth = Glide.WindowWidth; + OpenGL.WindowHeight = Glide.WindowHeight; + } + } + else if (UserConfig.Resolution <= 16) + { + // multiply the original size by the resolution factor + OpenGL.WindowWidth = Glide.WindowWidth * UserConfig.Resolution; + OpenGL.WindowHeight = Glide.WindowHeight * UserConfig.Resolution; + } + else if (UserConfig.Resolution >= 512) + { + // override the resolution + OpenGL.WindowWidth = UserConfig.Resolution; + // Glide games have a fixed 4/3 aspect ratio + OpenGL.WindowHeight = UserConfig.Resolution * 3 / 4; + } + else + { + // Use the resuolution requested by the game + OpenGL.WindowWidth = Glide.WindowWidth; + OpenGL.WindowHeight = Glide.WindowHeight; + } + Glide.WindowTotalPixels = Glide.WindowWidth * Glide.WindowHeight; + Glide.Refresh = ref; + Glide.State.ColorFormat = cformat; + Glide.NumBuffers = num_buffers; + Glide.AuxBuffers = num_aux_buffers; + OpenGL.Refresh = windowRefresh[ Glide.Refresh ]; + OpenGL.WaitSignal = (FxU32)( 1000 / OpenGL.Refresh ); + memset(&Glide.FrameBuffer, 0, sizeof(BufferStruct)); + memset(&Glide.TempBuffer, 0, sizeof(BufferStruct)); + memset(&Glide.ReadBuffer, 0, sizeof(BufferStruct)); + // Initing OpenGL Window + if ( !InitWindow(hwnd)) + { + return FXFALSE; + } + + // Note: The OpenGL resolution might have changed during the call to InitWindow(). + // As a result, buffers must be allocated afterwards + const unsigned long openglpixels = OpenGL.WindowWidth * OpenGL.WindowHeight; + // At first, allocate a framebuffer for 16bit pixel data only (will be expanded on demand) + unsigned long buffertypesize = sizeof(FxU16); // (dwWriteMode >= GR_LFBWRITEMODE_888) ? sizeof(FxU32) : sizeof(FxU16); + Glide.FrameBuffer.Address = (FxU16*) AllocFrameBuffer(Glide.WindowTotalPixels * buffertypesize + openglpixels * sizeof(FxU32), 1); + Glide.TempBuffer.Address = &Glide.FrameBuffer.Address[Glide.WindowTotalPixels * buffertypesize >> 1]; + memset( Glide.FrameBuffer.Address, 0, Glide.WindowTotalPixels * buffertypesize); + memset( Glide.TempBuffer.Address, 0, openglpixels * sizeof(FxU32)); + // Prealloc readbuffer for Carmageddon, because allocating it on demand + // (when moving the cursor in Movie mode) would produce an OutOfMemory error) + if (Glide.ReadBuffer.Address == NULL && + s_GlideApplication.GetType() == GlideApplication::Carmageddon) + { + Glide.ReadBuffer.Address = (FxU16*) AllocFrameBuffer(Glide.WindowTotalPixels, sizeof(FxU16)); +#ifdef OPENGL_DEBUG + GlideMsg("Allocated Readbuffer(%dx%d) at 0x%x\n", + Glide.WindowWidth, Glide.WindowHeight, Glide.ReadBuffer.Address); +#endif + } + // Initialise the frame buffer emulation + RenderInitialize(); + s_Framebuffer.initialise(&Glide.FrameBuffer, &Glide.TempBuffer); + + #ifdef OGL_DONE + GlideMsg( "----Start of grSstWinOpen()\n" ); + #endif + // All should be disabled + //depth buffering, fog, chroma-key, alpha blending, alpha testing + #ifdef OPTIMISE_GLIDE_STATE_CHANGES + // When state change optimising is enabled, passing in default values of 0 + // will not initialise the corresponding values in the OpenGL struct, + // because the optimising code assumes, it has already been set earlier. + // By writing values other than 0 to glide state variables which will + // become 0 below, the OpenGL values are initialises as exspected. + // For functions that are called by other functions during the + // initialisation, like grColorCombine, explicit default values + // are given, (in this case by grAlphaCombine) + // grTexClampMode + Glide.State.SClampMode = -1; + Glide.State.TClampMode = -1; + // grTexMipMapMode + Glide.State.MipMapMode = -1; + Glide.State.LodBlend = -1; + // grCullMode + Glide.State.CullMode = -1; + // grDepthMask + Glide.State.DepthBufferWritting = -1; + // grDepthBufferMode + Glide.State.DepthBufferMode = -1; + // grChromakeyValue + Glide.State.ChromakeyValue = -1; + // grAlphaTestReferenceValue + Glide.State.AlphaReferenceValue = -1.0f; + // grDepthBiasLevel + Glide.State.DepthBiasLevel = -1; + // grFogMode + Glide.State.FogMode = -1; + // grFogColorValue + Glide.State.FogColorValue = -1; + // grHints + Glide.State.STWHint = -1; + // color combine + Glide.State.ColorCombineFunction = GR_COMBINE_FUNCTION_LOCAL; + Glide.State.ColorCombineFactor = GR_COMBINE_FACTOR_LOCAL; + Glide.State.ColorCombineLocal = GR_COMBINE_LOCAL_CONSTANT; + Glide.State.ColorCombineOther = GR_COMBINE_OTHER_CONSTANT; + Glide.State.ColorCombineInvert = FXTRUE; + // alpha combine + Glide.State.AlphaFunction = GR_COMBINE_FUNCTION_LOCAL; + Glide.State.AlphaFactor = GR_COMBINE_FACTOR_LOCAL; + Glide.State.AlphaLocal = GR_COMBINE_LOCAL_CONSTANT; + Glide.State.AlphaOther = GR_COMBINE_OTHER_CONSTANT; + Glide.State.AlphaInvert = FXTRUE; + // Blend + Glide.State.AlphaBlendRgbSf = -1; + Glide.State.AlphaBlendRgbDf = -1; + Glide.State.AlphaBlendAlphaSf = -1; + Glide.State.AlphaBlendAlphaDf = -1; + // tex combine + Glide.State.TextureCombineCFunction = GR_COMBINE_FUNCTION_ZERO; + Glide.State.TextureCombineCFactor = GR_COMBINE_FACTOR_NONE; + Glide.State.TextureCombineAFunction = GR_COMBINE_FUNCTION_ZERO; + Glide.State.TextureCombineAFactor = GR_COMBINE_FACTOR_NONE; + Glide.State.TextureCombineRGBInvert = FXFALSE; + Glide.State.TextureCombineAInvert = FXFALSE; + // Alpha function + Glide.State.AlphaTestFunction = -1; + Glide.State.AlphaOther = -1; + // Chromakeying + Glide.State.ChromaKeyMode = GR_CHROMAKEY_ENABLE; + Glide.State.ChromakeyValue = 0xffffffff; + // constant color value + Glide.State.ConstantColorValue = 0; + // lod bias + Glide.State.LodBias = -1; + #endif + Glide.State.OriginInformation = org_loc; + grClipWindow( 0, 0, Glide.WindowWidth, Glide.WindowHeight ); + grSstOrigin( org_loc ); + grTexClampMode( 0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP ); + grTexMipMapMode( 0, GR_MIPMAP_DISABLE, FXFALSE ); + grTexFilterMode( 0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR ); + grFogMode( GR_FOG_DISABLE ); + grCullMode( GR_CULL_DISABLE ); + grRenderBuffer( GR_BUFFER_BACKBUFFER ); + grAlphaTestFunction( GR_CMP_ALWAYS ); + grDitherMode( GR_DITHER_4x4 ); + // grColorCombine depends on grAlphaCombine, + // so we have to call grAlphaCombine first + grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_CONSTANT, + FXFALSE ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_ITERATED, + FXFALSE ); + grTexCombine( GR_TMU0,GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); + grAlphaControlsITRGBLighting( FXFALSE ); + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO ); + grColorMask( FXTRUE, FXFALSE ); + grDepthMask( FXFALSE ); + grDepthBufferMode( GR_DEPTHBUFFER_DISABLE ); + grDepthBufferFunction( GR_CMP_LESS ); + // chroma-key value, alpha test reference, constant depth value, + // constant alpha value, etc.) and pixel rendering statistic counters + // are initialized to 0x00. + grChromakeyMode( GR_CHROMAKEY_DISABLE ); + grChromakeyValue( 0x00 ); + grAlphaTestReferenceValue( 0x00 ); + grDepthBiasLevel( 0x00 ); + grFogColorValue( 0x00 ); + grConstantColorValue( 0xFFFFFFFF ); + grGammaCorrectionValue( 1.6f ); + grHints( GR_HINT_STWHINT, 0 ); + grTexLodBiasValue(GR_TMU0, 0.0f); + + #ifdef OGL_DONE + GlideMsg( "----End of grSstWinOpen()\n" ); + #endif + + OpenGL.WinOpen = true; + glFinish( ); + + // Show the splash screen? (code copied from the linux driver src) + if (UserConfig.NoSplash == false) + { + // Obsolete because state is preserved in grSplash + // GrState state; + // grGlideGetState(&state); +// @todo: There seem to be several versions of the splash screen +/* +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) + grSstOrigin( GR_ORIGIN_LOWER_LEFT ); + if (!_GlideRoot.environment.noSplash) { + HMODULE newSplash; + if (newSplash = LoadLibrary("3dfxsplash2.dll")) { + FARPROC fxSplash; + if (fxSplash = GetProcAddress(newSplash, "_fxSplash@16")) { + fxSplash(hWnd, gc->state.screen_width, + gc->state.screen_height, nAuxBuffers); + // _GlideRoot.environment.noSplash = 1; + UserConfig.NoSplash = true; + } + } + } +#endif // (GLIDE_PLATFORM & GLIDE_OS_WIN32) +*/ + /* If it's still 0, then do the old one */ + if (UserConfig.NoSplash == false) + { + grSplash(0.0f, 0.0f, + static_cast(Glide.WindowWidth), + static_cast(Glide.WindowHeight), + 0); + // The splash screen is displayed once, and because the + // internal config is reinitialised each time grWinOpen() + // is called, the value must be reset in the user config + UserConfig.NoSplash = true; + } + // grGlideSetState(&state); + } + + return FXTRUE; +} + +//************************************************* +//* Close the graphics display device +//************************************************* +FX_ENTRY void FX_CALL +grSstWinClose( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstWinClose()\n" ); +#endif + if ( ! OpenGL.WinOpen ) + { + return; + } + + OpenGL.WinOpen = false; + +#ifdef OGL_DEBUG + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "** Debug Information **\n" ); + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "MaxTriangles in Frame = %d\n", OGLRender.MaxTriangles ); + GlideMsg( "MaxTriangles in Sequence = %d\n", OGLRender.MaxSequencedTriangles ); + GlideMsg( "Mean value of Triangles in Sequence = %g\n", + static_cast(OGLRender.OverallTriangles) / static_cast(OGLRender.OverallRenderTriangleCalls)); + GlideMsg( "Overall triangles = %d\n", OGLRender.OverallTriangles); + GlideMsg( "Overall lines = %d\n", OGLRender.OverallLines); + GlideMsg( "Overall points = %d\n", OGLRender.OverallPoints); + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "MaxZ = %f\nMinZ = %f\n", OGLRender.MaxZ, OGLRender.MinZ ); + GlideMsg( "MaxX = %f\nMinX = %f\nMaxY = %f\nMinY = %f\n", + OGLRender.MaxX, OGLRender.MinX, OGLRender.MaxY, OGLRender.MinY ); + GlideMsg( "MaxS = %f\nMinS = %f\nMaxT = %f\nMinT = %f\n", + OGLRender.MaxS, OGLRender.MinS, OGLRender.MaxT, OGLRender.MinT ); + GlideMsg( "MaxF = %f\nMinF = %f\n", OGLRender.MaxF, OGLRender.MinF ); + GlideMsg( "MaxR = %f\nMinR = %f\n", OGLRender.MaxR, OGLRender.MinR ); + GlideMsg( "MaxG = %f\nMinG = %f\n", OGLRender.MaxG, OGLRender.MinG ); + GlideMsg( "MaxB = %f\nMinB = %f\n", OGLRender.MaxB, OGLRender.MinR ); + GlideMsg( "MaxA = %f\nMinA = %f\n", OGLRender.MaxA, OGLRender.MinA ); + GlideMsg( OGL_LOG_SEPARATE ); + GlideMsg( "Texture Information:\n" ); + GlideMsg( " 565 = %d\n", Textures->Num_565_Tex ); + GlideMsg( " c565 = %d\n", Textures->Num_565_Chromakey_Tex ); + GlideMsg( " 1555 = %d\n", Textures->Num_1555_Tex ); + GlideMsg( "c1555 = %d\n", Textures->Num_1555_Chromakey_Tex ); + GlideMsg( " 4444 = %d\n", Textures->Num_4444_Tex ); + GlideMsg( "c4444 = %d\n", Textures->Num_4444_Chromakey_Tex ); + GlideMsg( " 332 = %d\n", Textures->Num_332_Tex ); + GlideMsg( " 8332 = %d\n", Textures->Num_8332_Tex ); + GlideMsg( "Alpha = %d\n", Textures->Num_Alpha_Tex ); + GlideMsg( " AI88 = %d\n", Textures->Num_AlphaIntensity88_Tex ); + GlideMsg( " AI44 = %d\n", Textures->Num_AlphaIntensity44_Tex ); + GlideMsg( " AP88 = %d\n", Textures->Num_AlphaPalette_Tex ); + GlideMsg( " P8 = %d\n", Textures->Num_Palette_Tex ); + GlideMsg( " cP8 = %d\n", Textures->Num_Palette_Chromakey_Tex ); + GlideMsg( "Inten = %d\n", Textures->Num_Intensity_Tex ); + GlideMsg( " YIQ = %d\n", Textures->Num_YIQ_Tex ); + GlideMsg( " AYIQ = %d\n", Textures->Num_AYIQ_Tex ); + GlideMsg( "Other = %d\n", Textures->Num_Other_Tex ); + GlideMsg( OGL_LOG_SEPARATE ); +#endif + + if (s_GlideApplication.GetType() == GlideApplication::FutureCop) + { + // Store the read buffer for read out after the window has been closed + // (needed by FutureCop LAPD) + // @todo: writemode, buffer and origin are hardwired, + // so this might not work for other games +#ifdef OGL_DEBUG + GlideMsg("----MacGLide readbuffer copy----\n"); +#endif + GrLfbInfo_t lfbinfo; + if (grLfbLock(GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER, GR_LFBWRITEMODE_ANY, GR_ORIGIN_UPPER_LEFT, FXFALSE, &lfbinfo)) + { + grLfbUnlock(GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER); + } +#ifdef OGL_DEBUG + GlideMsg(OGL_LOG_SEPARATE); +#endif + } + + Textures->Clear(); + GLExtensionsCleanup(); + RenderFree(); + FinaliseOpenGLWindow(); + + FreeFrameBuffer(Glide.FrameBuffer.Address); + Glide.FrameBuffer.Address = NULL; + Glide.TempBuffer.Address = NULL; + // Freeing the readbuffer is be deferred until + // reopening the window or unloading the library +} + +//************************************************* +//* Returns the Hardware Configuration +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstQueryHardware( GrHwConfiguration *hwconfig ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstQueryHardware( --- )\n" ); +#endif + + hwconfig->num_sst = 1; + hwconfig->SSTs[0].type = UserConfig.BoardType; + + switch (hwconfig->SSTs[0].type) + { + case GR_SSTTYPE_VOODOO: + hwconfig->SSTs[0].sstBoard.VoodooConfig.fbRam = UserConfig.FrameBufferMemorySize; + // GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS and GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS + // modes are not available in revision 1 of the Pixelfx chip + hwconfig->SSTs[0].sstBoard.VoodooConfig.fbiRev = 2; + hwconfig->SSTs[0].sstBoard.VoodooConfig.nTexelfx = UserConfig.GlideTextureUnits; + hwconfig->SSTs[0].sstBoard.VoodooConfig.sliDetect = FXFALSE; + for(int tmu = 0; tmu < UserConfig.GlideTextureUnits; tmu++) + { + hwconfig->SSTs[tmu].sstBoard.VoodooConfig.tmuConfig[0].tmuRev = 1; + hwconfig->SSTs[tmu].sstBoard.VoodooConfig.tmuConfig[0].tmuRam = UserConfig.TextureMemorySize; + } + break; + case GR_SSTTYPE_SST96: + hwconfig->SSTs[0].sstBoard.SST96Config.fbRam = UserConfig.FrameBufferMemorySize; + hwconfig->SSTs[0].sstBoard.SST96Config.nTexelfx = UserConfig.GlideTextureUnits; + hwconfig->SSTs[0].sstBoard.SST96Config.tmuConfig.tmuRev = 1; + hwconfig->SSTs[0].sstBoard.SST96Config.tmuConfig.tmuRam = UserConfig.TextureMemorySize; + break; + case GR_SSTTYPE_AT3D: + hwconfig->SSTs[0].sstBoard.AT3DConfig.rev = 1; // whatsoever + break; + case GR_SSTTYPE_Voodoo2: + hwconfig->SSTs[0].sstBoard.Voodoo2Config.fbRam = UserConfig.FrameBufferMemorySize; + // GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS and GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS + // modes are not available in revision 1 of the Pixelfx chip + hwconfig->SSTs[0].sstBoard.Voodoo2Config.fbiRev = 2; + hwconfig->SSTs[0].sstBoard.Voodoo2Config.nTexelfx = UserConfig.GlideTextureUnits; + hwconfig->SSTs[0].sstBoard.Voodoo2Config.sliDetect = FXFALSE; + for(int tmu = 0; tmu < UserConfig.GlideTextureUnits; tmu++) + { + hwconfig->SSTs[tmu].sstBoard.Voodoo2Config.tmuConfig[0].tmuRev = 1; + hwconfig->SSTs[tmu].sstBoard.Voodoo2Config.tmuConfig[0].tmuRam = UserConfig.TextureMemorySize; + } + break; + } + return FXTRUE; +} + +//************************************************* +//* Selects which Voodoo Board is Active +//************************************************* +FX_ENTRY void FX_CALL +grSstSelect( int which_sst ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstSelect( %d )\n", which_sst ); +#endif + // Nothing Needed Here but... + Glide.ActiveVoodoo = which_sst; +} + +//************************************************* +//* Returns the Screen Height +//************************************************* +FX_ENTRY FxU32 FX_CALL +grSstScreenHeight( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstScreenHeight()\n" ); +#endif + + return Glide.WindowHeight; +} + +//************************************************* +//* Returns the Screen Width +//************************************************* +FX_ENTRY FxU32 FX_CALL +grSstScreenWidth( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstScreenWidth()\n" ); +#endif + + return Glide.WindowWidth; +} + +//************************************************* +//* Sets the Y Origin +//************************************************* +FX_ENTRY void FX_CALL +grSstOrigin( GrOriginLocation_t origin ) +{ +#ifdef OGL_DONE + GlideMsg( "grSstSetOrigin( %d )\n", origin ); +#endif + + glReportErrors("grSstOrigin"); + + RenderDrawTriangles( ); + Glide.State.OriginInformation = origin; + glMatrixMode( GL_PROJECTION ); + glReportError(); + glLoadIdentity( ); + glReportError(); + switch ( origin ) + { + case GR_ORIGIN_LOWER_LEFT: + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMinY, Glide.State.ClipMaxY, + OpenGL.ZNear, OpenGL.ZFar); + glReportError(); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + glReportError(); + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.ClipMinY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + glReportError(); + break; + case GR_ORIGIN_UPPER_LEFT: + glOrtho(Glide.State.ClipMinX, Glide.State.ClipMaxX, + Glide.State.ClipMaxY, Glide.State.ClipMinY, + OpenGL.ZNear, OpenGL.ZFar); + glReportError(); + glViewport(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + glReportError(); + glScissor(OpenGL.OriginX + OpenGL.ClipMinX, + OpenGL.OriginY + OpenGL.WindowHeight - OpenGL.ClipMaxY, + OpenGL.ClipMaxX - OpenGL.ClipMinX, + OpenGL.ClipMaxY - OpenGL.ClipMinY); + glReportError(); + break; + } + glMatrixMode( GL_MODELVIEW ); + glReportError(); + grCullMode( Glide.State.CullMode ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grSstPerfStats( GrSstPerfStats_t * pStats ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSstPerfStats\n" ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grSstResetPerfStats( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSstResetPerfStats( )\n" ); +#endif +} + +//************************************************* +FX_ENTRY FxU32 FX_CALL +grSstVideoLine( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSstVideoLine( )\n" ); +#endif + + return 0; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstVRetraceOn( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSstVRetraceOn( )\n" ); +#endif + + return Glide.State.VRetrace; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstIsBusy( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grSstIsBusy( )\n" ); +#endif + + return FXFALSE; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstControl( GrControl_t code ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grSstControl( %lu )\n", code ); +#endif + if (code == GR_CONTROL_ACTIVATE) + { + RestoreOpenGLWindow(); + } + else if (code == GR_CONTROL_DEACTIVATE) + { + HideOpenGLWindow(); + } + else if (code == GR_CONTROL_RESIZE) + { + } + else if (code == GR_CONTROL_MOVE) + { + } + return code; +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +grSstControlMode( GrControl_t mode ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grSstControlMode( %d )\n", mode ); +#endif + + switch ( mode ) + { + case GR_CONTROL_ACTIVATE: + RestoreOpenGLWindow(); + break; + case GR_CONTROL_DEACTIVATE: + HideOpenGLWindow(); + break; + case GR_CONTROL_RESIZE: + case GR_CONTROL_MOVE: + break; + } + + return FXTRUE; +} + +//************************************************* +//* Return the Value of the graphics status register +//************************************************* +FX_ENTRY FxU32 FX_CALL +grSstStatus( void ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grSstStatus( )\n" ); +#endif + +// FxU32 Status = 0x0FFFF43F; + FxU32 Status = 0x0FFFF03F; + + // Vertical Retrace + Status |= ( ! Glide.State.VRetrace ) << 6; + + return Status; +// Bits +// 5:0 PCI FIFO free space (0x3F = free) +// 6 Vertical Retrace ( 0 = active, 1 = inactive ) +// 7 PixelFx engine busy ( 0 = engine idle ) +// 8 TMU busy ( 0 = engine idle ) +// 9 Voodoo Graphics busy ( 0 = idle ) +// 11:10 Displayed buffer ( 0 = buffer 0, 1 = buffer 1, 2 = auxiliary buffer, 3 = reserved ) +// 27:12 Memory FIFO ( 0xFFFF = FIFO empty ) +// 30:28 Number of swap buffers commands pending +// 31 PCI interrupt generated ( not implemented ) +} + +//************************************************* +//* Returns when Glides is Idle +//************************************************* +FX_ENTRY void FX_CALL +grSstIdle( void ) +{ +#ifdef OGL_DONE + GlideMsg( "grSetIdle( )\n" ); +#endif + + glReportErrors("grSetIdle"); + + RenderDrawTriangles( ); + glFlush( ); + glFinish( ); + glReportError(); +} + diff --git a/MacGLide/OpenGLide/grguSstGlide.h b/MacGLide/OpenGLide/grguSstGlide.h new file mode 100644 index 0000000..8d526cc --- /dev/null +++ b/MacGLide/OpenGLide/grguSstGlide.h @@ -0,0 +1,27 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Sst Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#ifndef GRGUSSTGLIDE_H_ +#define GRGUSSTGLIDE_H_ + +// functions not defined in the SDK but part of either +// - earlier versions of Glide 2.4 +// - Part of the GLide 3 interface +#ifdef __cplusplus +extern "C" { +#endif + FX_ENTRY FxBool FX_CALL grSstControlMode(GrControl_t mode); +#ifdef __cplusplus +} +#endif + +#endif /*GRGUSSTGLIDE_H_*/ diff --git a/MacGLide/OpenGLide/grguTex.cpp b/MacGLide/OpenGLide/grguTex.cpp new file mode 100644 index 0000000..7ae8b85 --- /dev/null +++ b/MacGLide/OpenGLide/grguTex.cpp @@ -0,0 +1,849 @@ +//************************************************************** +//* OpenGLide - Glide to OpenGL Wrapper +//* http://openglide.sourceforge.net +//* +//* Glide Texture Functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "GlideSettings.h" +#include "GLextensions.h" +#include "GLRender.h" +#include "GLRenderUpdateState.h" +#include "PGTexture.h" +#include "PGUTexture.h" + + +// Functions + +//************************************************* +//* Return the lowest start address for texture downloads +//************************************************* +FX_ENTRY FxU32 FX_CALL +grTexMinAddress( GrChipID_t tmu ) +{ +#ifdef OGL_DONE + GlideMsg( "grTexMinAddress( %d ) = 0\n", tmu ); +#endif + + return (FxU32) 0; +} + +//************************************************* +//* Return the highest start address for texture downloads +//************************************************* +FX_ENTRY FxU32 FX_CALL +grTexMaxAddress( GrChipID_t tmu ) +{ +#ifdef OGL_DONE + GlideMsg( "grTexMaxAddress( %d ) = %lu\n", tmu, Glide.TexMemoryMaxPosition ); +#endif + + return (FxU32)( Glide.TexMemoryMaxPosition ); +} + +//************************************************* +//* Specify the current texture source for rendering +//************************************************* +FX_ENTRY void FX_CALL +grTexSource( GrChipID_t tmu, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ) +{ +#ifdef OPTIMISE_GLIDE_STATE_CHANGES + const GrTexInfo* current = Textures->GetCurrentTexInfo(); +#endif + CHECK_STATE_CHANGED(Glide.State.TexSource.StartAddress == startAddress && + Glide.State.TexSource.EvenOdd == evenOdd && + current->aspectRatio == info->aspectRatio && + current->format == info->format && + current->largeLod == info->largeLod && + current->smallLod == info->smallLod); + +#ifdef OGL_PARTDONE + GlideMsg("grTexSource( %d, 0x%x, 0x%x, (%u, %u, ar=%u, fmt=%u) )\n", + tmu, startAddress, evenOdd, + info->smallLod, info->largeLod, info->aspectRatio, info->format); +#endif + + // We're emulating tmu0 only + if ( tmu != GR_TMU0 ) + { + return; + } + +#ifdef OGL_DEBUG + if((startAddress & 7 ) != 0 || startAddress < 0 || startAddress > Glide.TexMemoryMaxPosition) + { + if (startAddress != GR_NULL_MIPMAP_HANDLE) + { + GlideMsg("Warning: grTexSource(%d, %d, %d, xxx) invalid startAddress\n", tmu, startAddress, evenOdd); + } + } +#endif + + RenderDrawTriangles(); + Glide.State.TexSource.StartAddress = startAddress; + Glide.State.TexSource.EvenOdd = evenOdd; + Textures->Source( startAddress, evenOdd, info ); +} + +//************************************************* +//* Return the texture memory consumed by a texture +//************************************************* +FX_ENTRY FxU32 FX_CALL +grTexTextureMemRequired( FxU32 dwEvenOdd, GrTexInfo *texInfo ) +{ +#ifdef OGL_DONE + GlideMsg( "grTexTextureMemRequired( %u, --- )\n", dwEvenOdd ); +#endif + + return Textures->TextureMemRequired( dwEvenOdd, texInfo ); +} + +//************************************************* +//* Return the texture memory consumed by a texture +//************************************************* +FX_ENTRY void FX_CALL +grTexDownloadMipMap( GrChipID_t tmu, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grTexDownloadMipMap(%d, 0x%x, 0x%x, (%u, %u, ar=%u, fmt=%u) )\n", + tmu, startAddress, evenOdd, + info->smallLod, info->largeLod, info->aspectRatio, info->format); +#endif + + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + info->smallLod = info->largeLod; + Textures->DownloadMipMap( startAddress, evenOdd, info ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexDownloadMipMapLevel( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grTexDownloadMipMapLevel( %d, 0x%x, %d, %d, %d, %d, 0x%x, --- )\n", + tmu, startAddress, thisLod, largeLod, aspectRatio, format, evenOdd ); +#endif + + if ( ( tmu != GR_TMU0 ) || ( thisLod != largeLod ) ) + { + return; + } + Textures->DownloadMipMapLevel(startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, data); +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexDownloadMipMapLevelPartial( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data, + int start, + int end ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grTexDownloadMipMapLevelPartial( %d, 0x%x, %d, %d, %d, fmt=%d, 0x%x, ---, %d, %d )\n", + tmu, startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, start, end ); +#endif + if ( ( tmu != GR_TMU0 ) || ( thisLod != largeLod ) ) + { + return; + } + + Textures->DownloadMipMapLevelPartial(startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, data, start, end); +} + +//************************************************* +//* Set the texture map clamping/wrapping mode +//************************************************* +FX_ENTRY void FX_CALL +grTexClampMode( GrChipID_t tmu, + GrTextureClampMode_t s_clampmode, + GrTextureClampMode_t t_clampmode ) +{ + CHECK_STATE_CHANGED( Glide.State.SClampMode == s_clampmode + && Glide.State.TClampMode == t_clampmode); + +#ifdef OGL_DONE + GlideMsg( "grTexClampMode( %d, %d, %d )\n", + tmu, s_clampmode, t_clampmode ); +#endif + + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + Glide.State.SClampMode = s_clampmode; + Glide.State.TClampMode = t_clampmode; + + switch ( s_clampmode ) + { + case GR_TEXTURECLAMP_CLAMP: OpenGL.SClampMode = InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP; break; + case GR_TEXTURECLAMP_WRAP: OpenGL.SClampMode = GL_REPEAT; break; + } + switch ( t_clampmode ) + { + case GR_TEXTURECLAMP_CLAMP: OpenGL.TClampMode = InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP; break; + case GR_TEXTURECLAMP_WRAP: OpenGL.TClampMode = GL_REPEAT; break; + } +} + +void grTexFilterMode_update(GrChipID_t tmu, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode) +{ + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + Glide.State.MinFilterMode = minfilter_mode; + Glide.State.MagFilterMode = magfilter_mode; + // At least on Rage 128 OpenGL Engine 1.1.ATI-5.99, GL_NEAREST_MIPMAP_LINEAR + // and GL_NEAREST_MIPMAP_NEAREST seem to cause textures to not be displayed + // As a result, mipmaps are only available on renderers with EXT_SGIS_generate_mipmap + FxBool mipmapmode = InternalConfig.Mipmapping; // && InternalConfig.EXT_SGIS_generate_mipmap; + switch ( minfilter_mode ) + { + case GR_TEXTUREFILTER_POINT_SAMPLED: + if ( ( Glide.State.MipMapMode != GR_MIPMAP_DISABLE ) && mipmapmode) + { + if ( Glide.State.LodBlend ) + { + OpenGL.MinFilterMode = GL_NEAREST_MIPMAP_LINEAR; + } + else + { + OpenGL.MinFilterMode = GL_NEAREST_MIPMAP_NEAREST; + } + } + else + { + OpenGL.MinFilterMode = GL_NEAREST; + } + break; + + case GR_TEXTUREFILTER_BILINEAR: + if (mipmapmode) + { + if ( Glide.State.LodBlend ) + { + OpenGL.MinFilterMode = GL_LINEAR_MIPMAP_LINEAR; + } + else + { + OpenGL.MinFilterMode = GL_LINEAR_MIPMAP_NEAREST; + } + } + else + { + OpenGL.MinFilterMode = GL_LINEAR; + } + break; + } + switch ( magfilter_mode ) + { + case GR_TEXTUREFILTER_POINT_SAMPLED: + OpenGL.MagFilterMode = GL_NEAREST; + break; + case GR_TEXTUREFILTER_BILINEAR: + OpenGL.MagFilterMode = GL_LINEAR; + break; + } +} + +//************************************************* +//* Set the texture Min/Mag Filter +//************************************************* +FX_ENTRY void FX_CALL +grTexFilterMode( GrChipID_t tmu, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode) +{ + if (InternalConfig.TextureSmoothing) return; + CHECK_STATE_CHANGED(Glide.State.MinFilterMode == minfilter_mode + && Glide.State.MagFilterMode == magfilter_mode); + +#ifdef OGL_PARTDONE + GlideMsg("grTexFilterMode( %d, %d, %d )\n", + tmu, minfilter_mode, magfilter_mode); +#endif + + grTexFilterMode_update(tmu, minfilter_mode, magfilter_mode); +} + + +//************************************************* +//* Set the texture MipMap Mode +//************************************************* +FX_ENTRY void FX_CALL +grTexMipMapMode( GrChipID_t tmu, + GrMipMapMode_t mode, + FxBool lodBlend ) +{ + if (InternalConfig.TextureSmoothing) return; + CHECK_STATE_CHANGED(Glide.State.MipMapMode == mode + && Glide.State.LodBlend == lodBlend); + +#ifdef OGL_PARTDONE + GlideMsg("grTexMipMapMode( %d, %d, %d )\n", + tmu, mode, lodBlend ); +#endif + + if ( tmu != GR_TMU0 ) + { + return; + } + + Glide.State.MipMapMode = mode; + Glide.State.LodBlend = lodBlend; + + grTexFilterMode_update(tmu, + Glide.State.MinFilterMode, + Glide.State.MagFilterMode); +} + +//************************************************* +//* Returns the memory occupied by a texture +//************************************************* +FX_ENTRY FxU32 FX_CALL +grTexCalcMemRequired( GrLOD_t lodmin, GrLOD_t lodmax, + GrAspectRatio_t aspect, GrTextureFormat_t fmt ) +{ +#ifdef OGL_DONE + GlideMsg( "grTexCalcMemRequired( %d, %d, %d, %d )\n", + lodmin, lodmax, aspect, fmt ); +#endif + + static GrTexInfo texInfo; + texInfo.aspectRatio = aspect; + texInfo.format = fmt; + texInfo.largeLod = lodmax; + texInfo.smallLod = lodmin; + + return Textures->TextureMemRequired( 0, &texInfo ); +} + +//************************************************* +//* Download a subset of an NCC table or color palette +//************************************************* +FX_ENTRY void FX_CALL +grTexDownloadTablePartial( GrChipID_t tmu, + GrTexTable_t type, + void *data, + int start, + int end ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grTexDownloadTablePartial( %d, %d, ---, %d, %d )\n", + tmu, type, start, end ); +#endif + + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + Textures->DownloadTable( type, (FxU32*)data, start, end + 1 - start ); +} + +//************************************************* +//* download an NCC table or color palette +//************************************************* +FX_ENTRY void FX_CALL +grTexDownloadTable( GrChipID_t tmu, + GrTexTable_t type, + void *data ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "grTexDownloadTable( %d, %d, --- )\n", tmu, type ); +#endif + + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + Textures->DownloadTable( type, (FxU32*)data, 0, 256 ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexLodBiasValue( GrChipID_t tmu, float bias ) +{ + glReportErrors("grTexLodBiasValue"); + +#ifdef OGL_NOTDONE + GlideMsg( "grTexLodBiasValue( %d, %d )\n", tmu, bias ); +#endif + + if (tmu != GR_TMU0) + { + return; + } + + CHECK_STATE_CHANGED(bias == Glide.State.LodBias); + RenderDrawTriangles(); + + Glide.State.LodBias = bias; + if ( InternalConfig.EXT_texture_lod_bias ) + { + if (OpenGL.ColorAlphaUnit2) + { + for(int unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias); + } + } + else + { + glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias ); + } + } + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexNCCTable( GrChipID_t tmu, GrNCCTable_t NCCTable ) +{ +#ifdef OGL_DONE + GlideMsg( "grTexNCCTable( %d, %u )\n", tmu, NCCTable ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles(); + Textures->NCCTable( NCCTable ); +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexDetailControl( GrChipID_t tmu, + int lod_bias, + FxU8 detail_scale, + float detail_max ) +{ + // CHECK_STATE_CHANGED(...) + +#ifdef OGL_NOTDONE + GlideMsg( "grTexDetailControl( %d, %d, %d, %-4.2f )\n", + tmu, lod_bias, detail_scale, detail_max ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexMultibase( GrChipID_t tmu, + FxBool enable ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grTexMultibase( %d, %d )\n", tmu, enable ); +#endif + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return; + } +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexMultibaseAddress( GrChipID_t tmu, + GrTexBaseRange_t range, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "grTexMultibaseAddress( %d, %d, %lu, %lu, --- )\n", + tmu, range, startAddress, evenOdd ); +#endif +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexCombine( GrChipID_t tmu, + GrCombineFunction_t rgb_function, + GrCombineFactor_t rgb_factor, + GrCombineFunction_t alpha_function, + GrCombineFactor_t alpha_factor, + FxBool rgb_invert, + FxBool alpha_invert ) +{ + CHECK_STATE_CHANGED( Glide.State.TextureCombineCFunction == rgb_function + && Glide.State.TextureCombineCFactor == rgb_factor + && Glide.State.TextureCombineAFunction == alpha_function + && Glide.State.TextureCombineAFactor == alpha_factor + && Glide.State.TextureCombineRGBInvert == rgb_invert + && Glide.State.TextureCombineAInvert == alpha_invert); + +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "grTexCombine( %d, %d, %d, %d, %d, %d, %d )\n", + tmu, rgb_function, rgb_factor, alpha_function, alpha_factor, + rgb_invert, alpha_invert ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return; + } + + RenderDrawTriangles( ); + + if (Glide.State.TextureCombineCFunction != rgb_function || + Glide.State.TextureCombineCFactor != rgb_factor) + { + Glide.State.TextureCombineCFunction = rgb_function; + Glide.State.TextureCombineCFactor = rgb_factor; + SetColorTextureState(); + SetTextureState(); + } + if (Glide.State.TextureCombineAFunction != alpha_function || + Glide.State.TextureCombineAFactor != alpha_factor) + { + Glide.State.TextureCombineAFunction = alpha_function; + Glide.State.TextureCombineAFactor = alpha_factor; + SetAlphaTextureState(); + SetTextureState(); + } + if (Glide.State.TextureCombineRGBInvert != rgb_invert) + { + Glide.State.TextureCombineRGBInvert = rgb_invert; + SetColorCombineState(); + SetAlphaCombineState(); + } + if (Glide.State.TextureCombineAInvert != alpha_invert) + { + Glide.State.TextureCombineAInvert = alpha_invert; + SetAlphaCombineState(); + } +} + +//************************************************* +FX_ENTRY void FX_CALL +grTexCombineFunction( GrChipID_t tmu, GrTextureCombineFnc_t func ) +{ +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "grTexCombineFunction( %d, %d )\n", tmu, func ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return; + } + + switch ( func ) + { + case GR_TEXTURECOMBINE_ZERO: // 0x00 per component + grTexCombine( tmu, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_DECAL: // Clocal decal texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_OTHER: // Cother pass through + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_ADD: // Cother + Clocal additive texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_MULTIPLY: // Cother * Clocal modulated texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_SUBTRACT: // Cother – Clocal subtractive texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_ONE: // 255 0xFF per component + grTexCombine( tmu, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, FXTRUE, FXTRUE ); + break; + +// case GR_TEXTURECOMBINE_DETAIL: // blend (Cother, Clocal) detail textures with detail on selected TMU +// case GR_TEXTURECOMBINE_DETAIL_OTHER: // blend (Cother, Clocal) detail textures with detail on neighboring TMU +// case GR_TEXTURECOMBINE_TRILINEAR_ODD: // blend (Cother, Clocal) LOD blended textures with odd levels on selected TMU +// case GR_TEXTURECOMBINE_TRILINEAR_EVEN: // blend (Cother, Clocal) LOD blended textures with even levels on selected TMU +// break; + } +} + +//************************************************* +//* Return the amount of unallocated texture memory on a Texture Mapping Unit +//************************************************* +FX_ENTRY FxU32 FX_CALL +guTexMemQueryAvail( GrChipID_t tmu ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "guTexMemQueryAvail( %d ) = %u\n", tmu, UTextures.MemQueryAvail( tmu ) ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return 0; + } + + return UTextures.MemQueryAvail( tmu ); +} + +//************************************************* +FX_ENTRY void FX_CALL +guTexCombineFunction( GrChipID_t tmu, GrTextureCombineFnc_t func ) +{ +#if defined( OGL_PARTDONE ) || defined( OGL_COMBINE ) + GlideMsg( "guTexCombineFunction( %d, %d )\n", tmu, func ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return; + } + + switch ( func ) + { + case GR_TEXTURECOMBINE_ZERO: // 0x00 per component + grTexCombine( tmu, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_DECAL: // Clocal decal texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_OTHER: // Cother pass through + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_ADD: // Cother + Clocal additive texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_MULTIPLY: // Cother * Clocal modulated texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_SUBTRACT: // Cother – Clocal subtractive texture + grTexCombine( tmu, GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); + break; + + case GR_TEXTURECOMBINE_ONE: // 255 0xFF per component + grTexCombine( tmu, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_ZERO, FXTRUE, FXTRUE ); + break; + +// case GR_TEXTURECOMBINE_DETAIL: // blend (Cother, Clocal) detail textures with detail on selected TMU +// case GR_TEXTURECOMBINE_DETAIL_OTHER: // blend (Cother, Clocal) detail textures with detail on neighboring TMU +// case GR_TEXTURECOMBINE_TRILINEAR_ODD: // blend (Cother, Clocal) LOD blended textures with odd levels on selected TMU +// case GR_TEXTURECOMBINE_TRILINEAR_EVEN: // blend (Cother, Clocal) LOD blended textures with even levels on selected TMU +// break; + } +} + +//************************************************* +FX_ENTRY GrMipMapId_t FX_CALL +guTexGetCurrentMipMap( GrChipID_t tmu ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexGetCurrentMipMap( %d ) = %d\n", tmu, UTextures.GetCurrentMipMap( tmu ) ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return GR_NULL_MIPMAP_HANDLE; + } + + return UTextures.GetCurrentMipMap( tmu ); +} + +//************************************************* +FX_ENTRY FxBool FX_CALL +guTexChangeAttributes( GrMipMapId_t mmid, + int width, int height, + GrTextureFormat_t fmt, + GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, + GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minFilterMode, + GrTextureFilterMode_t magFilterMode ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexChangeAttributes( %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d )\n", + mmid, width, height, fmt, mm_mode, smallest_lod, largest_lod, aspect, + s_clamp_mode, t_clamp_mode, minFilterMode, magFilterMode ); +#endif + + return UTextures.ChangeAttributes( mmid, width, height, fmt, mm_mode, + smallest_lod, largest_lod, aspect, s_clamp_mode, t_clamp_mode, + minFilterMode, magFilterMode ); +} + +//************************************************* +FX_ENTRY GrMipMapInfo * FX_CALL +guTexGetMipMapInfo( GrMipMapId_t mmid ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexGetMipMapInfo( ) = 0x%p\n" ); +#endif + + return UTextures.GetMipMapInfo( mmid ); +} + +//************************************************* +FX_ENTRY void FX_CALL +guTexMemReset( void ) +{ +#ifdef OGL_PARTDONE + GlideMsg( "guTexMemReset( )\n" ); +#endif + + UTextures.MemReset( ); + Textures->Clear( ); +} + +//************************************************* +FX_ENTRY void FX_CALL +guTexDownloadMipMapLevel( GrMipMapId_t mmid, GrLOD_t lod, const void **src ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexDownloadMipMapLevel( %d, %d, 0x%p )\n", mmid, lod, src ); +#endif + + UTextures.DownloadMipMapLevel( mmid, lod, src ); +} + +//************************************************* +FX_ENTRY void FX_CALL +guTexDownloadMipMap( GrMipMapId_t mmid, const void *src, const GuNccTable *table ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexDownloadMipMap( %d, 0x%p, 0x%p )\n", mmid, src, table ); +#endif + + UTextures.DownloadMipMap( mmid, src, table ); +} + +//************************************************* +FX_ENTRY GrMipMapId_t FX_CALL +guTexAllocateMemory( GrChipID_t tmu, + FxU8 odd_even_mask, + int width, int height, + GrTextureFormat_t fmt, + GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, + GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode, + float lod_bias, + FxBool trilinear ) +{ +#ifdef OGL_DONE + GlideMsg( "guTexAllocateMemory( %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d )\n", + tmu, odd_even_mask, width, height, fmt, mm_mode, smallest_lod, largest_lod, aspect, + s_clamp_mode, t_clamp_mode, minfilter_mode, magfilter_mode, lod_bias, trilinear ); +#endif + + // Ignoring TMU as we are only emulating Glide and assuming a well behaviored program + if ( tmu != GR_TMU0 ) + { + return GR_NULL_MIPMAP_HANDLE; + } + + return UTextures.AllocateMemory( tmu, odd_even_mask, width, height, fmt, mm_mode, + smallest_lod, largest_lod, aspect, s_clamp_mode, t_clamp_mode, + minfilter_mode, magfilter_mode, lod_bias, trilinear ); +} + +//************************************************* +FX_ENTRY void FX_CALL +guTexSource( GrMipMapId_t id ) +{ + // Works because the current id isn't changed in UTextures.Source + // when id is GR_NULL_MIPMAP_HANDLE (todo: this might be a bug) + CHECK_STATE_CHANGED(id == GR_NULL_MIPMAP_HANDLE || id == UTextures.GetCurrentID()); + +#ifdef OGL_DONE + GlideMsg( "guTexSource( %d )\n", id ); +#endif + + RenderDrawTriangles(); + + UTextures.Source( id ); +} + +//************************************************* +FX_ENTRY FxU16 * FX_CALL +guTexCreateColorMipMap( void ) +{ +#ifdef OGL_NOTDONE + GlideMsg( "guTexCreateColorMipMap( ) = NULL\n" ); +#endif + + return NULL; +} + diff --git a/MacGLide/OpenGLide/sdk2_3dfx.h b/MacGLide/OpenGLide/sdk2_3dfx.h new file mode 100644 index 0000000..e8626e9 --- /dev/null +++ b/MacGLide/OpenGLide/sdk2_3dfx.h @@ -0,0 +1,122 @@ +/* +** Copyright (c) 1995, 3Dfx Interactive, Inc. +** All Rights Reserved. +** +** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; +** the contents of this file may not be disclosed to third parties, copied or +** duplicated in any form, in whole or in part, without the prior written +** permission of 3Dfx Interactive, Inc. +** +** RESTRICTED RIGHTS LEGEND: +** Use, duplication or disclosure by the Government is subject to restrictions +** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data +** and Computer Software clause at DFARS 252.227-7013, and/or in similar or +** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - +** rights reserved under the Copyright Laws of the United States. +** +** $Revision: 1.2 $ +** $Date: 2003/11/02 16:29:59 $ +*/ +#ifndef __3DFX_H__ +#define __3DFX_H__ + +/* +** basic data types +*/ +typedef unsigned char FxU8; +typedef signed char FxI8; +typedef unsigned short FxU16; +typedef signed short FxI16; +typedef signed long FxI32; +typedef unsigned long FxU32; +typedef int FxBool; +typedef float FxFloat; +typedef double FxDouble; + +/* +** color types +*/ +typedef unsigned long FxColor_t; +typedef struct { float r, g, b, a; } FxColor4; + +/* +** fundamental types +*/ +#define FXTRUE 1 +#define FXFALSE 0 + +/* +** helper macros +*/ +#define FXUNUSED( a ) ((void)(a)) +#define FXBIT( i ) ( 1L << (i) ) + +/* +** export macros +*/ + +#if defined(CPPDLL) +#define DLLEXPORT extern "C" __declspec(dllexport) +# define FX_ENTRY DLLEXPORT +# define FX_CALL __stdcall +#elif defined(__MSC__) +# if defined (MSVC16) +# define FX_ENTRY +# define FX_CALL +# else +# define FX_ENTRY extern +# define FX_CALL __stdcall +# endif +#elif defined(__WATCOMC__) +# define FX_ENTRY extern +# define FX_CALL __stdcall +#elif defined (__IBMC__) || defined (__IBMCPP__) + /* IBM Visual Age C/C++: */ +# define FX_ENTRY extern +# define FX_CALL __stdcall +#elif defined(__DJGPP__) +# define FX_ENTRY extern +# define FX_CALL +#elif defined(__unix__) +# define FX_ENTRY extern +# define FX_CALL +#elif defined(__MWERKS__) +# if macintosh +# define FX_ENTRY extern +# define FX_CALL +# else /* !macintosh */ +# error "Unknown MetroWerks target platform" +# endif /* !macintosh */ +#else +# warning define FX_ENTRY & FX_CALL for your compiler +# define FX_ENTRY extern +# define FX_CALL +#endif + +/* +** x86 compiler specific stuff +*/ +#if defined(__BORLANDC_) +# define REALMODE + +# define REGW( a, b ) ((a).x.b) +# define REGB( a, b ) ((a).h.b) +# define INT86( a, b, c ) int86(a,b,c) +# define INT86X( a, b, c, d ) int86x(a,b,c,d) + +# define RM_SEG( a ) FP_SEG( a ) +# define RM_OFF( a ) FP_OFF( a ) +#elif defined(__WATCOMC__) +# undef FP_SEG +# undef FP_OFF + +# define REGW( a, b ) ((a).w.b) +# define REGB( a, b ) ((a).h.b) +# define INT86( a, b, c ) int386(a,b,c) +# define INT86X( a, b, c, d ) int386x(a,b,c,d) + +# define RM_SEG( a ) ( ( ( ( FxU32 ) (a) ) & 0x000F0000 ) >> 4 ) +# define RM_OFF( a ) ( ( FxU16 ) (a) ) +#endif + +#endif /* !__3DFX_H__ */ diff --git a/MacGLide/OpenGLide/sdk2_glide.h b/MacGLide/OpenGLide/sdk2_glide.h new file mode 100644 index 0000000..79afecf --- /dev/null +++ b/MacGLide/OpenGLide/sdk2_glide.h @@ -0,0 +1,1515 @@ +/* +** Copyright (c) 1995, 3Dfx Interactive, Inc. +** All Rights Reserved. +** +** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; +** the contents of this file may not be disclosed to third parties, copied or +** duplicated in any form, in whole or in part, without the prior written +** permission of 3Dfx Interactive, Inc. +** +** RESTRICTED RIGHTS LEGEND: +** Use, duplication or disclosure by the Government is subject to restrictions +** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data +** and Computer Software clause at DFARS 252.227-7013, and/or in similar or +** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - +** rights reserved under the Copyright Laws of the United States. +*/ + +/* +** GLIDE.H +** +** The following #defines are relevant when using Glide: +** +** One of the following "platform constants" must be defined during +** compilation: +** +** __DOS__ Defined for 32-bit DOS applications +** __WIN32__ Defined for 32-bit Windows applications +** __sparc__ Defined for Sun Solaris/SunOS +** __linux__ Defined for Linux applications +** __IRIX__ Defined for SGI Irix applications +** +*/ +#ifndef __GLIDE_H__ +#define __GLIDE_H__ + +#include "sdk2_3dfx.h" +#include "sdk2_glidesys.h" +#include "sdk2_sst1vid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** ----------------------------------------------------------------------- +** TYPE DEFINITIONS +** ----------------------------------------------------------------------- +*/ +typedef FxU32 GrColor_t; +typedef FxU8 GrAlpha_t; +typedef FxU32 GrMipMapId_t; +typedef FxU8 GrFog_t; +typedef void (FX_CALL *GrProc)(); + +/* +** ----------------------------------------------------------------------- +** CONSTANTS AND TYPES +** ----------------------------------------------------------------------- +*/ +#define MAX_NUM_SST 4 +#define MAX_MIPMAPS_PER_SST 1024 + +#ifndef GLIDE_LIB +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +#define GR_FOG_TABLE_SIZE 128 +#else /* !(defined(GLIDE3) && defined(GLIDE3_ALPHA)) */ +#define GR_FOG_TABLE_SIZE 64 +#endif /* !(defined(GLIDE3) && defined(GLIDE3_ALPHA)) */ +#endif /* GLIDE_LIB */ + +#define GR_NULL_MIPMAP_HANDLE ((GrMipMapId_t) -1) +#define GR_ZDEPTHVALUE_NEAREST 0xFFFF +#define GR_ZDEPTHVALUE_FARTHEST 0x0000 +#define GR_WDEPTHVALUE_NEAREST 0x0000 +#define GR_WDEPTHVALUE_FARTHEST 0xFFFF + +#define GR_MIPMAPLEVELMASK_EVEN FXBIT(0) +#define GR_MIPMAPLEVELMASK_ODD FXBIT(1) +#define GR_MIPMAPLEVELMASK_BOTH (GR_MIPMAPLEVELMASK_EVEN | GR_MIPMAPLEVELMASK_ODD ) + +#define GR_LODBIAS_BILINEAR 0.5 +#define GR_LODBIAS_TRILINEAR 0.0 + +typedef FxI32 GrChipID_t; +#define GR_TMU0 0x0 +#define GR_TMU1 0x1 +#define GR_TMU2 0x2 +#define GR_FBI 0x3 + +typedef FxI32 GrCombineFunction_t; +#define GR_COMBINE_FUNCTION_ZERO 0x0 +#define GR_COMBINE_FUNCTION_NONE GR_COMBINE_FUNCTION_ZERO +#define GR_COMBINE_FUNCTION_LOCAL 0x1 +#define GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 +#define GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 +#define GR_COMBINE_FUNCTION_BLEND_OTHER GR_COMBINE_FUNCTION_SCALE_OTHER +#define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 +#define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 +#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 +#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 +#define GR_COMBINE_FUNCTION_BLEND GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL +#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 +#define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 +#define GR_COMBINE_FUNCTION_BLEND_LOCAL GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL +#define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 + +typedef FxI32 GrCombineFactor_t; +#define GR_COMBINE_FACTOR_ZERO 0x0 +#define GR_COMBINE_FACTOR_NONE GR_COMBINE_FACTOR_ZERO +#define GR_COMBINE_FACTOR_LOCAL 0x1 +#define GR_COMBINE_FACTOR_OTHER_ALPHA 0x2 +#define GR_COMBINE_FACTOR_LOCAL_ALPHA 0x3 +#define GR_COMBINE_FACTOR_TEXTURE_ALPHA 0x4 +#define GR_COMBINE_FACTOR_TEXTURE_RGB 0x5 +#define GR_COMBINE_FACTOR_DETAIL_FACTOR GR_COMBINE_FACTOR_TEXTURE_ALPHA +#define GR_COMBINE_FACTOR_LOD_FRACTION 0x5 +#define GR_COMBINE_FACTOR_ONE 0x8 +#define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL 0x9 +#define GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA 0xa +#define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA 0xb +#define GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA 0xc +#define GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA +#define GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION 0xd + + +typedef FxI32 GrCombineLocal_t; +#define GR_COMBINE_LOCAL_ITERATED 0x0 +#define GR_COMBINE_LOCAL_CONSTANT 0x1 +#define GR_COMBINE_LOCAL_NONE GR_COMBINE_LOCAL_CONSTANT +#define GR_COMBINE_LOCAL_DEPTH 0x2 + +typedef FxI32 GrCombineOther_t; +#define GR_COMBINE_OTHER_ITERATED 0x0 +#define GR_COMBINE_OTHER_TEXTURE 0x1 +#define GR_COMBINE_OTHER_CONSTANT 0x2 +#define GR_COMBINE_OTHER_NONE GR_COMBINE_OTHER_CONSTANT + + +typedef FxI32 GrAlphaSource_t; +#define GR_ALPHASOURCE_CC_ALPHA 0x0 +#define GR_ALPHASOURCE_ITERATED_ALPHA 0x1 +#define GR_ALPHASOURCE_TEXTURE_ALPHA 0x2 +#define GR_ALPHASOURCE_TEXTURE_ALPHA_TIMES_ITERATED_ALPHA 0x3 + + +typedef FxI32 GrColorCombineFnc_t; +#define GR_COLORCOMBINE_ZERO 0x0 +#define GR_COLORCOMBINE_CCRGB 0x1 +#define GR_COLORCOMBINE_ITRGB 0x2 +#define GR_COLORCOMBINE_ITRGB_DELTA0 0x3 +#define GR_COLORCOMBINE_DECAL_TEXTURE 0x4 +#define GR_COLORCOMBINE_TEXTURE_TIMES_CCRGB 0x5 +#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB 0x6 +#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_DELTA0 0x7 +#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_ADD_ALPHA 0x8 +#define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA 0x9 +#define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA_ADD_ITRGB 0xa +#define GR_COLORCOMBINE_TEXTURE_ADD_ITRGB 0xb +#define GR_COLORCOMBINE_TEXTURE_SUB_ITRGB 0xc +#define GR_COLORCOMBINE_CCRGB_BLEND_ITRGB_ON_TEXALPHA 0xd +#define GR_COLORCOMBINE_DIFF_SPEC_A 0xe +#define GR_COLORCOMBINE_DIFF_SPEC_B 0xf +#define GR_COLORCOMBINE_ONE 0x10 + +typedef FxI32 GrAlphaBlendFnc_t; +#define GR_BLEND_ZERO 0x0 +#define GR_BLEND_SRC_ALPHA 0x1 +#define GR_BLEND_SRC_COLOR 0x2 +#define GR_BLEND_DST_COLOR GR_BLEND_SRC_COLOR +#define GR_BLEND_DST_ALPHA 0x3 +#define GR_BLEND_ONE 0x4 +#define GR_BLEND_ONE_MINUS_SRC_ALPHA 0x5 +#define GR_BLEND_ONE_MINUS_SRC_COLOR 0x6 +#define GR_BLEND_ONE_MINUS_DST_COLOR GR_BLEND_ONE_MINUS_SRC_COLOR +#define GR_BLEND_ONE_MINUS_DST_ALPHA 0x7 +#define GR_BLEND_RESERVED_8 0x8 +#define GR_BLEND_RESERVED_9 0x9 +#define GR_BLEND_RESERVED_A 0xa +#define GR_BLEND_RESERVED_B 0xb +#define GR_BLEND_RESERVED_C 0xc +#define GR_BLEND_RESERVED_D 0xd +#define GR_BLEND_RESERVED_E 0xe +#define GR_BLEND_ALPHA_SATURATE 0xf +#define GR_BLEND_PREFOG_COLOR GR_BLEND_ALPHA_SATURATE + +typedef FxI32 GrAspectRatio_t; +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +//#define GLIDE3_DEBUG +#ifdef GLIDE3_DEBUG +#define GR_ASPECT_8x1 0x0 /* 8W x 1H */ +#define GR_ASPECT_4x1 0x1 /* 4W x 1H */ +#define GR_ASPECT_2x1 0x2 /* 2W x 1H */ +#define GR_ASPECT_1x1 0x3 /* 1W x 1H */ +#define GR_ASPECT_1x2 0x4 /* 1W x 2H */ +#define GR_ASPECT_1x4 0x5 /* 1W x 4H */ +#define GR_ASPECT_1x8 0x6 /* 1W x 8H */ +#else +#define GR_ASPECT_8x1 3 /* 8W x 1H */ +#define GR_ASPECT_4x1 2 /* 4W x 1H */ +#define GR_ASPECT_2x1 1 /* 2W x 1H */ +#define GR_ASPECT_1x1 0 /* 1W x 1H */ +#define GR_ASPECT_1x2 -1 /* 1W x 2H */ +#define GR_ASPECT_1x4 -2 /* 1W x 4H */ +#define GR_ASPECT_1x8 -3 /* 1W x 8H */ +#endif /* GLIDE3_DEBUG */ +#else +#define GR_ASPECT_8x1 0x0 /* 8W x 1H */ +#define GR_ASPECT_4x1 0x1 /* 4W x 1H */ +#define GR_ASPECT_2x1 0x2 /* 2W x 1H */ +#define GR_ASPECT_1x1 0x3 /* 1W x 1H */ +#define GR_ASPECT_1x2 0x4 /* 1W x 2H */ +#define GR_ASPECT_1x4 0x5 /* 1W x 4H */ +#define GR_ASPECT_1x8 0x6 /* 1W x 8H */ +#endif + +typedef FxI32 GrBuffer_t; +#define GR_BUFFER_FRONTBUFFER 0x0 +#define GR_BUFFER_BACKBUFFER 0x1 +#define GR_BUFFER_AUXBUFFER 0x2 +#define GR_BUFFER_DEPTHBUFFER 0x3 +#define GR_BUFFER_ALPHABUFFER 0x4 +#define GR_BUFFER_TRIPLEBUFFER 0x5 + +typedef FxI32 GrChromakeyMode_t; +#define GR_CHROMAKEY_DISABLE 0x0 +#define GR_CHROMAKEY_ENABLE 0x1 + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +typedef FxI32 GrChromaRangeMode_t; +#define GR_CHROMARANGE_RGB_ANY 0x0 +#define GR_CHROMARANGE_RGb_ANY 0x1 +#define GR_CHROMARANGE_RgB_ANY 0x2 +#define GR_CHROMARANGE_Rgb_ANY 0x3 +#define GR_CHROMARANGE_rGB_ANY 0x4 +#define GR_CHROMARANGE_rGb_ANY 0x5 +#define GR_CHROMARANGE_rgB_ANY 0x6 +#define GR_CHROMARANGE_rgb_ANY 0x7 +#define GR_CHROMARANGE_RGB_ALL 0x8 +#define GR_CHROMARANGE_RGb_ALL 0x9 +#define GR_CHROMARANGE_RgB_ALL 0xa +#define GR_CHROMARANGE_Rgb_ALL 0xb +#define GR_CHROMARANGE_rGB_ALL 0xc +#define GR_CHROMARANGE_rGb_ALL 0xd +#define GR_CHROMARANGE_rgB_ALL 0xe +#define GR_CHROMARANGE_rgb_ALL 0xf +#endif + +typedef FxI32 GrCmpFnc_t; +#define GR_CMP_NEVER 0x0 +#define GR_CMP_LESS 0x1 +#define GR_CMP_EQUAL 0x2 +#define GR_CMP_LEQUAL 0x3 +#define GR_CMP_GREATER 0x4 +#define GR_CMP_NOTEQUAL 0x5 +#define GR_CMP_GEQUAL 0x6 +#define GR_CMP_ALWAYS 0x7 + +typedef FxI32 GrColorFormat_t; +#define GR_COLORFORMAT_ARGB 0x0 +#define GR_COLORFORMAT_ABGR 0x1 + +#define GR_COLORFORMAT_RGBA 0x2 +#define GR_COLORFORMAT_BGRA 0x3 + +typedef FxI32 GrCullMode_t; +#define GR_CULL_DISABLE 0x0 +#define GR_CULL_NEGATIVE 0x1 +#define GR_CULL_POSITIVE 0x2 + +typedef FxI32 GrDepthBufferMode_t; +#define GR_DEPTHBUFFER_DISABLE 0x0 +#define GR_DEPTHBUFFER_ZBUFFER 0x1 +#define GR_DEPTHBUFFER_WBUFFER 0x2 +#define GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS 0x3 +#define GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS 0x4 + +typedef FxI32 GrDitherMode_t; +#define GR_DITHER_DISABLE 0x0 +#define GR_DITHER_2x2 0x1 +#define GR_DITHER_4x4 0x2 + +typedef FxI32 GrFogMode_t; +#define GR_FOG_DISABLE 0x0 +#define GR_FOG_WITH_ITERATED_ALPHA 0x1 +#define GR_FOG_WITH_TABLE 0x2 +#define GR_FOG_WITH_ITERATED_Z 0x3 /* Bug 735 */ +#define GR_FOG_MULT2 0x100 +#define GR_FOG_ADD2 0x200 + +typedef FxU32 GrLock_t; +#define GR_LFB_READ_ONLY 0x00 +#define GR_LFB_WRITE_ONLY 0x01 +#define GR_LFB_IDLE 0x00 +#define GR_LFB_NOIDLE 0x10 + +typedef FxI32 GrLfbBypassMode_t; +#define GR_LFBBYPASS_DISABLE 0x0 +#define GR_LFBBYPASS_ENABLE 0x1 + +typedef FxI32 GrLfbWriteMode_t; +#define GR_LFBWRITEMODE_565 0x0 /* RGB:RGB */ +#define GR_LFBWRITEMODE_555 0x1 /* RGB:RGB */ +#define GR_LFBWRITEMODE_1555 0x2 /* ARGB:ARGB */ +#define GR_LFBWRITEMODE_RESERVED1 0x3 +#define GR_LFBWRITEMODE_888 0x4 /* RGB */ +#define GR_LFBWRITEMODE_8888 0x5 /* ARGB */ +#define GR_LFBWRITEMODE_RESERVED2 0x6 +#define GR_LFBWRITEMODE_RESERVED3 0x7 +#define GR_LFBWRITEMODE_RESERVED4 0x8 +#define GR_LFBWRITEMODE_RESERVED5 0x9 +#define GR_LFBWRITEMODE_RESERVED6 0xa +#define GR_LFBWRITEMODE_RESERVED7 0xb +#define GR_LFBWRITEMODE_565_DEPTH 0xc /* RGB:DEPTH */ +#define GR_LFBWRITEMODE_555_DEPTH 0xd /* RGB:DEPTH */ +#define GR_LFBWRITEMODE_1555_DEPTH 0xe /* ARGB:DEPTH */ +#define GR_LFBWRITEMODE_ZA16 0xf /* DEPTH:DEPTH */ +#define GR_LFBWRITEMODE_ANY 0xFF + + +typedef FxI32 GrOriginLocation_t; +#define GR_ORIGIN_UPPER_LEFT 0x0 +#define GR_ORIGIN_LOWER_LEFT 0x1 +#define GR_ORIGIN_ANY 0xFF + +typedef struct { + int size; + void *lfbPtr; + FxU32 strideInBytes; + GrLfbWriteMode_t writeMode; + GrOriginLocation_t origin; +} GrLfbInfo_t; + +typedef FxI32 GrLOD_t; +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +#ifdef GLIDE3_DEBUG +#define GR_LOD_256 0x0 +#define GR_LOD_128 0x1 +#define GR_LOD_64 0x2 +#define GR_LOD_32 0x3 +#define GR_LOD_16 0x4 +#define GR_LOD_8 0x5 +#define GR_LOD_4 0x6 +#define GR_LOD_2 0x7 +#define GR_LOD_1 0x8 +#else +#define GR_LOD_256 0x8 +#define GR_LOD_128 0x7 +#define GR_LOD_64 0x6 +#define GR_LOD_32 0x5 +#define GR_LOD_16 0x4 +#define GR_LOD_8 0x3 +#define GR_LOD_4 0x2 +#define GR_LOD_2 0x1 +#define GR_LOD_1 0x0 +#endif /* GLIDE3_DEBUG */ +#else +#define GR_LOD_256 0x0 +#define GR_LOD_128 0x1 +#define GR_LOD_64 0x2 +#define GR_LOD_32 0x3 +#define GR_LOD_16 0x4 +#define GR_LOD_8 0x5 +#define GR_LOD_4 0x6 +#define GR_LOD_2 0x7 +#define GR_LOD_1 0x8 +#endif + +typedef FxI32 GrMipMapMode_t; +#define GR_MIPMAP_DISABLE 0x0 /* no mip mapping */ +#define GR_MIPMAP_NEAREST 0x1 /* use nearest mipmap */ +#define GR_MIPMAP_NEAREST_DITHER 0x2 /* GR_MIPMAP_NEAREST + LOD dith */ + + +typedef FxI32 GrSmoothingMode_t; +#define GR_SMOOTHING_DISABLE 0x0 +#define GR_SMOOTHING_ENABLE 0x1 + +typedef FxI32 GrTextureClampMode_t; +#define GR_TEXTURECLAMP_WRAP 0x0 +#define GR_TEXTURECLAMP_CLAMP 0x1 + +typedef FxI32 GrTextureCombineFnc_t; +#define GR_TEXTURECOMBINE_ZERO 0x0 /* texout = 0 */ +#define GR_TEXTURECOMBINE_DECAL 0x1 /* texout = texthis */ +#define GR_TEXTURECOMBINE_OTHER 0x2 /* this TMU in passthru mode */ +#define GR_TEXTURECOMBINE_ADD 0x3 /* tout = tthis + t(this+1) */ +#define GR_TEXTURECOMBINE_MULTIPLY 0x4 /* texout = tthis * t(this+1) */ +#define GR_TEXTURECOMBINE_SUBTRACT 0x5 /* Sutract from upstream TMU */ +#define GR_TEXTURECOMBINE_DETAIL 0x6 /* detail--detail on tthis */ +#define GR_TEXTURECOMBINE_DETAIL_OTHER 0x7 /* detail--detail on tthis+1 */ +#define GR_TEXTURECOMBINE_TRILINEAR_ODD 0x8 /* trilinear--odd levels tthis*/ +#define GR_TEXTURECOMBINE_TRILINEAR_EVEN 0x9 /*trilinear--even levels tthis*/ +#define GR_TEXTURECOMBINE_ONE 0xa /* texout = 0xFFFFFFFF */ + +typedef FxI32 GrTextureFilterMode_t; +#define GR_TEXTUREFILTER_POINT_SAMPLED 0x0 +#define GR_TEXTUREFILTER_BILINEAR 0x1 + +typedef FxI32 GrTextureFormat_t; +#define GR_TEXFMT_8BIT 0x0 +#define GR_TEXFMT_RGB_332 GR_TEXFMT_8BIT +#define GR_TEXFMT_YIQ_422 0x1 +#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ +#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ +#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4 +#define GR_TEXFMT_P_8 0x5 /* 8-bit palette */ +#define GR_TEXFMT_RSVD0 0x6 +#define GR_TEXFMT_RSVD1 0x7 +#define GR_TEXFMT_16BIT 0x8 +#define GR_TEXFMT_ARGB_8332 GR_TEXFMT_16BIT +#define GR_TEXFMT_AYIQ_8422 0x9 +#define GR_TEXFMT_RGB_565 0xa +#define GR_TEXFMT_ARGB_1555 0xb +#define GR_TEXFMT_ARGB_4444 0xc +#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd +#define GR_TEXFMT_AP_88 0xe /* 8-bit alpha 8-bit palette */ +#define GR_TEXFMT_RSVD2 0xf + +typedef FxU32 GrTexTable_t; +#define GR_TEXTABLE_NCC0 0x0 +#define GR_TEXTABLE_NCC1 0x1 +#define GR_TEXTABLE_PALETTE 0x2 + +typedef FxU32 GrNCCTable_t; +#define GR_NCCTABLE_NCC0 0x0 +#define GR_NCCTABLE_NCC1 0x1 + +typedef FxU32 GrTexBaseRange_t; +#define GR_TEXBASE_256 0x0 +#define GR_TEXBASE_128 0x1 +#define GR_TEXBASE_64 0x2 +#define GR_TEXBASE_32_TO_1 0x3 + +#ifdef GLIDE3 + +#define GLIDE3_VERTEX_LAYOUT 1 + +typedef FxU32 GrEnableMode_t; +#define GR_MODE_DISABLE 0x0 +#define GR_MODE_ENABLE 0x1 + +#define GR_AA_ORDERED 0x01 +#define GR_ALLOW_MIPMAP_DITHER 0x02 +#define GR_SHAMELESS_PLUG 0x03 +#define GR_VIDEO_SMOOTHING 0x04 + +typedef FxU32 GrCoordinateSpaceMode_t; +#define GR_WINDOW_COORDS 0x00 +#define GR_CLIP_COORDS 0x01 + +#endif + +#ifdef GLIDE3 +#ifdef GLIDE3_ALPHA +#define GLIDE3_EXTRA_STATE 392 +#else +#define GLIDE3_EXTRA_STATE 216 +#endif +#else +#define GLIDE3_EXTRA_STATE 0 +#endif + +#define GLIDE_STATE_PAD_SIZE 312 + GLIDE3_EXTRA_STATE + +#ifdef GLIDE_LIB +typedef struct _GrState_s GrState; +#else +typedef struct _GrState_s { + char pad[GLIDE_STATE_PAD_SIZE]; +} GrState; +#endif + +#ifdef GLIDE3 +/* Types of data in strips */ +#define GR_FLOAT 0 +#define GR_U8 1 + +/* Parameters for strips */ +#define GR_PARAM_XY 0x01 +#define GR_PARAM_Z 0x02 +#define GR_PARAM_W 0x03 +#define GR_PARAM_Q 0x04 + +#define GR_PARAM_A 0x10 +#define GR_PARAM_A0 GR_PARAM_A +#define GR_PARAM_A1 GR_PARAM_A+1 +#define GR_PARAM_A2 GR_PARAM_A+2 +#define GR_PARAM_A3 GR_PARAM_A+3 +#define GR_PARAM_A4 GR_PARAM_A+4 +#define GR_PARAM_A5 GR_PARAM_A+5 +#define GR_PARAM_A6 GR_PARAM_A+6 +#define GR_PARAM_A7 GR_PARAM_A+7 + +#define GR_PARAM_RGB 0x20 +#define GR_PARAM_RGB0 GR_PARAM_RGB +#define GR_PARAM_RGB1 GR_PARAM_RGB+1 +#define GR_PARAM_RGB2 GR_PARAM_RGB+2 +#define GR_PARAM_RGB3 GR_PARAM_RGB+3 +#define GR_PARAM_RGB4 GR_PARAM_RGB+4 +#define GR_PARAM_RGB5 GR_PARAM_RGB+5 +#define GR_PARAM_RGB6 GR_PARAM_RGB+6 +#define GR_PARAM_RGB7 GR_PARAM_RGB+7 + +#define GR_PARAM_PARGB 0x30 +#define GR_PARAM_PARGB0 GR_PARAM_PARGB +#define GR_PARAM_PARGB1 GR_PARAM_PARGB+1 +#define GR_PARAM_PARGB2 GR_PARAM_PARGB+2 +#define GR_PARAM_PARGB3 GR_PARAM_PARGB+3 +#define GR_PARAM_PARGB4 GR_PARAM_PARGB+4 +#define GR_PARAM_PARGB5 GR_PARAM_PARGB+5 +#define GR_PARAM_PARGB6 GR_PARAM_PARGB+6 +#define GR_PARAM_PARGB7 GR_PARAM_PARGB+7 + +#define GR_PARAM_ST0 0x40 +#define GR_PARAM_ST1 GR_PARAM_ST0+1 +#define GR_PARAM_ST2 GR_PARAM_ST0+2 +#define GR_PARAM_ST3 GR_PARAM_ST0+3 +#define GR_PARAM_ST4 GR_PARAM_ST0+4 +#define GR_PARAM_ST5 GR_PARAM_ST0+5 +#define GR_PARAM_ST6 GR_PARAM_ST0+6 +#define GR_PARAM_ST7 GR_PARAM_ST0+7 + +#define GR_PARAM_Q0 0x50 +#define GR_PARAM_Q1 GR_PARAM_Q0+1 +#define GR_PARAM_Q2 GR_PARAM_Q0+2 +#define GR_PARAM_Q3 GR_PARAM_Q0+3 +#define GR_PARAM_Q4 GR_PARAM_Q0+4 +#define GR_PARAM_Q5 GR_PARAM_Q0+5 +#define GR_PARAM_Q6 GR_PARAM_Q0+6 +#define GR_PARAM_Q7 GR_PARAM_Q0+7 + +#define GR_PARAM_DISABLE 0x00 +#define GR_PARAM_ENABLE 0x01 + +/* Componenets for strips */ +/* vertex */ +#define GR_VERTEX_XYZ 3 +#define GR_VERTEX_XYZW 4 +/* Color */ +#define GR_COLOR_RGB 3 +#define GR_COLOR_RGBA 4 +/* Texture */ +#define GR_TEX_NONE 0 +#define GR_TEX_ST 2 +#define GR_TEX_STW 3 + +/* grDrawVertexArray primitive type */ +#define GR_POINTS 0 +#define GR_LINE_STRIP 1 +#define GR_LINES 2 +#define GR_POLYGON 3 +#define GR_TRIANGLE_STRIP 4 +#define GR_TRIANGLE_FAN 5 +#define GR_TRIANGLES 6 + + +/* Stuff for grGet/grReset */ +#define GR_BITS_DEPTH 0x01 +#define GR_BITS_RGBA 0x02 +#define GR_FIFO_FULLNESS 0x03 +#define GR_FOG_TABLE_ENTRIES 0x04 +#define GR_GAMMA_TABLE_ENTRIES 0x05 +#define GR_IS_BUSY 0x06 +#define GR_LFB_PIXEL_PIPE 0x07 +#define GR_MAX_TEXTURE_SIZE 0x08 +#define GR_MAX_TEXTURE_ASPECT_RATIO 0x09 +#define GR_MEMORY_FB 0x0a +#define GR_MEMORY_TMU 0x0b +#define GR_MEMORY_UMA 0x0c +#define GR_NUM_BOARDS 0x0d +#define GR_NUM_POWER_OF_TWO_TEXTURES 0x0e +#define GR_NUM_FB 0x0f +#define GR_NUM_TMU 0x10 +#define GR_PENDING_BUFFERSWAPS 0x11 +#define GR_REVISION_FB 0x12 +#define GR_REVISION_TMU 0x13 +#define GR_STATS_LINES 0x14 /* grSet/grReset */ +#define GR_STATS_PIXELS_AFUNC_FAIL 0x15 +#define GR_STATS_PIXELS_CHROMA_FAIL 0x16 +#define GR_STATS_PIXELS_DEPTHFUNC_FAIL 0x17 +#define GR_STATS_PIXELS_IN 0x18 +#define GR_STATS_PIXELS_OUT 0x19 +#define GR_STATS_PIXELS 0x1a /* grReset */ +#define GR_STATS_POINTS 0x1b /* grSet/grReset */ +#define GR_STATS_TRIANGLES_IN 0x1c +#define GR_STATS_TRIANGLES_OUT 0x1d +#define GR_STATS_TRIANGLES 0x1e /* grReset */ +#define GR_SWAP_HISTORY 0x1f +#define GR_TEXTURE_ALIGN 0x20 +#define GR_VIDEO_POSITION 0x21 +#define GR_VIEWPORT 0x22 +#define GR_WDEPTH_MIN_MAX 0x23 +#define GR_ZDEPTH_MIN_MAX 0x24 + +/* stuff for grGetString */ +#define GR_EXTENSION 0xa0 +#define GR_HARDWARE 0xa1 +#define GR_RENDERER 0xa2 +#define GR_VENDOR 0xa3 +#define GR_VERSION 0xa4 + +#endif + +/* +** ----------------------------------------------------------------------- +** STRUCTURES +** ----------------------------------------------------------------------- +*/ + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +#ifdef GLIDE3_DEBUG +typedef struct { + GrLOD_t smallLod; + GrLOD_t largeLod; + GrAspectRatio_t aspectRatio; + GrTextureFormat_t format; + void *data; +} GrTexInfo; +#else +typedef struct { + GrLOD_t smallLodLog2; + GrLOD_t largeLodLog2; + GrAspectRatio_t aspectRatioLog2; + GrTextureFormat_t format; + void *data; +} GrTexInfo; +#endif /* GLIDE3_DEBUG */ +#else +typedef struct { + GrLOD_t smallLod; + GrLOD_t largeLod; + GrAspectRatio_t aspectRatio; + GrTextureFormat_t format; + void *data; +} GrTexInfo; +#endif + +#ifndef GLIDE3_ALPHA +/* +** 3DF texture file structs +*/ + +typedef struct +{ + FxU32 width, height; + int small_lod, large_lod; + GrAspectRatio_t aspect_ratio; + GrTextureFormat_t format; +} Gu3dfHeader; + +typedef struct +{ + FxU8 yRGB[16]; + FxI16 iRGB[4][3]; + FxI16 qRGB[4][3]; + FxU32 packed_data[12]; +} GuNccTable; + +typedef struct { + FxU32 data[256]; +} GuTexPalette; + +typedef union { + GuNccTable nccTable; + GuTexPalette palette; +} GuTexTable; + +typedef struct +{ + Gu3dfHeader header; + GuTexTable table; + void *data; + FxU32 mem_required; /* memory required for mip map in bytes. */ +} Gu3dfInfo; + +typedef struct +{ + int sst; /* SST where this texture map was stored */ + FxBool valid; /* set when this table entry is allocated*/ + int width, height; + GrAspectRatio_t aspect_ratio; /* aspect ratio of the mip map. */ + void *data; /* actual texture data */ + + GrTextureFormat_t format; /* format of the texture table */ + GrMipMapMode_t mipmap_mode; /* mip map mode for this texture */ + GrTextureFilterMode_t magfilter_mode; /* filtering to be used when magnified */ + GrTextureFilterMode_t minfilter_mode; /* filtering to be used with minified */ + GrTextureClampMode_t s_clamp_mode; /* how this texture should be clamped in s */ + GrTextureClampMode_t t_clamp_mode; /* how this texture should be clamped in t */ + FxU32 tLOD; /* Register value for tLOD register */ + FxU32 tTextureMode; /* Register value for tTextureMode register + not including non-texture specific bits */ + FxU32 lod_bias; /* LOD bias of the mip map in preshifted 4.2*/ + GrLOD_t lod_min, lod_max; /* largest and smallest levels of detail */ + int tmu; /* tmu on which this texture resides */ + FxU32 odd_even_mask; /* mask specifying levels on this tmu */ + FxU32 tmu_base_address; /* base addr (in TMU mem) of this texture */ + FxBool trilinear; /* should we blend by lod? */ + + GuNccTable ncc_table; /* NCC compression table (optional) */ +} GrMipMapInfo; +#endif + +typedef int GrSstType; +#define GR_SSTTYPE_VOODOO 0 +#define GR_SSTTYPE_SST96 1 +#define GR_SSTTYPE_AT3D 2 +#define GR_SSTTYPE_Voodoo2 3 + +typedef struct GrTMUConfig_St { + int tmuRev; /* Rev of Texelfx chip */ + int tmuRam; /* 1, 2, or 4 MB */ +} GrTMUConfig_t; + +typedef struct GrVoodooConfig_St { + int fbRam; /* 1, 2, or 4 MB */ + int fbiRev; /* Rev of Pixelfx chip */ + int nTexelfx; /* How many texelFX chips are there? */ + FxBool sliDetect; /* Is it a scan-line interleaved board? */ + GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */ +} GrVoodooConfig_t; + +typedef struct GrSst96Config_St { + int fbRam; /* How much? */ + int nTexelfx; + GrTMUConfig_t tmuConfig; +} GrSst96Config_t; + +typedef GrVoodooConfig_t GrVoodoo2Config_t; + +typedef struct GrAT3DConfig_St { + int rev; +} GrAT3DConfig_t; + +typedef struct { + int num_sst; /* # of HW units in the system */ + struct { + GrSstType type; /* Which hardware is it? */ + union SstBoard_u { + GrVoodooConfig_t VoodooConfig; + GrSst96Config_t SST96Config; + GrAT3DConfig_t AT3DConfig; + GrVoodoo2Config_t Voodoo2Config; + } sstBoard; + } SSTs[MAX_NUM_SST]; /* configuration for each board */ +} GrHwConfiguration; + +typedef struct GrSstPerfStats_s { + FxU32 pixelsIn; /* # pixels processed (minus buffer clears) */ + FxU32 chromaFail; /* # pixels not drawn due to chroma key */ + FxU32 zFuncFail; /* # pixels not drawn due to Z comparison */ + FxU32 aFuncFail; /* # pixels not drawn due to alpha comparison */ + FxU32 pixelsOut; /* # pixels drawn (including buffer clears) */ +} GrSstPerfStats_t; + + +typedef struct { + float sow; /* s texture ordinate (s over w) */ + float tow; /* t texture ordinate (t over w) */ + float oow; /* 1/w (used mipmapping - really 0xfff/w) */ +} GrTmuVertex; + +/* +** GrVertex +** If these are changed the C & assembly language trisetup routines MUST +** be changed, for they will no longer work. +*/ +#if !GLIDE3_VERTEX_LAYOUT +typedef struct +{ + float x, y, z; /* X, Y, and Z of scrn space -- Z is ignored */ + float r, g, b; /* R, G, B, ([0..255.0]) */ + float ooz; /* 65535/Z (used for Z-buffering) */ + float a; /* Alpha [0..255.0] */ + float oow; /* 1/W (used for W-buffering, texturing) */ + GrTmuVertex tmuvtx[GLIDE_NUM_TMU]; +} GrVertex; + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 1 +#define GR_VERTEX_Z_OFFSET 2 +#define GR_VERTEX_R_OFFSET 3 +#define GR_VERTEX_G_OFFSET 4 +#define GR_VERTEX_B_OFFSET 5 +#define GR_VERTEX_OOZ_OFFSET 6 +#define GR_VERTEX_A_OFFSET 7 +#define GR_VERTEX_OOW_OFFSET 8 + +#else /* GLIDE3_VERTEX_LAYOUT */ +typedef struct +{ + float x, y; /* X and Y in screen space */ + float ooz; /* 65535/Z (used for Z-buffering) */ + float oow; /* 1/W (used for W-buffering, texturing) */ + float r, g, b, a; /* R, G, B, A [0..255.0] */ + float z; /* Z is ignored */ + GrTmuVertex tmuvtx[GLIDE_NUM_TMU]; +} GrVertex; + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 1 +#define GR_VERTEX_OOZ_OFFSET 2 +#define GR_VERTEX_OOW_OFFSET 3 +#define GR_VERTEX_R_OFFSET 4 +#define GR_VERTEX_G_OFFSET 5 +#define GR_VERTEX_B_OFFSET 6 +#define GR_VERTEX_A_OFFSET 7 +#define GR_VERTEX_Z_OFFSET 8 + +#endif /* GLIDE3_VERTEX_LAYOUT */ + +#define GR_VERTEX_SOW_TMU0_OFFSET 9 +#define GR_VERTEX_TOW_TMU0_OFFSET 10 +#define GR_VERTEX_OOW_TMU0_OFFSET 11 +#define GR_VERTEX_SOW_TMU1_OFFSET 12 +#define GR_VERTEX_TOW_TMU1_OFFSET 13 +#define GR_VERTEX_OOW_TMU1_OFFSET 14 + +#if (GLIDE_NUM_TMU > 2) +#define GR_VERTEX_SOW_TMU2_OFFSET 15 +#define GR_VERTEX_TOW_TMU2_OFFSET 16 +#define GR_VERTEX_OOW_TMU2_OFFSET 17 +#endif + +typedef FxU32 GrLfbSrcFmt_t; +#define GR_LFB_SRC_FMT_565 0x00 +#define GR_LFB_SRC_FMT_555 0x01 +#define GR_LFB_SRC_FMT_1555 0x02 +#define GR_LFB_SRC_FMT_888 0x04 +#define GR_LFB_SRC_FMT_8888 0x05 +#define GR_LFB_SRC_FMT_565_DEPTH 0x0c +#define GR_LFB_SRC_FMT_555_DEPTH 0x0d +#define GR_LFB_SRC_FMT_1555_DEPTH 0x0e +#define GR_LFB_SRC_FMT_ZA16 0x0f +#define GR_LFB_SRC_FMT_RLE16 0x80 + +typedef FxI32 GrPassthruMode_t; +#define GR_PASSTHRU_SHOW_VGA 0x0 +#define GR_PASSTHRU_SHOW_SST1 0x1 + +typedef FxU32 GrHint_t; +#define GR_HINTTYPE_MIN 0 +#define GR_HINT_STWHINT 0 +#define GR_HINT_FIFOCHECKHINT 1 +#define GR_HINT_FPUPRECISION 2 +#define GR_HINT_ALLOW_MIPMAP_DITHER 3 +#define GR_HINT_LFB_WRITE 4 +#define GR_HINT_LFB_PROTECT 5 +#define GR_HINT_LFB_RESET 6 +#define GR_HINTTYPE_MAX GR_HINT_LFB_RESET +#ifdef H3D +#define GR_HINT_H3DENABLE GR_HINTTYPE_MAX +#undef GR_HINTTYPE_MAX +#define GR_HINTTYPE_MAX GR_HIT_H3DENABLE +#endif + +typedef FxU32 GrSTWHint_t; +#define GR_STWHINT_W_DIFF_FBI FXBIT(0) +#define GR_STWHINT_W_DIFF_TMU0 FXBIT(1) +#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2) +#define GR_STWHINT_W_DIFF_TMU1 FXBIT(3) +#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4) +#define GR_STWHINT_W_DIFF_TMU2 FXBIT(5) +#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6) + +typedef FxU32 GrControl_t; +#define GR_CONTROL_ACTIVATE 0x1 +#define GR_CONTROL_DEACTIVATE 0x2 +#define GR_CONTROL_RESIZE 0x3 +#define GR_CONTROL_MOVE 0x4 + +#define GR_GENERATE_FIFOCHECK_HINT_MASK(swHWM, swLWM) \ + (((swHWM & 0xffff) << 16) | (swLWM & 0xffff)) + +/* +** ----------------------------------------------------------------------- +** FUNCTION PROTOTYPES +** ----------------------------------------------------------------------- +*/ +#ifndef FX_GLIDE_NO_FUNC_PROTO +/* +** rendering functions +*/ + +#ifndef GLIDE3_ALPHA + +FX_ENTRY void FX_CALL +grDrawPlanarPolygon( int nverts, const int ilist[], const GrVertex vlist[] ); + +FX_ENTRY void FX_CALL +grDrawPlanarPolygonVertexList( int nverts, const GrVertex vlist[] ); + +FX_ENTRY void FX_CALL +grDrawPolygon( int nverts, const int ilist[], const GrVertex vlist[] ); + +FX_ENTRY void FX_CALL +grDrawPolygonVertexList( int nverts, const GrVertex vlist[] ); + +#endif /* !GLIDE3_ALPHA */ + +#ifdef GLIDE3 +FX_ENTRY void FX_CALL +grDrawPoint( void *pt ); + +FX_ENTRY void FX_CALL +grDrawLine( void *v1, void *v2 ); + +FX_ENTRY void FX_CALL +grDrawTriangle( void *a, void *b, void *c ); + +#else +FX_ENTRY void FX_CALL +grDrawPoint( const GrVertex *pt ); + +FX_ENTRY void FX_CALL +grDrawLine( const GrVertex *v1, const GrVertex *v2 ); + +FX_ENTRY void FX_CALL +grDrawTriangle( const GrVertex *a, const GrVertex *b, const GrVertex *c ); +#endif + +/* +** buffer management +*/ +FX_ENTRY void FX_CALL +grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU16 depth ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY int FX_CALL +grBufferNumPending( void ); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY void FX_CALL +grBufferSwap( int swap_interval ); + +FX_ENTRY void FX_CALL +grRenderBuffer( GrBuffer_t buffer ); + +/* +** error management +*/ +typedef void (*GrErrorCallbackFnc_t)( const char *string, FxBool fatal ); + +FX_ENTRY void FX_CALL +grErrorSetCallback( GrErrorCallbackFnc_t fnc ); + +/* +** SST routines +*/ +#ifdef GLIDE3 +FX_ENTRY void FX_CALL +grFinish(void); +#endif + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +FX_ENTRY void FX_CALL +grFlush(void); +#endif + +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +grSstIdle(void); + +FX_ENTRY FxU32 FX_CALL +grSstVideoLine( void ); + +FX_ENTRY FxBool FX_CALL +grSstVRetraceOn( void ); + +FX_ENTRY FxBool FX_CALL +grSstIsBusy( void ); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY FxBool FX_CALL +grSstWinOpen( + FxU32 hWnd, + GrScreenResolution_t screen_resolution, + GrScreenRefresh_t refresh_rate, + GrColorFormat_t color_format, + GrOriginLocation_t origin_location, + int nColBuffers, + int nAuxBuffers); + +FX_ENTRY void FX_CALL +grSstWinClose( void ); + +FX_ENTRY FxBool FX_CALL +grSstControl( FxU32 code ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY FxBool FX_CALL +grSstQueryHardware( GrHwConfiguration *hwconfig ); + +FX_ENTRY FxBool FX_CALL +grSstQueryBoards( GrHwConfiguration *hwconfig ); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY void FX_CALL +grSstOrigin(GrOriginLocation_t origin); + +FX_ENTRY void FX_CALL +grSstSelect( int which_sst ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY FxU32 FX_CALL +grSstScreenHeight( void ); + +FX_ENTRY FxU32 FX_CALL +grSstScreenWidth( void ); + +FX_ENTRY FxU32 FX_CALL +grSstStatus( void ); +#endif /* !GLIDE3_ALPHA */ + +/* +** Drawing Statistics +*/ +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +grSstPerfStats(GrSstPerfStats_t *pStats); + +FX_ENTRY void FX_CALL +grSstResetPerfStats(void); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY void FX_CALL +grResetTriStats(); + +FX_ENTRY void FX_CALL +grTriStats(FxU32 *trisProcessed, FxU32 *trisDrawn); + +/* +** Glide configuration and special effect maintenance functions +*/ +FX_ENTRY void FX_CALL +grAlphaBlendFunction( + GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, + GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df + ); + +FX_ENTRY void FX_CALL +grAlphaCombine( + GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert + ); + +FX_ENTRY void FX_CALL +grAlphaControlsITRGBLighting( FxBool enable ); + +FX_ENTRY void FX_CALL +grAlphaTestFunction( GrCmpFnc_t function ); + +FX_ENTRY void FX_CALL +grAlphaTestReferenceValue( GrAlpha_t value ); + +FX_ENTRY void FX_CALL +grChromakeyMode( GrChromakeyMode_t mode ); + +FX_ENTRY void FX_CALL +grChromakeyValue( GrColor_t value ); + +FX_ENTRY void FX_CALL +grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy ); + +FX_ENTRY void FX_CALL +grColorCombine( + GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert ); + +FX_ENTRY void FX_CALL +grColorMask( FxBool rgb, FxBool a ); + +FX_ENTRY void FX_CALL +grCullMode( GrCullMode_t mode ); + +FX_ENTRY void FX_CALL +grConstantColorValue( GrColor_t value ); + +FX_ENTRY void FX_CALL +grConstantColorValue4( float a, float r, float g, float b ); + +FX_ENTRY void FX_CALL +grDepthBiasLevel( FxI16 level ); + +FX_ENTRY void FX_CALL +grDepthBufferFunction( GrCmpFnc_t function ); + +FX_ENTRY void FX_CALL +grDepthBufferMode( GrDepthBufferMode_t mode ); + +FX_ENTRY void FX_CALL +grDepthMask( FxBool mask ); + +FX_ENTRY void FX_CALL +grDisableAllEffects( void ); + +FX_ENTRY void FX_CALL +grDitherMode( GrDitherMode_t mode ); + +FX_ENTRY void FX_CALL +grFogColorValue( GrColor_t fogcolor ); + +FX_ENTRY void FX_CALL +grFogMode( GrFogMode_t mode ); + +FX_ENTRY void FX_CALL +grFogTable( const GrFog_t ft[] ); + +FX_ENTRY void FX_CALL +grGammaCorrectionValue( float value ); + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +FX_ENTRY void FX_CALL +grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue); +#endif + +FX_ENTRY void FX_CALL +grSplash(float x, float y, float width, float height, FxU32 frame); + +#ifdef GLIDE3 +FX_ENTRY FxBool FX_CALL +grGet( FxU32 pname, FxU32 plength, FxI32 *params ); + +FX_ENTRY const char * FX_CALL +grGetString( FxU32 pname ); + +FX_ENTRY FxBool FX_CALL +grReset( FxU32 what ); + +FX_ENTRY GrProc FX_CALL +grGetProcAddress( char *procName ); + +FX_ENTRY void FX_CALL +grEnable( GrEnableMode_t mode ); + +FX_ENTRY void FX_CALL +grDisable( GrEnableMode_t mode ); + +FX_ENTRY void FX_CALL +grCoordinateSpace( GrCoordinateSpaceMode_t mode ); + +FX_ENTRY void FX_CALL +grDepthRange( FxFloat n, FxFloat f ); + +FX_ENTRY void FX_CALL +grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height ); + +#endif +/* +** texture mapping control functions +*/ +FX_ENTRY FxU32 FX_CALL +grTexCalcMemRequired( + GrLOD_t lodmin, GrLOD_t lodmax, + GrAspectRatio_t aspect, GrTextureFormat_t fmt); + +FX_ENTRY FxU32 FX_CALL +grTexTextureMemRequired( FxU32 evenOdd, + GrTexInfo *info ); + +FX_ENTRY FxU32 FX_CALL +grTexMinAddress( GrChipID_t tmu ); + + +FX_ENTRY FxU32 FX_CALL +grTexMaxAddress( GrChipID_t tmu ); + + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +FX_ENTRY void FX_CALL +grTexNCCTable( GrNCCTable_t table ); +#else +FX_ENTRY void FX_CALL +grTexNCCTable( GrChipID_t tmu, GrNCCTable_t table ); +#endif + +FX_ENTRY void FX_CALL +grTexSource( GrChipID_t tmu, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ); + +FX_ENTRY void FX_CALL +grTexClampMode( + GrChipID_t tmu, + GrTextureClampMode_t s_clampmode, + GrTextureClampMode_t t_clampmode + ); + +FX_ENTRY void FX_CALL +grTexCombine( + GrChipID_t tmu, + GrCombineFunction_t rgb_function, + GrCombineFactor_t rgb_factor, + GrCombineFunction_t alpha_function, + GrCombineFactor_t alpha_factor, + FxBool rgb_invert, + FxBool alpha_invert + ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +grTexCombineFunction( + GrChipID_t tmu, + GrTextureCombineFnc_t fnc + ); +#endif + +FX_ENTRY void FX_CALL +grTexDetailControl( + GrChipID_t tmu, + int lod_bias, + FxU8 detail_scale, + float detail_max + ); + +FX_ENTRY void FX_CALL +grTexFilterMode( + GrChipID_t tmu, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode + ); + + +FX_ENTRY void FX_CALL +grTexLodBiasValue(GrChipID_t tmu, float bias ); + +FX_ENTRY void FX_CALL +grTexDownloadMipMap( GrChipID_t tmu, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ); + +FX_ENTRY void FX_CALL +grTexDownloadMipMapLevel( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data ); + +FX_ENTRY void FX_CALL +grTexDownloadMipMapLevelPartial( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + void *data, + int start, + int end ); + + +FX_ENTRY void FX_CALL +ConvertAndDownloadRle( GrChipID_t tmu, + FxU32 startAddress, + GrLOD_t thisLod, + GrLOD_t largeLod, + GrAspectRatio_t aspectRatio, + GrTextureFormat_t format, + FxU32 evenOdd, + FxU8 *bm_data, + long bm_h, + FxU32 u0, + FxU32 v0, + FxU32 width, + FxU32 height, + FxU32 dest_width, + FxU32 dest_height, + FxU16 *tlut); + +FX_ENTRY void FX_CALL +grCheckForRoom(FxI32 n); + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +FX_ENTRY void FX_CALL +grTexDownloadTable( GrTexTable_t type, + void *data ); + +FX_ENTRY void FX_CALL +grTexDownloadTablePartial( GrTexTable_t type, + void *data, + int start, + int end ); +#else +FX_ENTRY void FX_CALL +grTexDownloadTable( GrChipID_t tmu, + GrTexTable_t type, + void *data ); + +FX_ENTRY void FX_CALL +grTexDownloadTablePartial( GrChipID_t tmu, + GrTexTable_t type, + void *data, + int start, + int end ); +#endif + +FX_ENTRY void FX_CALL +grTexMipMapMode( GrChipID_t tmu, + GrMipMapMode_t mode, + FxBool lodBlend ); + +FX_ENTRY void FX_CALL +grTexMultibase( GrChipID_t tmu, + FxBool enable ); + +FX_ENTRY void FX_CALL +grTexMultibaseAddress( GrChipID_t tmu, + GrTexBaseRange_t range, + FxU32 startAddress, + FxU32 evenOdd, + GrTexInfo *info ); + +/* +** utility texture functions +*/ + +#ifndef GLIDE3_ALPHA +FX_ENTRY GrMipMapId_t FX_CALL +guTexAllocateMemory( + GrChipID_t tmu, + FxU8 odd_even_mask, + int width, int height, + GrTextureFormat_t fmt, + GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, + GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minfilter_mode, + GrTextureFilterMode_t magfilter_mode, + float lod_bias, + FxBool trilinear + ); + +FX_ENTRY FxBool FX_CALL +guTexChangeAttributes( + GrMipMapId_t mmid, + int width, int height, + GrTextureFormat_t fmt, + GrMipMapMode_t mm_mode, + GrLOD_t smallest_lod, GrLOD_t largest_lod, + GrAspectRatio_t aspect, + GrTextureClampMode_t s_clamp_mode, + GrTextureClampMode_t t_clamp_mode, + GrTextureFilterMode_t minFilterMode, + GrTextureFilterMode_t magFilterMode + ); + +FX_ENTRY void FX_CALL +guTexCombineFunction( + GrChipID_t tmu, + GrTextureCombineFnc_t fnc + ); + +FX_ENTRY GrMipMapId_t FX_CALL +guTexGetCurrentMipMap( GrChipID_t tmu ); + +FX_ENTRY GrMipMapInfo * FX_CALL +guTexGetMipMapInfo( GrMipMapId_t mmid ); + +FX_ENTRY FxU32 FX_CALL +guTexMemQueryAvail( GrChipID_t tmu ); + +FX_ENTRY void FX_CALL +guTexMemReset( void ); + +FX_ENTRY void FX_CALL +guTexDownloadMipMap( + GrMipMapId_t mmid, + const void *src, + const GuNccTable *table + ); + +FX_ENTRY void FX_CALL +guTexDownloadMipMapLevel( + GrMipMapId_t mmid, + GrLOD_t lod, + const void **src + ); +FX_ENTRY void FX_CALL +guTexSource( GrMipMapId_t id ); +#endif /* !GLIDE3_ALPHA */ + +/* +** linear frame buffer functions +*/ + +FX_ENTRY FxBool FX_CALL +grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, + GrOriginLocation_t origin, FxBool pixelPipeline, + GrLfbInfo_t *info ); + +FX_ENTRY FxBool FX_CALL +grLfbUnlock( GrLock_t type, GrBuffer_t buffer ); + +FX_ENTRY void FX_CALL +grLfbConstantAlpha( GrAlpha_t alpha ); + +FX_ENTRY void FX_CALL +grLfbConstantDepth( FxU16 depth ); + +FX_ENTRY void FX_CALL +grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords); + +FX_ENTRY void FX_CALL +grLfbWriteColorFormat(GrColorFormat_t colorFormat); + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +FX_ENTRY FxBool FX_CALL +grLfbWriteRegion( GrBuffer_t dst_buffer, + FxU32 dst_x, FxU32 dst_y, + GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, + FxBool pixelPipeline, + FxI32 src_stride, void *src_data ); +#else +FX_ENTRY FxBool FX_CALL +grLfbWriteRegion( GrBuffer_t dst_buffer, + FxU32 dst_x, FxU32 dst_y, + GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, + FxI32 src_stride, void *src_data ); +#endif + +FX_ENTRY FxBool FX_CALL +grLfbReadRegion( GrBuffer_t src_buffer, + FxU32 src_x, FxU32 src_y, + FxU32 src_width, FxU32 src_height, + FxU32 dst_stride, void *dst_data ); + + +/* +** Antialiasing Functions +*/ + +#ifndef GLIDE3_ALPHA + +FX_ENTRY void FX_CALL +grAADrawLine(const GrVertex *v1, const GrVertex *v2); + +FX_ENTRY void FX_CALL +grAADrawPoint(const GrVertex *pt ); + +FX_ENTRY void FX_CALL +grAADrawPolygon(const int nverts, const int ilist[], const GrVertex vlist[]); + +FX_ENTRY void FX_CALL +grAADrawPolygonVertexList(const int nverts, const GrVertex vlist[]); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY void FX_CALL +grAADrawTriangle( + const GrVertex *a, const GrVertex *b, const GrVertex *c, + FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias + ); + +/* +** glide management functions +*/ +FX_ENTRY void FX_CALL +grGlideInit( void ); + +FX_ENTRY void FX_CALL +grGlideShutdown( void ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +grGlideGetVersion( char version[80] ); +#endif /* !GLIDE3_ALPHA */ + +FX_ENTRY void FX_CALL +grGlideGetState( GrState *state ); + +FX_ENTRY void FX_CALL +grGlideSetState( const GrState *state ); + +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +grGlideShamelessPlug(const FxBool on); + +FX_ENTRY void FX_CALL +grHints(GrHint_t hintType, FxU32 hintMask); +#endif /* !GLIDE3_ALPHA */ + +#ifdef GLIDE3 +FX_ENTRY void FX_CALL +grVertexLayout(FxU32 param, FxI32 offset, FxU32 mode); + +FX_ENTRY void FX_CALL +grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers); + +FX_ENTRY void FX_CALL +grDrawVertexArrayLinear(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride); + +FX_ENTRY void FX_CALL +grDrawVertexArrayLinear(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride); + +#endif + +#endif /* FX_GLIDE_NO_FUNC_PROTO */ + +#ifdef __cplusplus +} +#endif + +#include "sdk2_glideutl.h" + +#endif /* __GLIDE_H__ */ diff --git a/MacGLide/OpenGLide/sdk2_glidesys.h b/MacGLide/OpenGLide/sdk2_glidesys.h new file mode 100644 index 0000000..7ea3acc --- /dev/null +++ b/MacGLide/OpenGLide/sdk2_glidesys.h @@ -0,0 +1,128 @@ +/* +** Copyright (c) 1995, 3Dfx Interactive, Inc. +** All Rights Reserved. +** +** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; +** the contents of this file may not be disclosed to third parties, copied or +** duplicated in any form, in whole or in part, without the prior written +** permission of 3Dfx Interactive, Inc. +** +** RESTRICTED RIGHTS LEGEND: +** Use, duplication or disclosure by the Government is subject to restrictions +n** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data +** and Computer Software clause at DFARS 252.227-7013, and/or in similar or +** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - +** rights reserved under the Copyright Laws of the United States. +** +** $Header: /cvsroot/macglide/MacGLide/OpenGLide/sdk2_glidesys.h,v 1.2 2003/11/02 16:29:59 jens-olaf Exp $ +** $Log: sdk2_glidesys.h,v $ +** Revision 1.2 2003/11/02 16:29:59 jens-olaf +** Commented out code that has been copied to ../Mac/OpenGLide/ +** +** Revision 1.1 2002/12/05 13:50:21 fbarros +** 3dfx sdk 2 header file +** +** Revision 1.1.1.1 2001/06/25 18:00:50 paul +** v006 from sourceforge +** +** Revision 1.1.1.1 2001/02/01 16:24:51 fbarros +** Version 0.06 +** +** CVs: ---------------------------------------------------------------------- +** +*/ +#ifndef __GLIDESYS_H__ +#define __GLIDESYS_H__ + +/* +n** ----------------------------------------------------------------------- +** COMPILER/ENVIRONMENT CONFIGURATION +** ----------------------------------------------------------------------- +*/ + +/* Endianness is stored in bits [30:31] */ +#define GLIDE_ENDIAN_SHIFT 30 +#define GLIDE_ENDIAN_LITTLE (0x1 << GLIDE_ENDIAN_SHIFT) +#define GLIDE_ENDIAN_BIG (0x2 << GLIDE_ENDIAN_SHIFT) + +/* OS is stored in bits [0:6] */ +#define GLIDE_OS_SHIFT 0 +#define GLIDE_OS_UNIX 0x1 +#define GLIDE_OS_DOS32 0x2 +#define GLIDE_OS_WIN32 0x4 +#define GLIDE_OS_SYSTEM7 0x8 +#define GLIDE_OS_OS2 0x10 +#define GLIDE_OS_OTHER 0x20 /* For Proprietary Arcade HW */ + +/* Sim vs. Hardware is stored in bits [7:8] */ +#define GLIDE_SST_SHIFT 7 +#define GLIDE_SST_SIM (0x1 << GLIDE_SST_SHIFT) +#define GLIDE_SST_HW (0x2 << GLIDE_SST_SHIFT ) + +/* Hardware Type is stored in bits [9:12] */ +#define GLIDE_HW_SHIFT 9 +#define GLIDE_HW_SST1 (0x1 << GLIDE_HW_SHIFT) +#define GLIDE_HW_SST96 (0x2 << GLIDE_HW_SHIFT) +#define GLIDE_HW_SSTH3 (0x4 << GLIDE_HW_SHIFT) +#define GLIDE_HW_SST2 (0x8 << GLIDE_HW_SHIFT) + +/* +** Make sure we handle all instances of WIN32 +*/ +#ifndef __WIN32__ +# if defined ( _WIN32 ) || defined (WIN32) || defined(__NT__) +# define __WIN32__ +# endif +#endif + +/* We need two checks on the OS: one for endian, the other for OS */ +/* Check for endianness */ +#if defined(__IRIX__) || defined(__sparc__) || defined(MACOS) +# define GLIDE_ENDIAN GLIDE_ENDIAN_BIG +#else +# define GLIDE_ENDIAN GLIDE_ENDIAN_LITTLE +#endif + +/* Check for OS */ +#if defined(__IRIX__) || defined(__sparc__) || defined(__linux__) +# define GLIDE_OS GLIDE_OS_UNIX +#elif defined(__DOS__) +# define GLIDE_OS GLIDE_OS_DOS32 +#elif defined(__WIN32__) +# define GLIDE_OS GLIDE_OS_WIN32 +#endif + +/* Check for Simulator vs. Hardware */ +#ifdef GLIDE_SIMULATOR +# define GLIDE_SST GLIDE_SST_SIM +#else +# define GLIDE_SST GLIDE_SST_HW +#endif + +/* Check for type of hardware */ +#ifdef SST96 +# define GLIDE_HW GLIDE_HW_SST96 +#elif defined(SSTH3) +# define GLIDE_HW GLIDE_HW_SSTH3 +#elif defined(SST2) +# define GLIDE_HW GLIDE_HW_SST2 +#else /* Default to SST1 */ +# define GLIDE_HW GLIDE_HW_SST1 +#endif + + +#define GLIDE_PLATFORM (GLIDE_ENDIAN | GLIDE_OS | GLIDE_SST | GLIDE_HW) + +/* +** Control the number of TMUs +*/ +#ifndef GLIDE_NUM_TMU +# define GLIDE_NUM_TMU 2 +#endif + + +#if ( ( GLIDE_NUM_TMU < 0 ) && ( GLIDE_NUM_TMU > 3 ) ) +# error "GLIDE_NUM_TMU set to an invalid value" +#endif + +#endif /* __GLIDESYS_H__ */ diff --git a/MacGLide/OpenGLide/sdk2_glideutl.h b/MacGLide/OpenGLide/sdk2_glideutl.h new file mode 100644 index 0000000..5b6c519 --- /dev/null +++ b/MacGLide/OpenGLide/sdk2_glideutl.h @@ -0,0 +1,197 @@ +/* +** Copyright (c) 1995, 3Dfx Interactive, Inc. +** All Rights Reserved. +** +** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; +** the contents of this file may not be disclosed to third parties, copied or +** duplicated in any form, in whole or in part, without the prior written +** permission of 3Dfx Interactive, Inc. +** +** RESTRICTED RIGHTS LEGEND: +** Use, duplication or disclosure by the Government is subject to restrictions +** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data +** and Computer Software clause at DFARS 252.227-7013, and/or in similar or +** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - +** rights reserved under the Copyright Laws of the United States. +** +** $Header: /cvsroot/macglide/MacGLide/OpenGLide/sdk2_glideutl.h,v 1.2 2003/11/02 16:29:59 jens-olaf Exp $ +** $Log: sdk2_glideutl.h,v $ +** Revision 1.2 2003/11/02 16:29:59 jens-olaf +** Commented out code that has been copied to ../Mac/OpenGLide/ +** +** Revision 1.1 2002/12/05 13:50:21 fbarros +** 3dfx sdk 2 header file +** +** Revision 1.1.1.1 2001/06/25 18:00:50 paul +** v006 from sourceforge +** +** Revision 1.1.1.1 2001/02/01 16:24:51 fbarros +** Version 0.06 +** +** CVs: ---------------------------------------------------------------------- +** + * + * 11 1/07/98 11:18a Atai + * remove GrMipMapInfo and GrGC.mm_table in glide3 + * + * 10 1/06/98 6:47p Atai + * undo grSplash and remove gu routines + * + * 9 1/05/98 6:04p Atai + * move 3df gu related data structure from glide.h to glideutl.h + * + * 8 12/18/97 2:13p Peter + * fogTable cataclysm + * + * 7 12/15/97 5:52p Atai + * disable obsolete glide2 api for glide3 + * + * 6 8/14/97 5:32p Pgj + * remove dead code per GMT + * + * 5 6/12/97 5:19p Pgj + * Fix bug 578 + * + * 4 3/05/97 9:36p Jdt + * Removed guFbWriteRegion added guEncodeRLE16 + * + * 3 1/16/97 3:45p Dow + * Embedded fn protos in ifndef FX_GLIDE_NO_FUNC_PROTO +*/ + +/* Glide Utility routines */ + +#ifndef __GLIDEUTL_H__ +#define __GLIDEUTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +/* +** 3DF texture file structs +*/ + +typedef struct +{ + FxU32 width, height; + int small_lod, large_lod; + GrAspectRatio_t aspect_ratio; + GrTextureFormat_t format; +} Gu3dfHeader; + +typedef struct +{ + FxU8 yRGB[16]; + FxI16 iRGB[4][3]; + FxI16 qRGB[4][3]; + FxU32 packed_data[12]; +} GuNccTable; + +typedef struct { + FxU32 data[256]; +} GuTexPalette; + +typedef union { + GuNccTable nccTable; + GuTexPalette palette; +} GuTexTable; + +typedef struct +{ + Gu3dfHeader header; + GuTexTable table; + void *data; + FxU32 mem_required; /* memory required for mip map in bytes. */ +} Gu3dfInfo; + +#endif + +#ifndef FX_GLIDE_NO_FUNC_PROTO +/* +** rendering functions +*/ + +#ifndef GLIDE3_ALPHA +FX_ENTRY void FX_CALL +guAADrawTriangleWithClip( const GrVertex *a, const GrVertex + *b, const GrVertex *c); + +FX_ENTRY void FX_CALL +guDrawTriangleWithClip( + const GrVertex *a, + const GrVertex *b, + const GrVertex *c + ); + +FX_ENTRY void FX_CALL +guDrawPolygonVertexListWithClip( int nverts, const GrVertex vlist[] ); + +/* +** hi-level rendering utility functions +*/ +FX_ENTRY void FX_CALL +guAlphaSource( GrAlphaSource_t mode ); + +FX_ENTRY void FX_CALL +guColorCombineFunction( GrColorCombineFnc_t fnc ); + +FX_ENTRY int FX_CALL +guEncodeRLE16( void *dst, + void *src, + FxU32 width, + FxU32 height ); + +FX_ENTRY FxU16 * FX_CALL +guTexCreateColorMipMap( void ); +#endif /* !GLIDE3_ALPHA */ + +#ifdef GLIDE3 +FX_ENTRY void FX_CALL +guGammaCorrectionRGB( FxFloat red, FxFloat green, FxFloat blue ); +#endif + +/* +** fog stuff +*/ +FX_ENTRY float FX_CALL +guFogTableIndexToW( int i ); + +FX_ENTRY void FX_CALL +guFogGenerateExp( GrFog_t fogtable[], float density ); + +FX_ENTRY void FX_CALL +guFogGenerateExp2( GrFog_t fogtable[], float density ); + +FX_ENTRY void FX_CALL +guFogGenerateLinear(GrFog_t fogtable[], + float nearZ, float farZ ); + +/* +** endian stuff +*/ +#ifndef GLIDE3_ALPHA +FX_ENTRY FxU32 FX_CALL +guEndianSwapWords( FxU32 value ); + +FX_ENTRY FxU16 FX_CALL +guEndianSwapBytes( FxU16 value ); +#endif /* !GLIDE3_ALPHA */ + +/* +** hi-level texture manipulation tools. +*/ +FX_ENTRY FxBool FX_CALL +gu3dfGetInfo( const char *filename, Gu3dfInfo *info ); + +FX_ENTRY FxBool FX_CALL +gu3dfLoad( const char *filename, Gu3dfInfo *data ); + +#endif /* FX_GLIDE_NO_FUNC_PROTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __GLIDEUTL_H__ */ diff --git a/MacGLide/OpenGLide/sdk2_sst1vid.h b/MacGLide/OpenGLide/sdk2_sst1vid.h new file mode 100644 index 0000000..3a20459 --- /dev/null +++ b/MacGLide/OpenGLide/sdk2_sst1vid.h @@ -0,0 +1,120 @@ +/* +** Copyright (c) 1995, 3Dfx Interactive, Inc. +** All Rights Reserved. +** +** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; +** the contents of this file may not be disclosed to third parties, copied or +** duplicated in any form, in whole or in part, without the prior written +** permission of 3Dfx Interactive, Inc. +** +** RESTRICTED RIGHTS LEGEND: +** Use, duplication or disclosure by the Government is subject to restrictions +** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data +** and Computer Software clause at DFARS 252.227-7013, and/or in similar or +** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - +** rights reserved under the Copyright Laws of the United States. +** +** $Header: /cvsroot/macglide/MacGLide/OpenGLide/sdk2_sst1vid.h,v 1.2 2003/11/02 16:29:59 jens-olaf Exp $ +** $Log: sdk2_sst1vid.h,v $ +** Revision 1.2 2003/11/02 16:29:59 jens-olaf +** Commented out code that has been copied to ../Mac/OpenGLide/ +** +** Revision 1.1 2002/12/05 13:50:21 fbarros +** 3dfx sdk 2 header file +** +** Revision 1.1.1.1 2001/06/25 18:00:49 paul +** v006 from sourceforge +** +** Revision 1.1.1.1 2001/02/01 16:24:51 fbarros +** Version 0.06 +** +** CVs: ---------------------------------------------------------------------- +** + * + * 4 9/09/97 7:35p Sellers + * Added 400x300 resolution + * + * 3 8/24/97 9:31a Sellers + * moved new video timing to sst1vid.h + * redefined 1600x1280 to be 1600x1200 + * + * 2 6/05/97 11:14p Pgj + * + * 5 7/24/96 3:43p Sellers + * added 512x384 @ 60 Hz for arcade monitors + * added 512x256 @ 60 Hz for arcade monitors + * + * 4 7/18/96 10:58a Sellers + * fixed FT and TF clock delay values for lower frequencies with + * .5/.5 combos + * + * 3 6/18/96 6:54p Sellers + * added sst1InitShutdownSli() to fix Glide Splash screen problems with + * SLI + * + * 2 6/13/96 7:45p Sellers + * added "voodoo.ini" support + * added DirectX support + * misc cleanup + * + * 2 6/11/96 1:43p Sellers + * added support for 60, 75, 85, and 120 Hz refresh rates for "most" + * resolutions + * + * 1 5/08/96 5:43p Paik + * Video definitions +*/ +#ifndef __SST1VID_H__ +#define __SST1VID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Video defines */ + +typedef FxI32 GrScreenRefresh_t; +#define GR_REFRESH_60Hz 0x0 +#define GR_REFRESH_70Hz 0x1 +#define GR_REFRESH_72Hz 0x2 +#define GR_REFRESH_75Hz 0x3 +#define GR_REFRESH_80Hz 0x4 +#define GR_REFRESH_90Hz 0x5 +#define GR_REFRESH_100Hz 0x6 +#define GR_REFRESH_85Hz 0x7 +#define GR_REFRESH_120Hz 0x8 +#define GR_REFRESH_NONE 0xff + +typedef FxI32 GrScreenResolution_t; +#define GR_RESOLUTION_320x200 0x0 +#define GR_RESOLUTION_320x240 0x1 +#define GR_RESOLUTION_400x256 0x2 +#define GR_RESOLUTION_512x384 0x3 +#define GR_RESOLUTION_640x200 0x4 +#define GR_RESOLUTION_640x350 0x5 +#define GR_RESOLUTION_640x400 0x6 +#define GR_RESOLUTION_640x480 0x7 +#define GR_RESOLUTION_800x600 0x8 +#define GR_RESOLUTION_960x720 0x9 +#define GR_RESOLUTION_856x480 0xa +#define GR_RESOLUTION_512x256 0xb +#define GR_RESOLUTION_1024x768 0xC +#define GR_RESOLUTION_1280x1024 0xD +#define GR_RESOLUTION_1600x1200 0xE +#define GR_RESOLUTION_400x300 0xF +#define GR_RESOLUTION_NONE 0xff + +#ifdef GR_RESOLUTION_MAX +#undef GR_RESOLUTION_MAX +#endif +#ifdef GR_RESOLUTION_MIN +#undef GR_RESOLUTION_MIN +#endif +#define GR_RESOLUTION_MIN GR_RESOLUTION_320x200 +#define GR_RESOLUTION_MAX GR_RESOLUTION_1600x1200 + +#ifdef __cplusplus +} +#endif + +#endif /* __SST1VID_H__ */ diff --git a/MacGLide/OpenGLide/sst1.cpp b/MacGLide/OpenGLide/sst1.cpp new file mode 100644 index 0000000..342eb26 --- /dev/null +++ b/MacGLide/OpenGLide/sst1.cpp @@ -0,0 +1,55 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* pre-glide22 buffer access interface +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#include "sst1.h" + +// Called by Quake 1 3dfx on the Mac +// (resolves error message: sst1InitMapBoard nicht gefunden) +// +// See also: http://www.xlr8yourmac.com/feedback/voodoo2gen.html +// Ľ Quake 1.09.x does not work. A programmer friend of mine says +// this is because Quake makes a call to an obsolete Glide function +// (sstInitMapBoard or similar call) which I hear was purposefully +// left out of these relatively up-to-date Glide 2.x drivers ... +// Parameters from +// http://home.y3m.net/horde/chora/co.php/homeworld/src/rgl/glide3/include/sst1init3.h?sbt=3&ord=1&r=1.1.1.1 + +FX_ENTRY FxU32* FX_CALL sst1InitMapBoard(FxU32 param1) +{ +#ifdef OGL_NOTDONE + GlideMsg("sst1InitMapBoard(%d)\n", param1); +#endif + + return 0; +} + +FX_ENTRY FxBool FX_CALL sst1InitGamma(FxU32* param1, double param2) +{ +#ifdef OGL_NOTDONE + GlideMsg("sst1InitGamma(%d, %g)\n", param1, param2); +#endif + + return FXTRUE; +} + +FX_ENTRY FxBool FX_CALL grSstOpen(GrScreenResolution_t res, + GrScreenRefresh_t refresh, + GrColorFormat_t cFormat, + GrOriginLocation_t locateOrigin, + GrSmoothingMode_t smoothMode, + int numBuffers) +{ +#ifdef OGL_DONE + GlideMsg("grSstOpen( %d, %d, %d, %d, %d, %d, %d)\n", res, refresh, cFormat, locateOrigin, smoothMode, numBuffers); +#endif + return grSstWinOpen( 0, res, refresh, cFormat, locateOrigin, numBuffers, 0); +} diff --git a/MacGLide/OpenGLide/sst1.h b/MacGLide/OpenGLide/sst1.h new file mode 100644 index 0000000..a084272 --- /dev/null +++ b/MacGLide/OpenGLide/sst1.h @@ -0,0 +1,35 @@ +//************************************************************** +//* OpenGLide for Macintosh - Glide to OpenGL Wrapper +//* http://macglide.sourceforge.net/ +//* +//* pre-glide24 sst1 functions +//* +//* OpenGLide is OpenSource under LGPL license +//* Originaly made by Fabio Barros +//* Modified by Paul for Glidos (http://www.glidos.net) +//* Mac version and additional features by Jens-Olaf Hemprich +//************************************************************** + +#pragma once + +#include "sdk2_3dfx.h" +#include "sdk2_glide.h" + +// prototypes for obsolete sst1-board functions + +#ifdef __cplusplus +extern "C" { +#endif + +FX_ENTRY FxU32* FX_CALL sst1InitMapBoard(FxU32 param1); +FX_ENTRY FxBool FX_CALL sst1InitGamma(FxU32* param1, double param2); +FX_ENTRY FxBool FX_CALL grSstOpen(GrScreenResolution_t res, + GrScreenRefresh_t refresh, + GrColorFormat_t cFormat, + GrOriginLocation_t locateOrigin, + GrSmoothingMode_t smoothMode, + int numBuffers); + +#ifdef __cplusplus +} +#endif diff --git a/MacGLide/glide2x/driversrc_declarations.h b/MacGLide/glide2x/driversrc_declarations.h new file mode 100644 index 0000000..c0799de --- /dev/null +++ b/MacGLide/glide2x/driversrc_declarations.h @@ -0,0 +1,5 @@ +#pragma once + +#include "Glide.h" + +extern void _grShamelessPlug(void); diff --git a/MacGLide/glide2x/driversrc_defines.h b/MacGLide/glide2x/driversrc_defines.h new file mode 100644 index 0000000..77dc8ac --- /dev/null +++ b/MacGLide/glide2x/driversrc_defines.h @@ -0,0 +1,22 @@ +#pragma once + +#ifndef _DRIVERSRC_DEFINES_H_ +#define _DRIVERSRC_DEFINES_H_ + +#include "sdk2_glide.h" + +#define GLIDE_PLUG +// #define GLIDE_PLATFORM +// #define GLIDE_HW_SST1 +// #define GLIDE_HW_SST96 +#define GR_BEGIN_NOFIFOCHECK(x,y) +#define GDBG_INFO_MORE(x) +// #define GR_END() +#define GR_DIENTRY(f,r,p) r f p + +// These defines are obsolete in the emulation +// (they can be commented out in the src) +// #define GR_SET_EXPECTED_SIZE(n,p) +// #define GR_CHECK_SIZE_SLOPPY() + +#endif //_DRIVERSRC_DEFINES_H_ diff --git a/MacGLide/glide2x/sst1/glide/src/banner.inc b/MacGLide/glide2x/sst1/glide/src/banner.inc new file mode 100644 index 0000000..4401d19 --- /dev/null +++ b/MacGLide/glide2x/sst1/glide/src/banner.inc @@ -0,0 +1,122 @@ +/* + * THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + * PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + * TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + * INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + * DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + * THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + * FULL TEXT OF THE NON-WARRANTY PROVISIONS. + * + * USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + * RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + * TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + * AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + * SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + * THE UNITED STATES. + * + * COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + */ + + +static int banner_width = 180; +static int banner_height = 90; +static unsigned short banner_data[] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x52aa, 0xad34, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2922, 0xacee, 0x39a5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x93ea, 0xd5d0, 0x944d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9383, 0xd506, 0x8beb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc63, 0xd506, 0xd58d, 0x7b6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a82, 0xd4e4, 0xd504, 0xc54d, 0x2943, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5202, 0xd4e3, 0xd4e3, 0xd505, 0xcd6d, 0x5aa8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3961, 0xc483, 0xd503, 0xd504, 0xd569, 0x8baa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5268, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9364, 0xd4e2, 0xd4e2, 0xd4e2, 0xd505, 0xc54e, 0x4206, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa3e3, 0xd504, 0xd546, 0xd504, 0xd525, 0xc54d, 0x2103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e1, 0x93a4, 0xcd4c, 0x20e2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc86, 0xd504, 0xd547, 0xd548, 0xd504, 0xd526, 0xbd2f, 0x2944, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7ae3, 0xd504, 0xd56a, 0xd634, 0xd569, 0xd525, 0xdd69, 0x8369, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49c3, 0xb487, 0xd504, 0xd528, 0x5246, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0x6ac4, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x528a, 0x39e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xd526, 0xd548, 0xd5cf, 0xd613, 0xd527, 0xd505, 0xd548, 0xacae, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49a1, 0xcce5, 0xd56a, 0xde12, 0xde98, 0xddce, 0xd548, 0xdd04, 0xc52e, 0x18e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72c5, 0xcce7, 0xd504, 0xd503, 0xd527, 0x7b48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49e2, 0x9b83, 0xc4a4, 0xac23, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5247, 0xc570, 0x736a, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9363, 0xd505, 0xd58c, 0xd634, 0xd678, 0xd5f1, 0xd548, 0xd504, 0xd58b, 0x942c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18a1, 0xb444, 0xdd48, 0xddf0, 0xde98, 0xdeb9, 0xde55, 0xdd6b, 0xdd03, 0xdd8b, 0x7349, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2902, 0x9be6, 0xd527, 0xd524, 0xd524, 0xdd03, 0xd526, 0x9c09, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e1, 0x72c4, 0xac25, 0xd4e3, 0xd4e3, 0xd4e3, 0x8345, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc85, 0xd5cf, 0xacef, 0x4227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc85, 0xd526, 0xd5f1, 0xd698, 0xd6ba, 0xd699, 0xd5cf, 0xd547, 0xd525, 0xd5ae, 0x7b6a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8b43, 0xdd04, 0xddae, 0xde76, 0xdeda, 0xdeda, 0xdeba, 0xddcf, 0xdd25, 0xdd47, 0xbd0c, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a04, 0xbc86, 0xdd24, 0xdd26, 0xddcf, 0xddcf, 0xdd25, 0xdd26, 0xb4ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41a3, 0x8b64, 0xc4a6, 0xd503, 0xd4e3, 0xd4e3, 0xd4e3, 0xd507, 0x49e4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9362, 0xd4e3, 0xd56b, 0xcdb2, 0x83cc, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xd525, 0xd548, 0xd613, 0xd6b9, 0xd6ba, 0xd6ba, 0xd677, 0xddae, 0xd527, 0xdd25, 0xd58d, 0x62c8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xd505, 0xdd68, 0xde34, 0xdeda, 0xdedb, 0xdedb, 0xdeda, 0xde33, 0xdd8a, 0xdd25, 0xdd8c, 0x6b09, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72e5, 0xcd06, 0xdd24, 0xdd68, 0xde33, 0xdeb9, 0xde34, 0xdd46, 0xdd25, 0xcd49, 0x20c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c1, 0x6aa4, 0xa404, 0xd4e4, 0xd504, 0xd549, 0xd5ae, 0xd5ad, 0xd548, 0xd505, 0xbc86, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a21, 0xd4e2, 0xd4e3, 0xd506, 0xd58c, 0xb531, 0x5248, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9363, 0xd504, 0xd5ad, 0xd655, 0xdeba, 0xdeba, 0xdeba, 0xdeba, 0xde76, 0xddae, 0xdd04, 0xdd47, 0xc54d, 0x4a06, 0x0000, 0x0000, 0x0000, 0x2921, 0xbc84, 0xdd46, 0xde11, 0xde98, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb8, 0xddf0, 0xdd46, 0xdd47, 0xbcec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2922, 0x9c07, 0xdd26, 0xdd26, 0xdd8a, 0xde55, 0xdeb9, 0xdedb, 0xde55, 0xdd8b, 0xdd25, 0xdd47, 0x5246, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3983, 0x8b65, 0xbcc8, 0xd526, 0xd526, 0xd56a, 0xd612, 0xd676, 0xd698, 0xd5f2, 0xd525, 0xd506, 0x93c7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18a1, 0xc462, 0xd4e3, 0xd503, 0xd504, 0xd527, 0xcdd1, 0x8c0d, 0x18e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbc86, 0xd505, 0xd5f1, 0xde98, 0xd6ba, 0xdeda, 0xdedb, 0xdedb, 0xdeba, 0xde55, 0xdd8c, 0xdd25, 0xdd26, 0xbd2e, 0x2943, 0x0000, 0x0000, 0x9b83, 0xdd26, 0xddcd, 0xde77, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xde33, 0xdd89, 0xdd25, 0xddad, 0x6ae9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5204, 0xbca8, 0xdd46, 0xdd48, 0xddcf, 0xdeb8, 0xdeda, 0xdedb, 0xdedb, 0xde97, 0xddee, 0xdd25, 0xdd46, 0x7b68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a44, 0xa3e6, 0xcce5, 0xd504, 0xd547, 0xd58c, 0xd633, 0xd698, 0xd6ba, 0xd6ba, 0xd678, 0xd5d0, 0xd504, 0xd527, 0x6286, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9b82, 0xd548, 0xd58b, 0xd549, 0xd4e3, 0xd505, 0xd58c, 0xbd51, 0x5aa9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a24, 0xd526, 0xd526, 0xde35, 0xdeba, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde34, 0xdd6a, 0xdd25, 0xdd26, 0xacac, 0x1081, 0x6aa3, 0xd504, 0xdd48, 0xde76, 0xdeda, 0xdedb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdeda, 0xde97, 0xddcf, 0xdd25, 0xdd47, 0xb4ee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b25, 0xd507, 0xdd24, 0xdd8a, 0xde32, 0xdeb9, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xde97, 0xddef, 0xdd46, 0xdd46, 0x9c2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2922, 0x7b26, 0xbc86, 0xd525, 0xdd04, 0xd546, 0xddd0, 0xde55, 0xd699, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd634, 0xd58c, 0xd504, 0xc4e9, 0x20c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a62, 0xd527, 0xd5d0, 0xd656, 0xd5ad, 0xd527, 0xd505, 0xd527, 0xd5b0, 0x944d, 0x2924, 0x0000, 0x0000, 0x0000, 0x0000, 0x9384, 0xd525, 0xd58a, 0xde56, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde55, 0xdd48, 0xdd24, 0xdd24, 0xa3c3, 0xc4a4, 0xdd48, 0xde10, 0xdeb9, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xde54, 0xdd68, 0xdd26, 0xdd8a, 0x5a87, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2922, 0xa407, 0xdd26, 0xdd45, 0xddab, 0xde55, 0xdeda, 0xdedb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdeb8, 0xde32, 0xdd46, 0xdd25, 0xb4cb, 0x0000, 0x0000, 0x0000, 0x5224, 0x9be7, 0xcce7, 0xdd04, 0xdd47, 0xdd8b, 0xde11, 0xde97, 0xdeba, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xd6b9, 0xd612, 0xd569, 0xd504, 0xa3e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e1, 0xc4c5, 0xd5af, 0xd698, 0xd698, 0xd634, 0xd58c, 0xd525, 0xd526, 0xd56a, 0xbd70, 0x62e9, 0x0000, 0x0000, 0x0000, 0xbc85, 0xd526, 0xddf0, 0xde98, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeb9, 0xde32, 0xdd48, 0xdd25, 0xdd24, 0xdd46, 0xddcd, 0xdeb8, 0xdeda, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xde97, 0xddee, 0xdd46, 0xdd46, 0xacad, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5224, 0xc4e9, 0xdd25, 0xdd47, 0xde10, 0xde97, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde75, 0xdd68, 0xdd25, 0xcd29, 0x3142, 0x7306, 0xb467, 0xd527, 0xdd25, 0xdd48, 0xddce, 0xde54, 0xde98, 0xdeba, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xde98, 0xd5d0, 0xd546, 0xd526, 0x7305, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c2, 0x39a5, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa3e4, 0xd56b, 0xd655, 0xd6ba, 0xd6ba, 0xd698, 0xd5f1, 0xd549, 0xd504, 0xd525, 0xd5ad, 0x9c6d, 0x3163, 0x5a23, 0xd525, 0xdd47, 0xde55, 0xdeb9, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde32, 0xddce, 0xddcd, 0xde11, 0xde97, 0xdeda, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xded9, 0xde54, 0xdd47, 0xdd46, 0xddcd, 0x5246, 0x0000, 0x0000, 0x0000, 0x0000, 0x8347, 0xd527, 0xdd46, 0xdd8a, 0xde32, 0xded9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde97, 0xddab, 0xdd46, 0xdd24, 0xcd06, 0xdd46, 0xdd46, 0xdd8b, 0xddcd, 0xde76, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xd654, 0xd58b, 0xd525, 0xcd4a, 0x3163, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3143, 0x5a65, 0x7b27, 0x9bc7, 0xac46, 0xc4a5, 0x93e8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72a2, 0xd548, 0xd5f1, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6b9, 0xd656, 0xd5ae, 0xd525, 0xd504, 0xdd47, 0xc4c6, 0xb444, 0xdd26, 0xdd8a, 0xde97, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefa, 0xde97, 0xddab, 0xdd46, 0xdd67, 0xa48d, 0x0000, 0x0000, 0x3163, 0xac27, 0xdd68, 0xdd45, 0xddcd, 0xde75, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde97, 0xddcd, 0xdd47, 0xdd24, 0xdd67, 0xddac, 0xde12, 0xde76, 0xdeda, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xde12, 0xd569, 0xd526, 0xb468, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2103, 0x4a26, 0x7307, 0x93a6, 0xa426, 0xbca7, 0xd506, 0xd4e3, 0xd4e2, 0xd4e2, 0xd4e3, 0xb445, 0x18a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3141, 0xcce5, 0xd5ad, 0xd6b9, 0xd6ba, 0xd6ba, 0xd6ba, 0xdeba, 0xde99, 0xd654, 0xd56a, 0xd525, 0xdd03, 0xdd03, 0xdd48, 0xddef, 0xdeb8, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xded9, 0xde52, 0xdd68, 0xdd45, 0xd5af, 0x4a05, 0x5a65, 0xc4e7, 0xdd46, 0xdd68, 0xddef, 0xde96, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde76, 0xddef, 0xde31, 0xdeb8, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xddce, 0xdd25, 0xd547, 0x8366, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39a4, 0x62c7, 0x8388, 0x9c29, 0xb487, 0xccc5, 0xd507, 0xd504, 0xd504, 0xd505, 0xd527, 0xd528, 0xd548, 0xd505, 0xd4e2, 0xc4c6, 0x4182, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xabe2, 0xd56b, 0xd678, 0xd6ba, 0xdeba, 0xd6ba, 0xdeda, 0xdeda, 0xdeba, 0xde98, 0xd5f0, 0xddad, 0xdd8c, 0xddcf, 0xde97, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xded9, 0xddab, 0xdd45, 0xdd68, 0xc4a7, 0xd548, 0xdd46, 0xdd89, 0xde32, 0xe6d9, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xde98, 0xdd8c, 0xdd04, 0xd56b, 0x4a04, 0x0000, 0x2944, 0x5a87, 0x7b48, 0x93e7, 0xac68, 0xc4ea, 0xd56a, 0xd527, 0xd525, 0xd505, 0xd526, 0xd549, 0xd58c, 0xd5d0, 0xd5f3, 0xd635, 0xd656, 0xd655, 0xd58c, 0xd506, 0xccc4, 0x6264, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7ae2, 0xd549, 0xd634, 0xd6b9, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeda, 0xdeda, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe6fa, 0xde31, 0xdd89, 0xe546, 0xdd45, 0xe567, 0xddaa, 0xe696, 0xe6fa, 0xe71b, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeba, 0xde54, 0xdd6b, 0xdd03, 0xcd08, 0xa448, 0xbcc9, 0xd528, 0xd526, 0xd525, 0xd505, 0xd505, 0xd526, 0xd528, 0xd56a, 0xd5ce, 0xd633, 0xd677, 0xd699, 0xd699, 0xd6ba, 0xd6ba, 0xd6ba, 0xd677, 0xd5cf, 0xd506, 0xd505, 0x8345, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a48, 0xa48c, 0x940a, 0x734a, 0x4207, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3961, 0xd506, 0xd5cf, 0xde98, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xad75, 0x39e7, 0x39e7, 0x39e7, 0x39e7, 0x8430, 0x94b2, 0xb5b6, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71b, 0xe6d9, 0xe653, 0xe5ed, 0xe5cc, 0xe631, 0xe6b8, 0xe6fb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde10, 0xdd49, 0xdd03, 0xdd03, 0xdd04, 0xdd27, 0xd547, 0xd569, 0xd5ae, 0xddf1, 0xd634, 0xd676, 0xd698, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd678, 0xd5f1, 0xd506, 0xd504, 0xa427, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a43, 0xc4a5, 0xd505, 0xd56c, 0xbd2d, 0xa4ae, 0x83cc, 0x5ac8, 0x2124, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb446, 0xddab, 0xde97, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0x8430, 0x39e7, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x39e7, 0x4208, 0x738e, 0xa534, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71b, 0xe71b, 0xe71b, 0xe71b, 0xe71b, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdeda, 0xde75, 0xddce, 0xddcd, 0xde11, 0xde54, 0xde55, 0xde77, 0xdeba, 0xdeba, 0xdeba, 0xdeba, 0xdeba, 0xdeba, 0xdeba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd699, 0xd5f2, 0xd547, 0xd504, 0xbc85, 0x2922, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a21, 0xc482, 0xd4e3, 0xd504, 0xd505, 0xd527, 0xd56b, 0xcd90, 0xb4cd, 0x942c, 0x734b, 0x39c6, 0x0000, 0x0000, 0x0000, 0x0000, 0x8323, 0xdd47, 0xde54, 0xdeb9, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0x5aeb, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0xb5b6, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdeda, 0xdeda, 0xdeba, 0xdeda, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd613, 0xd56a, 0xd505, 0xcd08, 0x5204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a21, 0xc4a3, 0xd526, 0xd569, 0xd526, 0xd505, 0xd505, 0xd504, 0xd525, 0xd548, 0xd5ae, 0xbd4e, 0xa48e, 0x838a, 0x5a45, 0x51e2, 0xd506, 0xddf0, 0xde97, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xb5b6, 0x39e7, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0xad55, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe71c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xd6ba, 0xd6ba, 0xd6ba, 0xd6ba, 0xd655, 0xd58d, 0xd503, 0xd549, 0x72e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a21, 0xc4c6, 0xd5ae, 0xd677, 0xd655, 0xd612, 0xd5cf, 0xd56a, 0xd525, 0xd503, 0xd503, 0xd504, 0xd526, 0xd547, 0xccc4, 0xd505, 0xddce, 0xde77, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xd6ba, 0x738e, 0x39e7, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0xbdd7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xd6ba, 0xdedb, 0xd6ba, 0xd677, 0xd58c, 0xd526, 0xd505, 0x93c8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a21, 0xccc6, 0xd5cd, 0xd677, 0xd699, 0xd6ba, 0xd6b9, 0xd699, 0xde77, 0xd611, 0xd58b, 0xdd47, 0xdd26, 0xdd26, 0xdd69, 0xde33, 0xdeb8, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xd69a, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0xc638, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xa514, 0xbdd7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xd6ba, 0xd6ba, 0xd698, 0xd5ad, 0xd526, 0xd505, 0xb48a, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xccc6, 0xd5f1, 0xd677, 0xd6ba, 0xdeba, 0xd6ba, 0xdeba, 0xdeba, 0xdeb9, 0xde98, 0xde55, 0xde76, 0xde97, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xd6ba, 0x8430, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0xad55, 0xe71c, 0xe71c, 0xe71c, 0xad75, 0x4228, 0x4a49, 0x7bcf, 0xad75, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xde98, 0xd611, 0xd527, 0xd504, 0xc52b, 0x39a3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xccc5, 0xd5f1, 0xd698, 0xd6ba, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0x8430, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x7bcf, 0xe71c, 0xe71c, 0xe71c, 0x7bcf, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x8c71, 0xbdf7, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xad75, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xde98, 0xde33, 0xd547, 0xd525, 0xcd28, 0x6286, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xcce7, 0xd5f1, 0xde98, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xc638, 0xb5b6, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xb5b6, 0x9cd3, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x52aa, 0xce59, 0xe71c, 0xce59, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0xa514, 0xce79, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0x9cf3, 0x4a49, 0x4a49, 0x9cf3, 0xbdf7, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xde34, 0xdd69, 0xdd25, 0xd569, 0x8389, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xcce6, 0xd5f0, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xc638, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0xbdf7, 0xe73c, 0x8c71, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x7bef, 0xb596, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xce79, 0x4a69, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0xad55, 0x9cf3, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xde55, 0xddad, 0xdd04, 0xdd26, 0xb4cb, 0x3185, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xcd09, 0xde11, 0xdeb9, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xbdd7, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x9cf3, 0xce59, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x528a, 0xb5b6, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0x7bef, 0x4a69, 0x4a69, 0x632c, 0x4a49, 0x4a49, 0x528a, 0x4a49, 0x630c, 0x4228, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xddf0, 0xdd47, 0xdd04, 0xdd26, 0xd58b, 0xd5d0, 0xc56f, 0xbcee, 0xa46c, 0x940b, 0x838a, 0x6b09, 0x5247, 0x2123, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b03, 0xdd47, 0xde32, 0xdeb9, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xbdd7, 0xbdd7, 0xbdd7, 0x9cd3, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x8c71, 0x9cf3, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x528a, 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0xc638, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0x4a69, 0x7bef, 0x4a69, 0x632c, 0x4a69, 0x630c, 0x4a49, 0x7bcf, 0x4a49, 0x8c71, 0x630c, 0x4228, 0xe71c, 0xd6ba, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdeba, 0xde75, 0xddef, 0xdd69, 0xdd26, 0xdd26, 0xdd26, 0xdd05, 0xd505, 0xd525, 0xd526, 0xd526, 0xd548, 0xd549, 0xd56c, 0xc4e8, 0xb4a9, 0xa44a, 0x93eb, 0x7b6a, 0x62c8, 0x41e5, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5204, 0x8b86, 0xbc86, 0xd505, 0xdd26, 0xddce, 0xdeb9, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0x9492, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4a49, 0x7bcf, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x528a, 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0xbdd7, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0x9492, 0xb596, 0xc618, 0x7bef, 0x4a69, 0x7bef, 0x4a49, 0x8c71, 0x4a49, 0x4a49, 0xad75, 0x4a49, 0x7bcf, 0x9cf3, 0x4228, 0x8c51, 0xce59, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde76, 0xde54, 0xde33, 0xd611, 0xd5d0, 0xd5ae, 0xd58d, 0xd56b, 0xd549, 0xd527, 0xd525, 0xd504, 0xd4e3, 0xd4e3, 0xd504, 0xd504, 0xd506, 0xbc65, 0x4a25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a44, 0x9385, 0xbc65, 0xd527, 0xdd26, 0xdd46, 0xddad, 0xde55, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0x630c, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5acb, 0xad55, 0xef7d, 0xef7d, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xc638, 0xd69a, 0xef5d, 0xef5d, 0xc618, 0xc618, 0x4a69, 0x9492, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0xce79, 0x9cf3, 0x4228, 0x4228, 0x630c, 0x4228, 0x9cd3, 0xbdd7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeda, 0xdeba, 0xdeba, 0xd6ba, 0xd6b9, 0xd699, 0xd698, 0xd678, 0xd677, 0xd656, 0xd5f2, 0xd548, 0xd504, 0xd4c2, 0x9bc4, 0x3121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a44, 0x93a6, 0xbca6, 0xd525, 0xd526, 0xdd47, 0xdd8c, 0xde11, 0xde76, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xad55, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0xce59, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xc638, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xd69a, 0xce59, 0xef5d, 0x9492, 0x8c71, 0x4a49, 0x4a49, 0xbdf7, 0xbdf7, 0x4228, 0x4228, 0x4228, 0x73ae, 0x4228, 0x4208, 0x73ae, 0xbdd7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xd6ba, 0xd6ba, 0xd698, 0xd634, 0xd56a, 0xd505, 0xbc85, 0x6262, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c1, 0x5a65, 0x93a4, 0xc4a5, 0xd525, 0xd505, 0xd548, 0xd5ad, 0xd633, 0xde77, 0xdeb9, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x39e7, 0x2165, 0x2185, 0x2186, 0x21c6, 0x2a07, 0x3228, 0x4228, 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x528a, 0x94b2, 0x8410, 0x52aa, 0x52aa, 0x52aa, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xbdd7, 0x52aa, 0x52aa, 0xa534, 0xd69a, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xc618, 0x8c71, 0x7bcf, 0x4a49, 0x4228, 0x4228, 0x8c71, 0xe73c, 0x4228, 0x630c, 0x4208, 0x8c51, 0x8c51, 0xad55, 0xe71c, 0xc638, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xd6ba, 0xdeba, 0xd656, 0xd5ce, 0xd527, 0xd4e5, 0x9ba3, 0x2901, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c1, 0x6264, 0x9bc5, 0xc4a5, 0xd505, 0xd525, 0xd549, 0xd5ae, 0xd634, 0xde98, 0xdeba, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x1904, 0x08e3, 0x0903, 0x0944, 0x0985, 0x09c6, 0x09e6, 0x09e6, 0x21e7, 0x3a08, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, 0x8410, 0xef7d, 0xef7d, 0xd6ba, 0xad55, 0x8430, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x5aeb, 0x630c, 0x5aeb, 0xbdf7, 0xf7be, 0xf7be, 0xf7be, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0x5acb, 0x52aa, 0x52aa, 0x52aa, 0x528a, 0xd69a, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0x8c71, 0xbdf7, 0x8430, 0x7bcf, 0x8c71, 0x4228, 0x73ae, 0x4228, 0x630c, 0x4208, 0x9cd3, 0x4208, 0x4208, 0xce79, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xd698, 0xd612, 0xd56b, 0xd504, 0xbc85, 0x5a43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e1, 0x6a83, 0x9bc4, 0xc4c6, 0xd505, 0xd526, 0xd569, 0xd5cf, 0xd655, 0xd698, 0xd6b9, 0xdeba, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x4208, 0x4208, 0x4208, 0x4208, 0x2986, 0x08c3, 0x08e3, 0x0903, 0x0924, 0x0965, 0x09c6, 0x09e7, 0x09e6, 0x09c6, 0x0985, 0x31c7, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x4228, 0xad75, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xbdf7, 0x8c51, 0x5aeb, 0x5aeb, 0x630c, 0x630c, 0x630c, 0x630c, 0x630c, 0x8c71, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf79e, 0xad75, 0x5acb, 0x5acb, 0x4228, 0x3186, 0x39c7, 0xb596, 0xdefb, 0xef5d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xbdd7, 0x9492, 0x4228, 0x4228, 0x4228, 0x4228, 0x4208, 0x4208, 0x4208, 0x4208, 0x9cd3, 0xbdf7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeb9, 0xde55, 0xd5ad, 0xdd27, 0xd506, 0x93a5, 0x20e1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3143, 0x9bc5, 0xc4c5, 0xd4e3, 0xd4e3, 0xd505, 0xd58c, 0xd633, 0xd698, 0xd6b9, 0xd6ba, 0xd6ba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xb5b6, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xad55, 0x4208, 0x4208, 0x4208, 0x4208, 0x08e3, 0x08c3, 0x08c3, 0x0903, 0x0924, 0x0965, 0x09a6, 0x09e6, 0x09e7, 0x09c6, 0x0985, 0x0924, 0x4228, 0x4a69, 0x528a, 0x39e7, 0x08c2, 0x2165, 0x632c, 0x8c92, 0xb5b6, 0xd69a, 0xef7d, 0xf7be, 0xf7be, 0x9cf3, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x632c, 0xdefb, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xdedb, 0x5aeb, 0x5acb, 0x52aa, 0x18e3, 0x0861, 0x0861, 0x4208, 0x73ae, 0x4208, 0x9cd3, 0x9492, 0xd69a, 0xdefb, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0x7bcf, 0x9cf3, 0x8c71, 0x4228, 0x4208, 0x4208, 0x4208, 0x4208, 0x9cd3, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdeba, 0xde97, 0xde11, 0xdd47, 0xd526, 0xbc86, 0x6244, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3121, 0x6a82, 0x9b82, 0xbc63, 0xd505, 0xd58b, 0xd612, 0xd677, 0xd6b9, 0xd6ba, 0xdeba, 0xdeda, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0x738e, 0x39e7, 0xc638, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0x9cf3, 0x4208, 0x4228, 0x4228, 0x1924, 0x08c3, 0x08e3, 0x0965, 0x0985, 0x09a6, 0x09e7, 0x0a28, 0x0a28, 0x09e7, 0x09a6, 0x0945, 0x31c6, 0x528a, 0x4a49, 0x0903, 0x08c2, 0x08c2, 0x08c2, 0x0903, 0x0965, 0x0965, 0x3a69, 0x73cf, 0x9d34, 0xce79, 0x9cf3, 0x632c, 0x632c, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0xb5b6, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xa514, 0x5aeb, 0x5aeb, 0x39c7, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x10a2, 0x0861, 0x0861, 0x632c, 0x4228, 0xce59, 0x7bcf, 0xa534, 0xdefb, 0xdedb, 0xe73c, 0xe73c, 0xce79, 0x4228, 0xe73c, 0xce59, 0xbdf7, 0x8c51, 0x4208, 0x4208, 0xbdd7, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdeb8, 0xde54, 0xdd8c, 0xdd25, 0xd505, 0x93a5, 0x20e1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4181, 0x7ae3, 0xa3e5, 0xc4a5, 0xd548, 0xd5cf, 0xde55, 0xde77, 0xdeb9, 0xdeba, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xbdd7, 0x39e7, 0x39e7, 0x39e7, 0x8430, 0xce59, 0xe73c, 0xe71c, 0xe73c, 0xad75, 0x4208, 0x4208, 0x4208, 0x2985, 0x08e3, 0x0985, 0x09c6, 0x0a27, 0x0a28, 0x09e7, 0x0a07, 0x0a68, 0x0aa9, 0x0a69, 0x09c6, 0x2165, 0x4a69, 0x2185, 0x08e3, 0x08c2, 0x08c2, 0x08a2, 0x0903, 0x0944, 0x0965, 0x0965, 0x0965, 0x0985, 0x0985, 0x2a28, 0x3a28, 0x52cb, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0xad55, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xe71c, 0x630c, 0x630c, 0x52aa, 0x2104, 0x3186, 0x0861, 0x0861, 0x31a6, 0x0861, 0x6b4d, 0x0861, 0x39c7, 0x4a49, 0x6b4d, 0xad55, 0x0861, 0x0861, 0x4a69, 0x0861, 0x8c51, 0x7bcf, 0xbdd7, 0xc618, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xbdf7, 0xce59, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdeda, 0xde97, 0xddcf, 0xdd46, 0xdd26, 0xbc86, 0x5a43, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18a1, 0x5202, 0x8b43, 0xac25, 0xcd07, 0xdd8c, 0xddf0, 0xde54, 0xde98, 0xdeda, 0xdeda, 0xdedb, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0x8430, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x8c51, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x31c7, 0x0944, 0x09a6, 0x09a5, 0x09e7, 0x0a27, 0x0a68, 0x0a28, 0x0a07, 0x0a28, 0x0a89, 0x0a89, 0x09c6, 0x31e7, 0x0903, 0x08e3, 0x08c2, 0x08e3, 0x08c2, 0x08c3, 0x0944, 0x0965, 0x0965, 0x0965, 0x0985, 0x0985, 0x09a6, 0x0985, 0x0965, 0x3a28, 0x632c, 0x738e, 0x738e, 0x738e, 0xffff, 0xffff, 0xffff, 0xffff, 0x9492, 0x632c, 0x630c, 0x5acb, 0x39e7, 0x5acb, 0xc638, 0xc618, 0xbdd7, 0x39e7, 0x7bcf, 0x0861, 0x4208, 0x0861, 0x6b4d, 0x8c51, 0x0861, 0x2945, 0x2945, 0x8430, 0x10a2, 0x10a2, 0x10a2, 0x94b2, 0x738e, 0xdedb, 0xad75, 0xb5b6, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdeb9, 0xde32, 0xdd8a, 0xdd47, 0xd506, 0x8b86, 0x20c1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e1, 0x6262, 0x9384, 0xb465, 0xd548, 0xddce, 0xde33, 0xde76, 0xdeb9, 0xdeda, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x39e7, 0x39e7, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4208, 0x31e7, 0x2186, 0x52ca, 0x634d, 0x1144, 0x09a6, 0x0a48, 0x0a89, 0x0a68, 0x0a48, 0x0a68, 0x0a48, 0x0965, 0x0924, 0x08e3, 0x0924, 0x0965, 0x0944, 0x0924, 0x0965, 0x09a6, 0x0985, 0x0965, 0x0965, 0x0985, 0x09a6, 0x0985, 0x0965, 0x0965, 0x1985, 0x632c, 0x73ae, 0x738e, 0xdedb, 0xffff, 0xffff, 0xb596, 0x6b4d, 0x632c, 0x4208, 0x2124, 0x31a6, 0x7bef, 0xe73c, 0xf7be, 0xef5d, 0xc618, 0x528a, 0x4228, 0x73ae, 0x7bcf, 0x8c71, 0x10a2, 0x4a49, 0x94b2, 0x3186, 0x7bcf, 0x2945, 0x4a49, 0x0861, 0x2104, 0x2945, 0x8c51, 0x0861, 0x39c7, 0xdefb, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde76, 0xdd8a, 0xdd46, 0xdd25, 0xd56b, 0xac8d, 0x6b09, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3961, 0x72c3, 0x9bc4, 0xcce6, 0xddab, 0xde33, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x3186, 0x0903, 0x0924, 0x0903, 0x08e3, 0x0944, 0x0965, 0x0a68, 0x0aca, 0x0aca, 0x0aa9, 0x0a89, 0x09c6, 0x0924, 0x0903, 0x0985, 0x09c6, 0x09e7, 0x09e6, 0x09a6, 0x09c6, 0x0a27, 0x0a07, 0x09e7, 0x09e7, 0x09e6, 0x09a6, 0x0985, 0x0965, 0x0944, 0x2165, 0x6b6d, 0x7bcf, 0xffff, 0xffff, 0xffff, 0x6b6d, 0x6b4d, 0x5acb, 0x0861, 0x0861, 0x0861, 0x0861, 0xb596, 0xf7be, 0xf7be, 0xf7be, 0x7bef, 0x528a, 0x528a, 0x8410, 0xef7d, 0xdedb, 0xe73c, 0xdedb, 0x7bcf, 0x738e, 0x39c7, 0x2104, 0x0861, 0x10a2, 0x528a, 0x2104, 0x0861, 0x94b2, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde75, 0xddcd, 0xdd47, 0xdd25, 0xdd47, 0xddce, 0xc56f, 0x8c2d, 0x4207, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4181, 0xbc85, 0xdd68, 0xde11, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x39e7, 0x08e3, 0x08e3, 0x0944, 0x0903, 0x08e3, 0x0924, 0x0965, 0x0a48, 0x0aa9, 0x0aea, 0x0b0b, 0x0aca, 0x09c6, 0x0924, 0x0985, 0x0944, 0x0965, 0x09e7, 0x09e7, 0x09e7, 0x09e7, 0x09e7, 0x09e7, 0x0a48, 0x0a89, 0x0aa9, 0x0a89, 0x0a28, 0x09c6, 0x0945, 0x0904, 0x5acb, 0x7bef, 0xc638, 0xe71c, 0xce79, 0x738e, 0x6b4d, 0x2945, 0x0861, 0x0861, 0x0861, 0x0861, 0xa514, 0xf7be, 0xf7be, 0xf7be, 0xbdd7, 0x528a, 0x528a, 0x528a, 0xd6ba, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xce59, 0x8c51, 0x94b2, 0xa534, 0xad75, 0x9cd3, 0x4a49, 0x39c7, 0xc638, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xde97, 0xddef, 0xdd69, 0xdd46, 0xdd25, 0xdd47, 0xd5af, 0xacce, 0x6b2a, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41a1, 0xc4a6, 0xdd47, 0xde11, 0xdeb8, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x31a6, 0x08c2, 0x08c2, 0x0924, 0x0904, 0x08e3, 0x0904, 0x09e6, 0x0a48, 0x0a89, 0x0aaa, 0x0aca, 0x0a89, 0x0924, 0x0985, 0x09e7, 0x0985, 0x0944, 0x0944, 0x0985, 0x638d, 0x4aeb, 0x09c6, 0x09c6, 0x09e7, 0x0a48, 0x0aa9, 0x0aca, 0x0aaa, 0x0a89, 0x0a28, 0x0965, 0x3a08, 0x8410, 0x7bef, 0x7bcf, 0x7bcf, 0x738e, 0x4a49, 0x0861, 0x0861, 0x0861, 0x0861, 0x4a49, 0xef5d, 0xffdf, 0xf7be, 0xf7be, 0xdefb, 0x52aa, 0x528a, 0x528a, 0xbdd7, 0xf79e, 0xef7d, 0xef7d, 0xd69a, 0xa514, 0x4208, 0x94b2, 0xd69a, 0xef5d, 0xef5d, 0xce79, 0xd69a, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdeda, 0xde98, 0xde54, 0xddce, 0xdd48, 0xdd25, 0xdd48, 0xdd8c, 0xc570, 0x942d, 0x4a27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49c2, 0xc4a5, 0xdd46, 0xddf0, 0xdeb7, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0x8c51, 0x39e7, 0x39e7, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x39e7, 0x08c2, 0x08c2, 0x0944, 0x0924, 0x0924, 0x0944, 0x0985, 0x09e7, 0x0a28, 0x0a68, 0x0a69, 0x09a5, 0x0944, 0x0985, 0x0985, 0x0985, 0x0965, 0x0965, 0x73cf, 0xffdf, 0xffdf, 0xa534, 0x52cb, 0x3a69, 0x19e7, 0x0a27, 0x0a69, 0x0aa9, 0x0a89, 0x0a89, 0x0a68, 0x1985, 0x7bef, 0x8410, 0x7bef, 0x7bcf, 0x632c, 0x1082, 0x0861, 0x0861, 0x0861, 0x0861, 0xc618, 0xffdf, 0xdedb, 0x9492, 0xb5b6, 0xd6ba, 0x94b2, 0x528a, 0x528a, 0x8410, 0xf79e, 0xc638, 0x9492, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4228, 0x5aeb, 0x8c71, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdeda, 0xde97, 0xddf0, 0xdd6a, 0xdd26, 0xdd26, 0xdd47, 0xd58d, 0xaccd, 0x732a, 0x18e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49e2, 0xc4c5, 0xdd46, 0xddef, 0xde98, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xad75, 0x8c51, 0x4208, 0x4208, 0x4208, 0x31a6, 0x31c7, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x10e3, 0x0924, 0x0965, 0x0944, 0x0944, 0x0944, 0x0924, 0x0944, 0x0985, 0x09a6, 0x0944, 0x08e3, 0x09c6, 0x09a6, 0x0965, 0x0965, 0x0965, 0x21e7, 0xb5b6, 0xa514, 0x632c, 0x632c, 0x6b4d, 0x6b6d, 0x6b6d, 0x428a, 0x0a48, 0x0a89, 0x0a89, 0x0a68, 0x0a27, 0x09c6, 0x73ae, 0x8430, 0x7bef, 0x7bcf, 0x3186, 0x0861, 0x0861, 0x0861, 0x0861, 0x3186, 0xc618, 0xffff, 0xef7d, 0x2124, 0x0861, 0x0861, 0x4228, 0x4a69, 0x528a, 0x528a, 0x8410, 0x4a69, 0x4a69, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4a49, 0x4228, 0x4228, 0xb596, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xde98, 0xde34, 0xddcf, 0xdd47, 0xdd04, 0xd525, 0xd569, 0xc54e, 0x940b, 0x4a27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5203, 0xccc5, 0xdd68, 0xde10, 0xdeb9, 0xdedb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xbdf7, 0x9cf3, 0x6b4d, 0x08e3, 0x08e3, 0x2165, 0x31c7, 0x39e7, 0x3a07, 0x7bef, 0x4249, 0x0985, 0x09c6, 0x09a6, 0x0965, 0x0985, 0x1185, 0x1965, 0x0903, 0x08e3, 0x08a2, 0x0924, 0x09c6, 0x09a6, 0x0985, 0x0985, 0x09a6, 0x3a49, 0x5aeb, 0x630c, 0x632c, 0x6b4d, 0x6b4d, 0x6b6d, 0x738e, 0x3208, 0x09e7, 0x0a89, 0x0a89, 0x0a48, 0x09c6, 0x0944, 0xad96, 0x9cd3, 0x8410, 0x52aa, 0x0861, 0x0861, 0x0861, 0x0861, 0x18c3, 0x5aeb, 0x630c, 0xffff, 0xffff, 0x9cd3, 0x0861, 0x0861, 0x0861, 0x39c7, 0x528a, 0x528a, 0x4a69, 0x4a69, 0x4a49, 0x39c7, 0x39e7, 0x4228, 0x4a49, 0x4228, 0x7bcf, 0xad55, 0xd69a, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdedb, 0xdedb, 0xdeda, 0xdeba, 0xde98, 0xde11, 0xdd6a, 0xd504, 0xd504, 0xd505, 0xd549, 0xb445, 0x7305, 0x2102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a22, 0xcce6, 0xdd69, 0xde10, 0xded9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0x634d, 0x08c2, 0x08e3, 0x0903, 0x0924, 0x0944, 0x0944, 0x0924, 0x08e3, 0x0944, 0x09a6, 0x09a6, 0x0985, 0x0965, 0x31c7, 0x29a6, 0x08e3, 0x08e3, 0x08c2, 0x0944, 0x0985, 0x0985, 0x0965, 0x0944, 0x21c6, 0x5acb, 0x5aeb, 0x630c, 0x632c, 0x6b4d, 0x6b4d, 0x6b6d, 0x4aaa, 0x0944, 0x0985, 0x0a69, 0x0a68, 0x0a28, 0x09a6, 0x0965, 0x3a69, 0x4228, 0x528a, 0x10a2, 0x0861, 0x0861, 0x0861, 0x0861, 0x4a69, 0x632c, 0x630c, 0xffff, 0xffff, 0xc638, 0x31a6, 0x0861, 0x0861, 0x10a2, 0x4a69, 0x4a69, 0x4208, 0x2965, 0x10a2, 0x0861, 0x0861, 0x1082, 0x39e7, 0x7bcf, 0xdefb, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdedb, 0xdeda, 0xdeda, 0xdeb9, 0xde97, 0xde54, 0xde12, 0xddcf, 0xdd6a, 0xdd25, 0xd504, 0xc4a4, 0xac04, 0x8b64, 0x6aa4, 0x2943, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a42, 0xccc5, 0xdd68, 0xde10, 0xdeb9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xe71c, 0x3a28, 0x08a2, 0x08e3, 0x08e3, 0x0924, 0x0944, 0x0965, 0x0944, 0x08e3, 0x08e3, 0x0965, 0x09a6, 0x09a6, 0x0985, 0x1185, 0x0924, 0x08e3, 0x08e3, 0x0924, 0x0924, 0x0944, 0x0965, 0x09a6, 0x11a6, 0x4a8a, 0x5aeb, 0x5aeb, 0x630c, 0x632c, 0x632c, 0x634d, 0x4289, 0x09a6, 0x0965, 0x0985, 0x0a89, 0x0a89, 0x0a27, 0x09c6, 0x0944, 0x0903, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x31a6, 0x9cf3, 0x630c, 0xa534, 0xb5b6, 0x5aeb, 0x5acb, 0x4228, 0x0861, 0x0861, 0x0861, 0x2945, 0x18e3, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0xb596, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdeda, 0xdeda, 0xdeb8, 0xde54, 0xddee, 0xdd69, 0xdd46, 0xdd26, 0xcce6, 0xb444, 0x9b83, 0x72c2, 0x49c2, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6242, 0xcce5, 0xdd68, 0xde32, 0xdeb9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0x7bef, 0x08a2, 0x0924, 0x0903, 0x0924, 0x0944, 0x0944, 0x0944, 0x0903, 0x08e3, 0x0985, 0x09c6, 0x0985, 0x0965, 0x0965, 0x0924, 0x0903, 0x0924, 0x09a6, 0x09a6, 0x0965, 0x0944, 0x0965, 0x3a28, 0x5acb, 0x5aeb, 0x5aeb, 0x630c, 0x630c, 0x52aa, 0x2a28, 0x09a6, 0x09a6, 0x0985, 0x09c6, 0x0aa9, 0x0aa9, 0x0a68, 0x09e7, 0x0965, 0x08c3, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x39c7, 0x630c, 0x5aeb, 0x5aeb, 0x5acb, 0x528a, 0x18e3, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x4a49, 0x9492, 0xd6ba, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe6fb, 0xded9, 0xde96, 0xde53, 0xde10, 0xddac, 0xdd68, 0xdd45, 0xd505, 0xbc64, 0xa3c4, 0x8303, 0x5a22, 0x20c1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6a62, 0xd4e6, 0xdd68, 0xde32, 0xdeb8, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xa555, 0x08a2, 0x0944, 0x0944, 0x0965, 0x0944, 0x0965, 0x0965, 0x0924, 0x0924, 0x0985, 0x0965, 0x0924, 0x0944, 0x0965, 0x0944, 0x0924, 0x0985, 0x09c6, 0x09c6, 0x09e7, 0x09a6, 0x0965, 0x21a6, 0x31e7, 0x3a28, 0x3269, 0x3248, 0x11a6, 0x0985, 0x09e6, 0x09a6, 0x0985, 0x09a6, 0x09e6, 0x0a48, 0x0a89, 0x0a68, 0x0a07, 0x3269, 0x7c10, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x5acb, 0x52aa, 0x4208, 0x2945, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x4a69, 0x94b2, 0xce59, 0xef7d, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71b, 0xe6fb, 0xe6d9, 0xe674, 0xe630, 0xe5aa, 0xdd68, 0xdd47, 0xdd47, 0xccc6, 0xac25, 0x8b64, 0x6284, 0x3142, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6aa3, 0xd505, 0xdd48, 0xde54, 0xdeb9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xce79, 0x0944, 0x0965, 0x0985, 0x0985, 0x0985, 0x0985, 0x09a6, 0x09a6, 0x0985, 0x0985, 0x0965, 0x0945, 0x0985, 0x0985, 0x0965, 0x09a6, 0x0a07, 0x0a07, 0x09e7, 0x09e7, 0x09e7, 0x0985, 0x0924, 0x0944, 0x0985, 0x0a07, 0x09e7, 0x0985, 0x0965, 0x09c6, 0x09c6, 0x0985, 0x0a27, 0x0a48, 0x0a28, 0x0a48, 0x0a48, 0x0a28, 0xa555, 0xb5b6, 0x0861, 0x0861, 0x0861, 0x0861, 0x2104, 0x2124, 0x0861, 0x0861, 0x2945, 0x4228, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x10a2, 0x3186, 0xb5b6, 0xf79e, 0xf7be, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe6f9, 0xe631, 0xe5cc, 0xe568, 0xe568, 0xd507, 0xb466, 0x93a5, 0x72a3, 0x4182, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72c3, 0xd505, 0xdd69, 0xde33, 0xdeb9, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xb5b6, 0x52eb, 0x09a6, 0x0985, 0x0944, 0x0924, 0x0944, 0x0985, 0x0965, 0x0965, 0x0944, 0x636d, 0x532c, 0x0985, 0x09c6, 0x0a28, 0x0a27, 0x0a28, 0x0a07, 0x0a07, 0x09c6, 0x0965, 0x0944, 0x0944, 0x0965, 0x09e6, 0x0a07, 0x09a6, 0x0965, 0x09c6, 0x09e7, 0x09c6, 0x0a48, 0x0a89, 0x0aca, 0x0aa9, 0x0a69, 0x6c0f, 0xf7be, 0xc618, 0x0861, 0x0861, 0x0861, 0x1082, 0x5acb, 0x6b4d, 0x4228, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x18c3, 0x0861, 0x0861, 0x2104, 0x4a49, 0xad55, 0xf7be, 0xf7be, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe6d8, 0xe5ec, 0xe589, 0xe566, 0x9be6, 0x1081, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72c3, 0xd4e4, 0xdd6a, 0xde32, 0xdeb9, 0xdeda, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xe73c, 0xc659, 0x9d13, 0x73ef, 0x4aca, 0x4289, 0x428a, 0x5b4d, 0x8c92, 0xc638, 0xf79e, 0x9d14, 0x0985, 0x0a69, 0x0a89, 0x0a28, 0x0a07, 0x0a07, 0x0a28, 0x09e7, 0x0985, 0x0944, 0x0924, 0x0944, 0x09c6, 0x0a07, 0x09c6, 0x0965, 0x09a6, 0x0a27, 0x0a28, 0x0a48, 0x0a69, 0x0aca, 0x0aea, 0x53ef, 0xef7d, 0xffff, 0xe73c, 0x18c3, 0x0861, 0x0861, 0x0861, 0x18c3, 0x2965, 0x39c7, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x2124, 0x7bef, 0xc638, 0xc618, 0x0861, 0x0861, 0x0861, 0x39c7, 0x8410, 0xf7be, 0xf7be, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe6f9, 0xe5ee, 0xe567, 0xdd68, 0x8326, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7ae3, 0xd505, 0xdd04, 0xdd26, 0xdd48, 0xdd69, 0xdd6a, 0xdd8b, 0xdd8b, 0xddab, 0xddab, 0xddcc, 0xddee, 0xddee, 0xde0f, 0xe60f, 0xe630, 0xe674, 0xe6b7, 0xe6d7, 0xe6d8, 0xe6d7, 0xe6f9, 0xe71b, 0xe73c, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xc659, 0x0a07, 0x0a89, 0x0a89, 0x0a28, 0x09c6, 0x09c6, 0x0a07, 0x0a48, 0x0a27, 0x09c6, 0x0985, 0x0985, 0x09c6, 0x0a27, 0x09e6, 0x09a5, 0x09a6, 0x09c6, 0x0a07, 0x0a48, 0x0a68, 0x0a89, 0x7491, 0xef7d, 0xffff, 0xffff, 0xffff, 0x9492, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x5aeb, 0xad55, 0xb5b6, 0x9492, 0x630c, 0x52aa, 0xad55, 0xe73c, 0xffff, 0xffff, 0xffdf, 0x5acb, 0x0861, 0x0861, 0x10a2, 0x4228, 0xce59, 0x9cf3, 0x632c, 0x9492, 0xd6ba, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe6d8, 0xe60f, 0xe588, 0xdd69, 0x7b06, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3961, 0x49c2, 0x5202, 0x5a22, 0x6a62, 0x6aa3, 0x7ae3, 0x8303, 0x8b44, 0x8b64, 0x93a4, 0x9bc5, 0xa3e5, 0xac25, 0xb446, 0xb466, 0xbca6, 0xc4c7, 0xcce7, 0xcd08, 0xd528, 0xdd68, 0xe5cc, 0xe693, 0xe71b, 0xef3c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xef7d, 0xadd7, 0x84d2, 0x536d, 0x1a68, 0x0a07, 0x09c6, 0x09e6, 0x0a28, 0x0a48, 0x0a48, 0x09e7, 0x0985, 0x0965, 0x0985, 0x09a6, 0x0985, 0x0944, 0x0924, 0x0965, 0x09a6, 0x3aeb, 0xb5d7, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xf7be, 0xad55, 0x39e7, 0x0861, 0x0861, 0x0861, 0x52aa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xb5b6, 0x0861, 0x0861, 0x0861, 0x630c, 0x9cd3, 0x3186, 0x2124, 0x31a6, 0xa534, 0xf79e, 0xf79e, 0xf79e, 0xef7d, 0xf79e, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe6b6, 0xe60f, 0xe567, 0xdd6a, 0x72e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0xbc86, 0xe60f, 0xe6b6, 0xe73b, 0xef3c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xe75d, 0xce79, 0xa575, 0x7c71, 0x434c, 0x0a89, 0x0a68, 0x0a28, 0x09c6, 0x0944, 0x0924, 0x0965, 0x0965, 0x0944, 0x21c6, 0x634c, 0xb5b6, 0xf79e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf79e, 0xce79, 0x9cf3, 0x7bcf, 0x5acb, 0xf79e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef7d, 0x9cf3, 0x73ae, 0x39e7, 0x630c, 0xb596, 0x0861, 0x0861, 0x39e7, 0xce59, 0xf79e, 0xf79e, 0xf79e, 0xf79d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe696, 0xe5ec, 0xe568, 0xdd48, 0x6ae6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20c1, 0xb446, 0xe5aa, 0xe651, 0xe71b, 0xef3c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xe73c, 0xce9a, 0xb5f7, 0x9d34, 0x94b2, 0x94b2, 0x9d34, 0xad75, 0xc659, 0xef5d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf79e, 0xdefb, 0xe71c, 0x94b2, 0x9cf3, 0xad55, 0xf7be, 0xf7be, 0xf79e, 0xf77c, 0xf739, 0xf6f6, 0xef39, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe6b6, 0xe5cc, 0xe568, 0xd548, 0x62a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa3e5, 0xe5a9, 0xe630, 0xe6f9, 0xef3c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf79e, 0xf738, 0xf671, 0xf62e, 0xf64f, 0xf64f, 0xee91, 0xeed6, 0xef3a, 0xef5c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71b, 0xe6b7, 0xe5ab, 0xe567, 0xd549, 0x6285, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8b65, 0xe588, 0xe631, 0xe6f8, 0xef3c, 0xef3c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xf79d, 0xf738, 0xf670, 0xf5ea, 0xf5eb, 0xf62c, 0xee0b, 0xedeb, 0xee0c, 0xee71, 0xeeb5, 0xeef8, 0xef19, 0xef3b, 0xef3c, 0xef3c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71b, 0xe695, 0xe5cc, 0xe568, 0xd549, 0x6264, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b05, 0xe568, 0xe60f, 0xe6d7, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xf7be, 0xf738, 0xf670, 0xf5eb, 0xd54b, 0x8bca, 0xb4ce, 0xcd6e, 0xe60d, 0xedeb, 0xedca, 0xedeb, 0xedec, 0xee2e, 0xee73, 0xeed7, 0xef1a, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe73c, 0xe71c, 0xe71b, 0xe695, 0xe5cd, 0xe546, 0xd54b, 0x5a45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6aa3, 0xdd48, 0xe5ed, 0xe6d7, 0xe73b, 0xe73c, 0xef5d, 0xef5d, 0xef5d, 0xef3b, 0xef19, 0xeef8, 0xeeb4, 0xee71, 0xee70, 0xeed5, 0xf75a, 0xf79e, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff12, 0xfed0, 0xff34, 0xffbb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xf759, 0xf691, 0xf5eb, 0xcd2c, 0x0000, 0x0000, 0x0000, 0x2924, 0x62e9, 0x93ea, 0xb48a, 0xcd2b, 0xe5cc, 0xedca, 0xeda9, 0xedca, 0xe60e, 0xe674, 0xe6b6, 0xe6d8, 0xe6f9, 0xe6fa, 0xe71b, 0xe71c, 0xe71b, 0xe674, 0xe5ab, 0xe567, 0xcd29, 0x5224, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5a23, 0xdd48, 0xe5cb, 0xe6b7, 0xe73b, 0xef3c, 0xef3c, 0xef3b, 0xef19, 0xeeb4, 0xee50, 0xedec, 0xedca, 0xdd69, 0xcd29, 0xedea, 0xee2d, 0xf718, 0xf79e, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffc, 0xff76, 0xff76, 0xfffd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffba, 0xfed0, 0xfeae, 0xfe8e, 0xfed1, 0xff57, 0xffdd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffde, 0xf7be, 0xf79c, 0xf6b3, 0xf60b, 0xdd8c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3163, 0x6ac7, 0x93c9, 0xb48a, 0xcd2a, 0xe58a, 0xe5aa, 0xe5cb, 0xe5cc, 0xe5cd, 0xe60f, 0xe673, 0xe6b7, 0xe6d8, 0xe653, 0xe5aa, 0xe567, 0xcd08, 0x5205, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49e2, 0xcd08, 0xe5cc, 0xe6b5, 0xe71a, 0xe71b, 0xe6f9, 0xeeb5, 0xee30, 0xedcb, 0xedca, 0xd54a, 0xac27, 0x72c5, 0x20c1, 0xa407, 0xedeb, 0xf670, 0xf719, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff77, 0xfecf, 0xfecf, 0xff33, 0xfffc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xff76, 0xfed0, 0xbceb, 0xc50b, 0xfe8f, 0xfeaf, 0xff13, 0xffbc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xf7be, 0xf7be, 0xf6d5, 0xf60b, 0xe5ed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3984, 0x6ac6, 0x93a7, 0xac47, 0xcce8, 0xe589, 0xe588, 0xe588, 0xe5aa, 0xe5ed, 0xe5cd, 0xe567, 0xe547, 0xcd09, 0x49e4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3962, 0xc4a6, 0xe5cb, 0xe672, 0xe6f9, 0xe673, 0xe60f, 0xe5cb, 0xeda9, 0xcd08, 0x9be6, 0x6284, 0x1081, 0x0000, 0x0000, 0x0000, 0xbcc9, 0xedeb, 0xf6b3, 0xf75a, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffdf, 0xffdf, 0xffde, 0xffde, 0xffde, 0xffde, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xff77, 0xfef1, 0xfed0, 0xfecf, 0xfecf, 0xff54, 0xfffc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xff55, 0xfed0, 0x7b69, 0x0000, 0x8389, 0xee2e, 0xfeaf, 0xfed1, 0xff78, 0xffdd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffdf, 0xffbe, 0xf6f5, 0xf62c, 0xee2e, 0x3163, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3162, 0x6aa5, 0x93a6, 0xac46, 0xccc6, 0xdd47, 0xe567, 0xdd46, 0xe546, 0xcd09, 0x41c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2901, 0xbc86, 0xe587, 0xe5aa, 0xe5ec, 0xe5a9, 0xe568, 0xc4c7, 0x93a6, 0x5a24, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdd6a, 0xf60c, 0xf6f7, 0xf77c, 0xf79e, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffde, 0xffde, 0xffbd, 0xff16, 0xfed2, 0xfef3, 0xff79, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffb9, 0xff32, 0xff12, 0xaced, 0xacec, 0xff11, 0xfed0, 0xff75, 0xfffc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff54, 0xfeb0, 0x41e5, 0x0000, 0x0000, 0x39a4, 0xbccb, 0xfe8f, 0xfe8f, 0xff14, 0xffbb, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffbe, 0xf6f5, 0xf62c, 0xf64d, 0x4a05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3983, 0x6ac4, 0x9385, 0xac25, 0xccc6, 0xc4ea, 0x41c4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20c1, 0xac26, 0xe567, 0xe567, 0xdd47, 0xbc87, 0x8b86, 0x49c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41c3, 0xedeb, 0xf64e, 0xf718, 0xf79d, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffbe, 0xffbd, 0xff59, 0xfeb1, 0xfe6e, 0xfe6d, 0xfe8e, 0xff14, 0xffdd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xff55, 0xfef0, 0xde53, 0x2103, 0x0000, 0xacee, 0xff11, 0xff11, 0xff75, 0xfffd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff11, 0xe60e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7327, 0xe5ee, 0xfe8f, 0xfed1, 0xff57, 0xffde, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffdf, 0xffbe, 0xf6f6, 0xf64d, 0xf64d, 0x62a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41a3, 0x41e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9be6, 0xdd27, 0xb446, 0x8324, 0x41a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b05, 0xf5eb, 0xf690, 0xf739, 0xf79d, 0xf7be, 0xf7be, 0xf7be, 0xf7be, 0xffbd, 0xff7a, 0xfef4, 0xfe6e, 0xfe4d, 0xf66f, 0xee0d, 0xfe6e, 0xfed1, 0xff78, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff97, 0xff12, 0xf713, 0x62e8, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff32, 0xff11, 0xff75, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffc, 0xfef1, 0xc54d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3163, 0xb4ab, 0xfe6e, 0xfeaf, 0xfef3, 0xffbb, 0xffde, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffdf, 0xffde, 0xff37, 0xf66e, 0xf64d, 0x7b26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41a3, 0x72e5, 0x3121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9be7, 0xf60c, 0xf6b3, 0xf75b, 0xf79d, 0xf7be, 0xf7be, 0xf7be, 0xff7b, 0xfef4, 0xfe6f, 0xfe4d, 0xfe90, 0xd5af, 0x6ae8, 0x7b48, 0xfeb0, 0xfe8e, 0xff14, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffb, 0xff33, 0xff33, 0xa4ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff11, 0xff12, 0xff75, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffc, 0xfef1, 0xa48c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6ac6, 0xddcd, 0xfe8e, 0xfeb0, 0xff58, 0xffdd, 0xffff, 0xffff, 0xffff, 0xffdf, 0xffde, 0xff37, 0xf66f, 0xf64d, 0x8b88, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbca8, 0xf60c, 0xf6f6, 0xf77c, 0xf7be, 0xf7be, 0xf77c, 0xf716, 0xf66f, 0xfe4d, 0xfe4d, 0xe610, 0x83aa, 0x18a2, 0x0000, 0x0000, 0xcd8f, 0xfe6e, 0xfed1, 0xff98, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff54, 0xff11, 0xd674, 0x2123, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff11, 0xff11, 0xff75, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffb9, 0xfef1, 0x7b69, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2943, 0xa449, 0xf64e, 0xfe8f, 0xff14, 0xff9b, 0xfffe, 0xffff, 0xffdf, 0xffdf, 0xff37, 0xfe8f, 0xf64d, 0x9be8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd54a, 0xf62d, 0xf75a, 0xf79d, 0xf77c, 0xf738, 0xf691, 0xfe4d, 0xfe4d, 0xee50, 0xa46c, 0x2943, 0x0000, 0x0000, 0x0000, 0x0000, 0x62a7, 0xfe8f, 0xfeaf, 0xfef2, 0xffdd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffe, 0xffb8, 0xfef1, 0xf6f3, 0x62e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0d, 0xff11, 0xff11, 0xff97, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff97, 0xfef2, 0x41e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6286, 0xd58d, 0xfe6e, 0xfed1, 0xff37, 0xffbd, 0xffde, 0xffdf, 0xff79, 0xfeb1, 0xfe4d, 0xac49, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x41a3, 0xedeb, 0xf64e, 0xf75a, 0xf75a, 0xf6d4, 0xf62d, 0xf62d, 0xf64f, 0xb4ed, 0x4a06, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xbd2e, 0xfeaf, 0xfeb0, 0xff77, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffb, 0xff33, 0xff32, 0xa4cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaced, 0xff32, 0xff12, 0xffb8, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffd, 0xff96, 0xe650, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20e2, 0x9c09, 0xf62e, 0xfe8e, 0xfed1, 0xff9c, 0xffde, 0xff79, 0xfed2, 0xfe4d, 0xb48a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x72e5, 0xf60c, 0xf66f, 0xf6b2, 0xf66f, 0xf62c, 0xf66e, 0xcd8e, 0x6ae8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a06, 0xf690, 0xfeaf, 0xff12, 0xffdc, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffc, 0xff76, 0xff32, 0xd652, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff32, 0xff32, 0xffb8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffc, 0xff75, 0xc56e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5205, 0xcd2b, 0xfe6e, 0xfeb0, 0xff36, 0xff36, 0xfed2, 0xfe4d, 0xc4ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9bc7, 0xf60b, 0xf60b, 0xf60b, 0xf62c, 0xddce, 0x838a, 0x18a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xacad, 0xfeb0, 0xfed0, 0xffb9, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff98, 0xff11, 0xf714, 0x5ac8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff31, 0xff53, 0xffb8, 0xffff, 0xffff, 0xffff, 0xffff, 0xfffb, 0xff53, 0xa4ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8ba8, 0xeded, 0xfe6d, 0xfe8f, 0xfe8f, 0xfe4d, 0xcd2b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb489, 0xf60b, 0xf60c, 0xe60e, 0x9c2a, 0x2943, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3184, 0xee2f, 0xfed0, 0xff33, 0xffdb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffda, 0xff55, 0xff75, 0x9ccf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0d, 0xff32, 0xff53, 0xffb8, 0xffff, 0xffff, 0xffff, 0xffda, 0xff33, 0x7b89, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x49e4, 0xc4eb, 0xfe4d, 0xfe4d, 0xfe4d, 0xdd6b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd54b, 0xee0e, 0xb4ab, 0x41e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x940b, 0xfef1, 0xfef1, 0xff98, 0xfffe, 0xffff, 0xffff, 0xfffe, 0xff76, 0xff53, 0xd654, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0d, 0xff32, 0xff33, 0xffd8, 0xffff, 0xfffd, 0xffb8, 0xff13, 0x41e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b27, 0xe5cc, 0xfe4d, 0xe5ed, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x39c7, 0xc5b4, 0x6ae7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2103, 0xde0f, 0xfef1, 0xff34, 0xffdb, 0xffff, 0xffff, 0xff97, 0xff32, 0xf736, 0x52a8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xaced, 0xff32, 0xff32, 0xffb7, 0xff96, 0xff32, 0xe691, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3983, 0xb48a, 0xee2f, 0x2103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x18c3, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7348, 0xff12, 0xfef0, 0xff77, 0xfffe, 0xfffc, 0xff33, 0xff74, 0x9c8e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0d, 0xff33, 0xff32, 0xff32, 0xff11, 0xc58e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7329, 0x2944, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xcdb0, 0xfed0, 0xff11, 0xff33, 0xff32, 0xff33, 0xd655, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xff32, 0xff32, 0xff11, 0xa48c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x62a7, 0xfed1, 0xfef1, 0xfef1, 0xff12, 0xf734, 0x5268, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0d, 0xff53, 0xff32, 0x7b68, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xb52e, 0xff11, 0xff11, 0xff75, 0x948e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad0e, 0xfef1, 0x41e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4a05, 0xf6b0, 0xff33, 0xce12, 0x18c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x940a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa48c, 0xef15, 0x4a47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2964, 0x73ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; +#define banner_pixel 16200 +#define MAXR 31 +#define MINR 0 +#define MAXG 63 +#define MING 0 +#define MAXB 31 +#define MINB 0 diff --git a/MacGLide/glide2x/sst1/glide/src/fxinline.h b/MacGLide/glide2x/sst1/glide/src/fxinline.h new file mode 100644 index 0000000..b9abb63 --- /dev/null +++ b/MacGLide/glide2x/sst1/glide/src/fxinline.h @@ -0,0 +1,27 @@ +/* + * THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + * PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + * TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + * INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + * DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + * THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + * FULL TEXT OF THE NON-WARRANTY PROVISIONS. + * + * USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + * RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + * TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + * AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + * SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + * THE UNITED STATES. + * + * COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + */ + +#ifndef __FX_INLINE_H__ +#define __FX_INLINE_H__ + +/* The # of 2-byte entries in the hw fog table */ +#define kInternalFogTableEntryCount 0x40UL + +#endif /* __FX_INLINE_H__ */ diff --git a/MacGLide/glide2x/sst1/glide/src/gbanner.c b/MacGLide/glide2x/sst1/glide/src/gbanner.c new file mode 100644 index 0000000..0aae088 --- /dev/null +++ b/MacGLide/glide2x/sst1/glide/src/gbanner.c @@ -0,0 +1,199 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +** +** $Header: /cvsroot/macglide/MacGLide/glide2x/sst1/glide/src/gbanner.c,v 1.2 2005/07/20 20:45:56 jens-olaf Exp $ +** $Log: gbanner.c,v $ +** Revision 1.2 2005/07/20 20:45:56 jens-olaf +** Commented out unwanted code instead of using #define statements +** +** Revision 1.1 2005/07/09 21:28:54 jens-olaf +** Added splash screen and shameless plug +** +** Revision 1.1.1.1 1999/12/07 21:48:52 joseph +** Initial checkin into SourceForge. +** + * + * 9 5/02/97 2:08p Pgj + * screen_width/height now FxU32 + * + * 8 3/16/97 2:24a Jdt + * Fixed bug. Didn't initialize info. + * + * 7 3/12/97 11:51p Jdt + * Watcom warning. + * + * 6 3/12/97 4:20p Jdt + * Fixed for VG96 and optimized SST-1 + * + * 5 2/26/97 11:55a Jdt + * Updated banner for new lfb api + * + * 4 12/23/96 1:37p Dow + * chagnes for multiplatform glide +** +*/ + +/* +#include <3dfx.h> +#include + +#define FX_DLL_DEFINITION +#include +#include +#include "fxglide.h" +*/ + +// OpenGLide specific +#include "../../../driversrc_defines.h" + +#ifdef GLIDE_PLUG +#include "banner.inc" +#endif + +/* display the translucent 3Dfx powerfield logo */ +void +_grShamelessPlug( void ) +{ +// #ifdef GLIDE_PLUG + GrState state; + GrLfbInfo_t info; + + GR_BEGIN_NOFIFOCHECK("_grShamelessPlug",80); + GDBG_INFO_MORE((gc->myLevel,"()\n")); + +// #if ( GLIDE_PLATFORM & GLIDE_HW_SST1 ) + grGlideGetState( &state ); + grDisableAllEffects(); + + grAlphaCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_TEXTURE, FXFALSE ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); + grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, + GR_BLEND_ONE_MINUS_SRC_ALPHA, + GR_BLEND_ZERO, GR_BLEND_ZERO ); + grClipWindow( 0, 0, + Glide.WindowWidth - 1, + Glide.WindowHeight - 1); + grDepthMask(FXFALSE); + grDepthBufferFunction(GR_CMP_ALWAYS); + grDepthBufferMode( GR_DEPTHBUFFER_DISABLE ); + + grChromakeyValue( 0x0000 ); + grChromakeyMode( GR_CHROMAKEY_ENABLE ); + grLfbConstantAlpha( (FxU8) 90); + grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); + + /* Attempt to lock with pixpipe enabled */ + info.size = sizeof( info ); + if ( grLfbLock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER, + GR_LFBWRITEMODE_565,GR_ORIGIN_UPPER_LEFT, + FXTRUE, &info ) ) { + FxU32 *dstData; + FxU32 dstJump; + FxU32 *srcData; + FxI32 srcJump; + FxU32 srcScanlineLength; + FxU32 scrWidth = Glide.WindowWidth; + FxU32 scrHeight = Glide.WindowHeight; + + FxU32 scanline; + + /* Draw Banner in lower right of screen */ + if ( scrWidth < (FxU32)banner_width ) return; + if ( scrHeight < (FxU32)banner_height ) return; + + dstData = static_cast(info.lfbPtr); + dstData = (FxU32*)( ((char*)dstData) + + (info.strideInBytes*((scrHeight-1)-banner_height)) + + ((scrWidth-banner_width)<<1) ); + dstJump = ((info.strideInBytes >> 1) - banner_width)>>1; + srcData = (FxU32*)&banner_data[banner_width*(banner_height-1)]; + srcScanlineLength = banner_width>>1; + srcJump = (-banner_width); + + for( scanline = 0; scanline < (FxU32)banner_height; scanline++ ) { + FxU32 *end = srcData + srcScanlineLength; + while( srcData < end ) *dstData++ = *srcData++; + dstData += dstJump; + srcData += srcJump; + } + + grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER ); + } + grGlideSetState( &state ); +/* +#elif ( GLIDE_PLATFORM & GLIDE_HW_SST96 ) + FXUNUSED( state ); + info.size = sizeof( info ); + if ( grLfbLock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER, + GR_LFBWRITEMODE_565,GR_ORIGIN_UPPER_LEFT, + FXFALSE, &info ) ) { + + FxU16 *dstData; + FxU32 dstJump; + FxU16 *srcData; + FxI32 srcJump; + FxU32 srcScanlineLength; + FxU32 scrWidth = gc->state.screen_width; + FxU32 scrHeight = gc->state.screen_height; + + FxU32 scanline; + + // Draw Banner in lower right of screen + if ( scrWidth < (FxU32)banner_width ) return; + if ( scrHeight < (FxU32)banner_height ) return; + + dstData = info.lfbPtr; + dstData = (FxU16*)( ((char*)dstData) + + (info.strideInBytes*((scrHeight-1)-banner_height)) + + ((scrWidth-banner_width)<<1) ); + dstJump = ((info.strideInBytes >> 1) - banner_width); + srcData = (FxU16*)&banner_data[banner_width*(banner_height-1)]; + srcScanlineLength = banner_width; + srcJump = (-banner_width)*2; + + for( scanline = 0; scanline < (FxU32)banner_height; scanline++ ) { + FxU16 *end = srcData + srcScanlineLength; + while( srcData < end ) { + if ( *srcData ) + *dstData = *srcData; + dstData++; + srcData++; + } + dstData += dstJump; + srcData += srcJump; + } + + grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER ); + } + +#else +# error "Shameless Plug Unimplemented on this Hardware" +#endif +*/ + + // GR_END(); +// #endif +} /* _grShamelessPlug */ diff --git a/MacGLide/glide2x/sst1/glide/src/gsplash.c b/MacGLide/glide2x/sst1/glide/src/gsplash.c new file mode 100644 index 0000000..19d64fc --- /dev/null +++ b/MacGLide/glide2x/sst1/glide/src/gsplash.c @@ -0,0 +1,1004 @@ +/* + ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. + ** + ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + ** THE UNITED STATES. + ** + ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + ** + ** $Header: /cvsroot/macglide/MacGLide/glide2x/sst1/glide/src/gsplash.c,v 1.6 2006/05/18 20:50:17 jens-olaf Exp $ + ** $Log: gsplash.c,v $ + ** Revision 1.6 2006/05/18 20:50:17 jens-olaf + ** No subtexturing/gapfix in splash anim + ** + ** Revision 1.5 2005/11/05 14:50:49 jens-olaf + ** Fixed endian-issues in grLfbWriteRegion() (fixes the menu backgrunds in Carmageddon 2) + ** + ** Revision 1.4 2005/08/17 20:16:57 jens-olaf + ** Fixed color of "3dfx" texture + ** + ** Revision 1.3 2005/07/14 18:54:34 jens-olaf + ** Fixed clearing the screen after the last frame + ** + ** Revision 1.2 2005/07/11 18:59:44 jens-olaf + ** Fixed buffer swap interval, added clear buffer command at the end of the animation because the last frame was displayed during game load + ** + ** Revision 1.1 2005/07/09 21:28:54 jens-olaf + ** Added splash screen and shameless plug + ** + ** Revision 1.1.1.1 1999/12/07 21:48:52 joseph + ** Initial checkin into SourceForge. + ** + * + * 14 12/19/97 8:09a Peter + * fog table propogation + * + * 13 7/07/97 3:05p Dow + * Moved fouled clears + * + * 12 3/18/97 9:07p Dow + * Got rid of #$#%#$ // comments + * + * 11 3/16/97 12:42a Jdt + * Removed watcom warning + * + * 10 3/13/97 10:53p Jdt + * Rewrote with simple optimizations. Changed prototype for + * multi-resolution, and running as a better shameless plug. + * + * 9 3/13/97 2:52a Jdt + * Added arguments to splash. + * + * 8 3/09/97 10:31a Dow + * Added GR_DIENTRY for di glide functions + * + * 7 3/01/97 6:24p Jdt + * Made splash force yorigin. + * + * 6 1/02/97 1:06p Dow + * Fixed state bug + * + * 3 11/17/96 11:16p Garymct + * Updated grSplash code to set all of the necessary state itself rather + * than expecting the caller to do so. + */ + +/* +#include <3dfx.h> +#define FX_DLL_DEFINITION +#include +#include + +#include "fxglide.h" +*/ +#include "fxinline.h" + +// OpenGLide specific +#include "../../../driversrc_defines.h" +#include "Glide.h" + +#include + +/*----------------------------- + Constants + -----------------------------*/ +#define MAX_NUM_VERTS 2556 + +#define FADEIN_END_PERCENT ( 0.3f ) +#define FADEOUT_BEGIN_PERCENT ( 0.8f ) + +#define SPIN_FRAMES 25 +#define SPIN_START 26 + +#define NO_TABLE ((GrTexTable_t)(~0)) + +/*----------------------------- + Macros + -----------------------------*/ +#define SNAP_BIAS ((float)(3<<18)) +#define SNAP_COORD(X) ((X)+SNAP_BIAS) + +/*----------------------------- + Types + -----------------------------*/ +typedef struct { + float x, y, z; /* object space coordinates */ + float nx, ny, nz; /* object space vertex normal for lighting */ + float s, t; /* pre-glide-ified texture coordinates */ +} Vert; + +typedef struct { + int v[3]; /* vertex indices into array of vertes for face */ + int mat_index; /* material index */ + int aa_edge_flags; +} Face; + +typedef float Vector[3]; +typedef float Matrix[16]; + +// typedef FxU32 Palette[256]; +typedef struct { + FxU8 yRGB[16]; + FxI16 iRGB[4][3]; + FxI16 qRGB[4][3]; + FxU32 packed_data[12]; +} NCCTable; +typedef union { +// Palette palette; + FxU32 palette[256]; + NCCTable nccTable; +} TextureTable; + +/*----------------------------- + Globals + -----------------------------*/ +/* xScale, xOffset, yScale, yOffset */ +static float viewPort[4] = { + 480.0f, 320.0f, + 480.0f, 240.0f +}; + +typedef struct { + GrTexInfo info; + FxU32 addr; + GrTexTable_t tableType; + TextureTable tableData; +} Texture; + +static int do_phong = 0; +static int pass; +static int fog; +static int useTextures; +static Vector light = { -0.57735f, -0.57735f, -0.57735f }; +static Vector transformed_verts[MAX_NUM_VERTS]; +static Vector transformed_norms[MAX_NUM_VERTS]; + +#include "splshdat.inc" + +static Texture textImage; +static Texture hiliteImage; +static Texture shadowImage; + +static FxU32 nextFreeBase; + +/*----------------------------- + Privates + -----------------------------*/ +static void sourceTexture( Texture *texture ) { + static Texture *lastTexture; + + if ( texture != lastTexture && useTextures ) { + grTexSource( GR_TMU0, + texture->addr, + GR_MIPMAPLEVELMASK_BOTH, + &texture->info ); + if ( texture->tableType != NO_TABLE ) { + grTexDownloadTable( GR_TMU0, + texture->tableType, + &texture->tableData ); + } + lastTexture = texture; + } +} + +static GrTexTable_t texTableType( GrTextureFormat_t format ) { + GrTexTable_t rv = (GrTexTable_t)NO_TABLE; + switch( format ) { + case GR_TEXFMT_YIQ_422: + case GR_TEXFMT_AYIQ_8422: + rv = GR_TEXTABLE_NCC0; + break; + case GR_TEXFMT_P_8: + case GR_TEXFMT_AP_88: + rv = GR_TEXTABLE_PALETTE; + break; + } + return rv; +} + +static void downloadTexture( Texture *texture, Gu3dfInfo *info ) { + texture->info.data = info->data; + texture->info.smallLod = info->header.small_lod; + texture->info.largeLod = info->header.large_lod; + texture->info.aspectRatio = info->header.aspect_ratio; + texture->info.format = info->header.format; + + texture->addr = nextFreeBase; + nextFreeBase += grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, + &texture->info ); + grTexDownloadMipMap( GR_TMU0, + texture->addr, + GR_MIPMAPLEVELMASK_BOTH, + &texture->info ); + + texture->tableType = texTableType( info->header.format ); + switch( texture->tableType ) { + case GR_TEXTABLE_NCC0: + case GR_TEXTABLE_NCC1: + case GR_TEXTABLE_PALETTE: + texture->tableData = *(TextureTable*)(&info->table); + break; + default: + break; + } + + return; +} + +#ifdef OPENGLIDE_HOST_MAC +void ConvertGu3dfInfoLSB2MSB(Gu3dfInfo* gu3dinfo) +{ + // Swap endianess fro LSB to MSB: + // Less optimal than supplying the correct data, + // but on the other hand it works with the original splash.inc + if (gu3dinfo->header.width > 0xffff) + { + // Convert the first time only... + swaplong(&gu3dinfo->header.width); + swaplong(&gu3dinfo->header.height); + swaplong(&gu3dinfo->header.small_lod); + swaplong(&gu3dinfo->header.large_lod); + swaplong(&gu3dinfo->header.aspect_ratio); + swaplong(&gu3dinfo->header.format); + // palette tables aren't swapped + // simply because they're not used + /* + for(FxU32 i = 0; i < 256; i++) + { + swaplong(&gu3dinfo->table.palette.data[i]); + } + */ + GuNccTable* ncc = &gu3dinfo->table.nccTable; + for ( int i = 0; i < 4; i++ ) + { + swapshort(&ncc->iRGB[i][0]); + swapshort(&ncc->iRGB[i][1]); + swapshort(&ncc->iRGB[i][2]); + } + for ( int i = 0; i < 4; i++ ) + { + swapshort(&ncc->qRGB[i][0]); + swapshort(&ncc->qRGB[i][1]); + swapshort(&ncc->qRGB[i][2]); + } + swaplong(&gu3dinfo->mem_required); + } +} +#else +void ConvertGu3dfInfoLSB2MSB(Gu3dfInfo* gu3dinfo) +{ +} +#endif + +static void createTextures( void ) { + Gu3dfInfo *info; + + /* + * Download the texture for the "3D" part of the model. + */ + info = ( Gu3dfInfo * )text_3dfinfo_raw; + info->data = ( void * )text_3dfinfo_image; + ConvertGu3dfInfoLSB2MSB(info); + downloadTexture( &textImage, info ); + + /* + * Download the texture for the specular highlight. + */ + info = ( Gu3dfInfo * )hilite_3dfinfo_raw; + info->data = ( void * )hilite_3dfinfo_image; + ConvertGu3dfInfoLSB2MSB(info); + downloadTexture( &hiliteImage, info ); + + /* + * Download the texture for the shadow. + */ + info = ( Gu3dfInfo * )shadow_3dfinfo_raw; + info->data = ( void * )shadow_3dfinfo_image; + ConvertGu3dfInfoLSB2MSB(info); + downloadTexture( &shadowImage, info ); + return; +} + +static void vecMatMult( float *dstVec, float *srcVec, float *matrix ) { + dstVec[0] = + srcVec[0] * matrix[0] + + srcVec[1] * matrix[4] + + srcVec[2] * matrix[8] + + matrix[12]; + + dstVec[1] = + srcVec[0] * matrix[1] + + srcVec[1] * matrix[5] + + srcVec[2] * matrix[9] + + matrix[13]; + + dstVec[2] = + srcVec[0] * matrix[2] + + srcVec[1] * matrix[6] + + srcVec[2] * matrix[10] + + matrix[14]; +} + +static void normMatMult( float *dstVec, float *srcVec, float *matrix ) { + dstVec[0] = + srcVec[0] * matrix[0] + + srcVec[1] * matrix[4] + + srcVec[2] * matrix[8]; + + dstVec[1] = + srcVec[0] * matrix[1] + + srcVec[1] * matrix[5] + + srcVec[2] * matrix[9]; + + dstVec[2] = + srcVec[0] * matrix[2] + + srcVec[1] * matrix[6] + + srcVec[2] * matrix[10]; +} + +static void xfAndProj( int frame, int obj ) { + int vertex; + float *matrix; + + matrix = &mat[frame][obj][0]; + + for( vertex = 0; vertex < num_verts[obj]; vertex++ ) { + float *srcVec; + float *dstVec; + float oow; + + /* transform point */ + srcVec = (float*)&(vert[obj][vertex].x); + dstVec = (float*)transformed_verts[vertex]; + vecMatMult( dstVec, srcVec, matrix ); + + /* project point */ + oow = 1.0f / dstVec[2]; + dstVec[0] = dstVec[0] * oow * viewPort[0] + viewPort[1] + SNAP_BIAS; + dstVec[1] = dstVec[1] * oow * viewPort[2] + viewPort[3] + SNAP_BIAS; + + /* transform normal */ + srcVec = (float*)&(vert[obj][vertex].nx); + dstVec = (float*)transformed_norms[vertex]; + normMatMult( dstVec, srcVec, matrix ); + } +} + +static void setupMaterial( int material_index ) { + switch( material_index ) { + case 0: /* 3d */ + if( pass == 1 ) { + sourceTexture( &textImage ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); + do_phong = 1; + } else if ( pass == 0xbeef ) { + /* Pantone 320C - 3D Green */ + grConstantColorValue( 0x00989100 ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_ITERATED, + FXFALSE ); + } else { + sourceTexture( &hiliteImage ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); + } + break; + case 1: /* fx */ + if ( pass == 0xbeef ) { + /* Black - fx */ + grConstantColorValue( 0x00 ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_ITERATED, + FXFALSE ); + do_phong = 1; + } else { + sourceTexture( &hiliteImage ); + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); + do_phong = 1; + } + break; + case 2: + case 3: + case 4: + grColorCombine( GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE ); + do_phong = 0; + break; + } + return; +} + +static void calculateIntensity( int material_index, + Vector intensity_factor, + int frame ) { + switch( material_index ) { + case 0: + /* 3d */ + intensity_factor[0] = 1.0f; + intensity_factor[1] = 1.0f; + intensity_factor[2] = 1.0f; + break; + case 1: + /* fx */ + intensity_factor[0] = 0.125f; + intensity_factor[1] = 0.125f; + intensity_factor[2] = 0.125f; + break; + case 2: + /* cyan */ + intensity_factor[0] = ( 10.0f / 255.0f ); + intensity_factor[1] = ( 75.0f / 255.0f ); + intensity_factor[2] = ( 120.0f / 255.0f ); + break; + case 3: + /* white */ + intensity_factor[0] = 1.0f; + intensity_factor[1] = 1.0f; + intensity_factor[2] = 1.0f; + break; + case 4: + /* yellow */ + intensity_factor[0] = ( 248.0f / 255.0f ); + intensity_factor[1] = ( 204.0f / 255.0f ); + intensity_factor[2] = 0.0f; + break; + } +} + +static void drawFaces( int frame, int objnum ) { + int facenum; + int material_index; + float intensity_factor[3]; + GrVertex gvert[3]; + static int prev_mat_index = 0xffff; + int i; + FxBool aa_a, aa_b, aa_c; + + for( facenum = 0; facenum < num_faces[objnum]; facenum++ ) { + material_index = face[objnum][facenum].mat_index; + if( material_index != prev_mat_index ) { + setupMaterial( material_index ); + calculateIntensity( material_index, + intensity_factor, frame ); + prev_mat_index = material_index; + } + + if( ( material_index != 0 ) && ( pass == 2 ) ) + continue; + + aa_a = aa_b = aa_c = FXFALSE; + if( face[objnum][facenum].aa_edge_flags & 4 ) + aa_a = FXTRUE; + if( face[objnum][facenum].aa_edge_flags & 2 ) + aa_b = FXTRUE; + if( face[objnum][facenum].aa_edge_flags & 1 ) + aa_c = FXTRUE; + + for( i = 0; i < 3; i++ ) { + float *transformed_vert, *transformed_norm; + Vert *v; + int vertnum; + float factor; + + vertnum = face[objnum][facenum].v[i]; + transformed_vert = transformed_verts[vertnum]; + transformed_norm = transformed_norms[vertnum]; + v = &vert[objnum][vertnum]; + + gvert[i].x = transformed_vert[0]; + gvert[i].y = transformed_vert[1]; + gvert[i].oow = 1.0f / transformed_vert[2]; + gvert[i].tmuvtx[0].oow = gvert[i].oow; + gvert[i].tmuvtx[0].sow = v->s * gvert[i].oow; + gvert[i].tmuvtx[0].tow = v->t * gvert[i].oow; + + factor = + ( ( light[0] * transformed_norm[0] + + light[1] * transformed_norm[1] + + light[2] * transformed_norm[2] ) + 1.0f ) * 127.5f; + + gvert[i].r = factor * intensity_factor[0]; + gvert[i].g = factor * intensity_factor[1]; + gvert[i].b = factor * intensity_factor[2]; + gvert[i].a = 255.0f; + } + + if( pass == 2 ) { + for( i = 0; i < 3; i++ ) { + float *transformed_norm; + + transformed_norm = + transformed_norms[face[objnum][facenum].v[i]]; + + gvert[i].tmuvtx[0].sow = gvert[i].oow * + ( 128.0f + transformed_norm[0] * 128.0f ); + gvert[i].tmuvtx[0].tow = gvert[i].oow * + ( 128.0f + transformed_norm[1] * 128.0f ); + + gvert[i].r = intensity_factor[0] * 255.0f; + gvert[i].g = intensity_factor[1] * 255.0f; + gvert[i].b = intensity_factor[2] * 255.0f; + } + + grDrawTriangle( &gvert[0], &gvert[1], &gvert[2] ); + + continue; + } + + grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, + GR_BLEND_ONE, GR_BLEND_ZERO ); + /* Do this if 3D. */ + if( material_index == 0 ) { + /* + * Draw the textured 3D without specular. + */ + sourceTexture( &textImage ); +#if 0 + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); +#endif + grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c ); + } else if( material_index != 1 ) { + /* + * Just go ahead and draw for things that don't + * have specular highlights. + */ + grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c ); + } + + if( do_phong && ( material_index != 0 ) ) { + /* + * figure out texture coords in [0..255.0f] based on the normal + * the specular highlight. + */ + for( i = 0; i < 3; i++ ) { + float *transformed_norm; + + transformed_norm = + transformed_norms[face[objnum][facenum].v[i]]; + + gvert[i].tmuvtx[0].sow = gvert[i].oow * + ( 128.0f + transformed_norm[0] * 128.0f ); + gvert[i].tmuvtx[0].tow = gvert[i].oow * + ( 128.0f + transformed_norm[1] * 128.0f ); + + gvert[i].r = intensity_factor[0] * 255.0f; + gvert[i].g = intensity_factor[1] * 255.0f; + gvert[i].b = intensity_factor[2] * 255.0f; + } + grAADrawTriangle( &gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c ); + } + } +} + +static void intersectLineWithZPlane( Vector result, Vector p1, + Vector p2, float z ) { + float t; + + t = ( z - p1[2] ) / ( p2[2] - p1[2] ); + result[0] = p1[0] + ( p2[0] - p1[0] ) * t; + result[1] = p1[1] + ( p2[1] - p1[1] ) * t; + result[2] = z; +} + +static float vectorMag( float *v ) { + return ( float )sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] ); +} + +static void drawShadow( int frame, int shadow_object_index, + int receiver_object_index, Vector light_position ) { + float *shadow_object_matrix; + float *receiver_object_matrix; + Vector view_verts[4]; + Vector projected_view_verts[4]; + int i; + + Vector local_verts[4] = { + { -280.0f, 0.0f, -160.0f }, + { -280.0f, 0.0f, 150.0f }, + { 280.0f, 0.0f, 150.0f }, + { 280.0f, 0.0f, -160.0f } + }; + + float texcoords[4][2] = { + { 10.5f, 127.5f }, + { 10.5f, 0.5f }, + { 255.0f, 0.5f }, + { 255.0f, 127.5f } + }; + + GrVertex gvert[4]; + GrVertex projected_gvert[4]; + GrVertex light_gvert; + + /* + * The point relative to the back part of the shield that + * the shadow is going to be projected onto. + */ + Vector shadow_light; + + shadow_light[0] = light_position[0]; + shadow_light[1] = light_position[1]; + shadow_light[2] = light_position[2]; + + shadow_object_matrix = &mat[frame][shadow_object_index][0]; + receiver_object_matrix = &mat[frame][receiver_object_index][0]; + + /* + * Offset the light by the Z position of + * the backplane that we are projected + * onto. + */ + shadow_light[2] += receiver_object_matrix[14]; + + for( i = 0; i < 4; i++ ) { + vecMatMult( view_verts[i], local_verts[i], shadow_object_matrix ); + + /* + * project . . . + */ + gvert[i].oow = 1.0f / view_verts[i][2]; + gvert[i].x = + view_verts[i][0] * gvert[i].oow * viewPort[0] + + viewPort[1] + SNAP_BIAS; + gvert[i].y = + view_verts[i][1] * gvert[i].oow * viewPort[2] + + viewPort[3] + SNAP_BIAS; + + /* + * Set up texture coordinates. + */ + gvert[i].tmuvtx[0].sow = texcoords[i][0] * gvert[i].oow; + gvert[i].tmuvtx[0].tow = texcoords[i][1] * gvert[i].oow; + } + + + /* + * Intersect each line formed by the light source and a + * particular corner of the shadow object with the + * plane which the texture is to be projected onto. + */ + for( i = 0; i < 4; i++ ) { + Vector tmpvect; + float q; + + intersectLineWithZPlane( projected_view_verts[i], + shadow_light, + view_verts[i], + receiver_object_matrix[14] - 26.0f ); + projected_gvert[i].oow = 1.0f / projected_view_verts[i][2]; + projected_gvert[i].x = + projected_view_verts[i][0] * projected_gvert[i].oow * viewPort[0] + + viewPort[1] + SNAP_BIAS; + projected_gvert[i].y = + projected_view_verts[i][1] * projected_gvert[i].oow * viewPort[2] + + viewPort[3] + SNAP_BIAS; + + tmpvect[0] = projected_view_verts[i][0] - shadow_light[0]; + tmpvect[1] = projected_view_verts[i][1] - shadow_light[1]; + tmpvect[2] = projected_view_verts[i][2] - shadow_light[2]; + q = vectorMag( tmpvect ); + + /* + * Set up texture coordinates. + */ + projected_gvert[i].tmuvtx[0].oow = projected_gvert[i].oow * q; + projected_gvert[i].tmuvtx[0].sow = + texcoords[i][0] * projected_gvert[i].oow; + projected_gvert[i].tmuvtx[0].tow = + texcoords[i][1] * projected_gvert[i].oow; + } + + light_gvert.oow = 1.0f / shadow_light[2]; + light_gvert.x = shadow_light[0] * light_gvert.oow * viewPort[0] + + viewPort[1] + SNAP_BIAS; + light_gvert.y = shadow_light[1] * light_gvert.oow * viewPort[2] + + viewPort[3] + SNAP_BIAS; + + /* + * Draw a segment between the light and the point which hits + * the surface that the light is being projected onto. + */ + grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE ); + sourceTexture( &shadowImage ); + + grAlphaBlendFunction( GR_BLEND_DST_COLOR, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO ); + + + grDrawTriangle( &projected_gvert[0], + &projected_gvert[1], + &projected_gvert[2] ); + grDrawTriangle( &projected_gvert[0], + &projected_gvert[2], + &projected_gvert[3] ); + grDrawTriangle( &projected_gvert[0], + &projected_gvert[2], + &projected_gvert[1] ); + grDrawTriangle( &projected_gvert[0], + &projected_gvert[3], + &projected_gvert[2] ); + + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO ); + +} + + +/*------------------------------------------------------------------- + Function: grSplash + Date: 3/13 + Implementor(s): GaryMcT + Library: Glide + Description: + Render the opening splash screen animation, or render + a single frame of the splash screen. + Arguments: + x, y - upper left hand coord of window + w, h - width and height of window to render + _frame - frame number to render ( ~0 to render all frames ) + Return: + none + -------------------------------------------------------------------*/ +GR_DIENTRY(grSplash,void,(float x,float y,float w,float h,FxU32 _frame)) +{ + // OpenGLide addition + #ifdef OGL_DONE + GlideMsg( "grSplash( %-4.2f, %-4.2f, %-4.2f, %-4.2f, %lu )\n", + x, y, w, h, _frame ); + #endif + + GrState oldState; + int frame; + Vector lights[] = { + { 5.0f, 300.0f, -1500.0f }, + { 5.0f, 150.0f, -1000.0f }, + { -30.0f, 150.0f, -1000.0f }, + { -30.0f, 100.0f, -1000.0f }, + { 30.0f, 70.0f, -1000.0f }, + }; + GrFog_t fogTable[kInternalFogTableEntryCount]; + int fadeInFrames, fadeOutFrames; + + GR_BEGIN_NOFIFOCHECK( "grSplash", 85 ); + GDBG_INFO_MORE((gc->myLevel,"(%f,%f,%f,%f,%d)\n", + x, y, w, h, _frame )); + + /* Check Screen Dimensions and Check Avail of Depth Buffer */ + // The emulation offers virtually unlimited buffers, so we don't have to check + /* + if ( (x > gc->state.screen_width) || + ((x+w) > gc->state.screen_width) || + ( y > gc->state.screen_height ) || + ((y+h) > gc->state.screen_height ) ) + return; + if ( gc->state.screen_height == 640 ) { + if ( gc->fbuf_size == 1 ) { + return; + } + } else if ( gc->state.screen_width == 800 ) { + if ( ( gc->fbuf_size == 1 ) || + ( gc->fbuf_size == 2 ) ) { + return; + } + } + */ + + // subtexturing doesn't work with the splash animation + // so we're going to turn it off temporarily + const unsigned long generatesubtextures = InternalConfig.GenerateSubTextures; InternalConfig.GenerateSubTextures = 0; + // Gapfix decreases the framerate but doesn't improve the rendering quality of the animation + const OpenGLideGapFixFlags gapfix = InternalConfig.GapFix; InternalConfig.GapFix = OpenGLideGapFixFlag_Disabled; + + // if ( !(gc->state.fbi_config.fbzMode & SST_YORIGIN) + if (Glide.State.OriginInformation == GR_ORIGIN_LOWER_LEFT) // @todo: correct? + { + y = (( Glide.WindowHeight - 1.0f ) - (h-1.0f) ) - y; + } + + viewPort[0] = w * ( 480.0f / 640.0f ); + viewPort[1] = x + ( w / 2.0f ); + viewPort[2] = h; + viewPort[3] = y + ( h / 2.0f ); + + grGlideGetState(&oldState); + + grSstOrigin( GR_ORIGIN_LOWER_LEFT ); + + if ( _frame == 0 ) { + createTextures(); + useTextures = 1; + } else { + useTextures = 0; + } + + grAlphaTestFunction( GR_CMP_ALWAYS ); + grChromakeyMode( GR_CHROMAKEY_DISABLE ); + grConstantColorValue( 0xffffffff ); + grDepthBufferMode( GR_DEPTHBUFFER_WBUFFER ); + grDepthMask( FXTRUE ); + grAlphaCombine( GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE ); + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO ); + if ( useTextures ) + grTexCombine( GR_TMU0, + GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE ); + else + grTexCombine( GR_TMU0, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, + FXTRUE, FXFALSE ); + grTexMipMapMode( GR_TMU0, + GR_MIPMAP_NEAREST, + FXFALSE ); + grTexFilterMode( GR_TMU0, + GR_TEXTUREFILTER_BILINEAR, + GR_TEXTUREFILTER_BILINEAR ); + grDepthBufferFunction( GR_CMP_LEQUAL ); + grCullMode( GR_CULL_NEGATIVE ); + // grClipWindow( (int)x, (int)y, (int)(x+w), (int)(y+h) ); + grFogColorValue( 0x0 ); + + fadeInFrames = (int)(((float)total_num_frames) * FADEIN_END_PERCENT); + fadeOutFrames = (int)(((float)total_num_frames) * + (1.0f - FADEOUT_BEGIN_PERCENT)); + + if ( _frame == 0 ) { /* Render Whole Animation */ + for( frame = 1; frame < total_num_frames; frame++ ) { + int i; + + /* Set Fog Value For This Frame */ + if( frame < fadeInFrames ) { + unsigned char fval = + ((unsigned char)255) - + ((unsigned char)( 255.0f * + (float)(frame+1) / + (float)fadeInFrames )); + for( i = 0; i < kInternalFogTableEntryCount; i++ ) + fogTable[i] = fval; + grFogMode( GR_FOG_WITH_TABLE ); + grFogTable( fogTable ); + fog = 1; + } else if( frame > total_num_frames-fadeOutFrames ) { + unsigned char fval = + ((unsigned char)255) - + (unsigned char)(255.0f* + ((float)(total_num_frames-frame))/ + ((float)fadeOutFrames)); + for( i = 0; i < kInternalFogTableEntryCount; i++ ) + fogTable[i] = fval; + grFogMode( GR_FOG_WITH_TABLE ); + grFogTable( fogTable ); + fog = 1; + } else { + grFogMode( GR_FOG_DISABLE ); + fog = 0; + } + grBufferClear( 0x00000000, 0, GR_WDEPTHVALUE_FARTHEST ); + + pass = 1; + + /* + * Avoid Z-aliasing between the shield and the 3dfx by + * not writing Z for the shield. + */ + + grDepthMask( FXFALSE ); + /* cyan part of shield */ + xfAndProj( frame, 2 ); + drawFaces( frame, 2 ); + + /* yellow and white part of shield. */ + xfAndProj( frame, 0 ); + drawFaces( frame, 0 ); + + /* + * Reanable writes to the depth-buffer. + */ + grDepthMask( FXTRUE ); + + /* + * Draw the shadow projected from the 3Dfx logo onto + * the rest of the powershield. + */ + grDepthBufferFunction( GR_CMP_ALWAYS ); + grFogMode( GR_FOG_DISABLE ); + drawShadow( frame, 1, 0, lights[0] ); + if ( fog ) grFogMode( GR_FOG_WITH_TABLE ); /* hack around mp fog */ + grDepthBufferFunction( GR_CMP_LEQUAL ); + + /* 3Dfx logo */ + xfAndProj( frame, 1 ); + drawFaces( frame, 1 ); + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ONE, + GR_BLEND_ONE, GR_BLEND_ZERO ); + + pass = 2; + drawFaces( frame, 1 ); + pass = 1; + grAlphaBlendFunction( GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO ); + grBufferSwap( 2 ); + } + } else { /* Render One Frame */ + frame = ((_frame>>1) % SPIN_FRAMES)+SPIN_START; + + grColorMask( FXFALSE, FXFALSE ); + grBufferClear( 0x00000000, 0, GR_WDEPTHVALUE_FARTHEST ); + grColorMask( FXTRUE, FXFALSE ); + + pass = 0xbeef; + + /* 3Dfx logo */ + xfAndProj( frame, 1 ); + drawFaces( frame, 1 ); + } + + + // Added by Jenz: Clear the buffer after the last frame to avoid + // the last image be displayed while the game is loading + // (May be a problem of MacGLide since the 3dfx hardware + if (_frame == 0) + { + grColorMask(FXTRUE, FXTRUE); + grBufferClear(0x00000000, 0, GR_WDEPTHVALUE_FARTHEST); + grColorMask(FXTRUE, FXFALSE); + grBufferSwap( 2 ); + + } + /* + * Clean up after yourself! + */ + grGlideSetState(&oldState); + + // Reenable temporarily disabled settings + InternalConfig.GenerateSubTextures = generatesubtextures; + InternalConfig.GapFix = gapfix; +} + + diff --git a/MacGLide/glide2x/sst1/glide/src/splshdat.inc b/MacGLide/glide2x/sst1/glide/src/splshdat.inc new file mode 100644 index 0000000..668e4a6 --- /dev/null +++ b/MacGLide/glide2x/sst1/glide/src/splshdat.inc @@ -0,0 +1,17369 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +** +** $Header: /cvsroot/macglide/MacGLide/glide2x/sst1/glide/src/splshdat.inc,v 1.2 2005/07/11 19:03:41 jens-olaf Exp $ +** $Log: splshdat.inc,v $ +** Revision 1.2 2005/07/11 19:03:41 jens-olaf +** Adjusted the number of frames to match the array size +** +** Revision 1.1 2005/07/09 21:28:54 jens-olaf +** Added splash screen and shameless plug +** +** Revision 1.1.1.1 1999/12/07 21:48:54 joseph +** Initial checkin into SourceForge. +** +** +*/ + +static Vert vert_0[] = { +{ 273.149261f, -24.549585f, 271.420441f, 0.012590f, -0.999890f, 0.007876f, 189.411841f, 18.708570f }, +{ 262.776489f, -24.549574f, 143.489777f, 0.005015f, -0.999765f, 0.021108f, 187.071440f, 69.986058f }, +{ 484.061951f, -24.549578f, 188.438385f, 0.011169f, -0.999936f, -0.001735f, 236.999758f, 51.969644f }, +{ 383.791992f, -24.549570f, 84.710793f, 0.010803f, -0.999785f, 0.017720f, 214.376000f, 93.546010f }, +{ 563.586426f, -24.549566f, 46.677605f, 0.009678f, -0.999914f, -0.008881f, 254.942760f, 108.790640f }, +{ 432.198181f, -24.549561f, -5.186394f, 0.013545f, -0.999894f, 0.005335f, 225.297815f, 129.578823f }, +{ 542.840820f, -24.549555f, -77.795677f, 0.007103f, -0.999894f, -0.012739f, 250.261958f, 158.682259f }, +{ 407.995087f, -24.549522f, -95.083649f, 0.013879f, -0.999904f, -0.000529f, 219.836900f, 165.611674f }, +{ 494.434692f, -24.549543f, -205.726379f, 0.002522f, -0.999903f, -0.013725f, 239.340159f, 209.959770f }, +{ 300.809937f, -24.549547f, -171.150482f, 0.015764f, -0.999874f, -0.001621f, 195.652869f, 196.100972f }, +{ 331.928192f, -24.549507f, -274.878052f, 0.002234f, -0.999897f, -0.014178f, 202.674041f, 237.677320f }, +{ 155.591354f, -24.549513f, -202.268799f, 0.011551f, -0.999861f, -0.012043f, 162.887410f, 208.573894f }, +{ 138.303436f, -24.549505f, -288.708374f, -0.003900f, -0.999855f, -0.016564f, 158.986767f, 243.220826f }, +{ -10.372740f, -24.549486f, -178.065643f, 0.019735f, -0.999598f, -0.020336f, 125.441172f, 198.872725f }, +{ -76.066864f, -24.549473f, -316.369080f, -0.005668f, -0.999796f, -0.019403f, 110.618699f, 254.307860f }, +{ -148.676147f, -24.549513f, -212.641541f, 0.006169f, -0.999812f, -0.018392f, 94.235969f, 212.731524f }, +{ -235.115784f, -24.549473f, -316.369080f, -0.011969f, -0.999851f, -0.012476f, 74.732718f, 254.307860f }, +{ -276.606812f, -24.549515f, -191.895996f, 0.001960f, -0.999741f, -0.022663f, 65.371153f, 204.416240f }, +{ -394.164703f, -24.549477f, -267.962891f, -0.008901f, -0.999940f, -0.006464f, 38.846733f, 234.905569f }, +{ -352.673676f, -24.549488f, -136.574646f, -0.001484f, -0.999702f, -0.024356f, 48.208294f, 182.242196f }, +{ -490.977112f, -24.549486f, -167.692871f, -0.010745f, -0.999942f, -0.000498f, 17.003084f, 194.715083f }, +{ -404.537445f, -24.549494f, -81.253296f, -0.011367f, -0.999900f, -0.008360f, 36.506343f, 160.068151f }, +{ -563.586426f, -24.549498f, -29.389488f, -0.008846f, -0.999795f, 0.018188f, 0.620349f, 139.279968f }, +{ -421.825378f, -24.549501f, 8.643953f, -0.014278f, -0.999891f, -0.003750f, 32.605693f, 124.035300f }, +{ -522.095337f, -24.549541f, 105.456299f, -0.006669f, -0.999881f, 0.013889f, 9.981924f, 85.230734f }, +{ -363.046448f, -24.549541f, 112.371468f, -0.021114f, -0.999733f, -0.009357f, 45.867897f, 82.458980f }, +{ -446.028503f, -24.549519f, 205.726318f, 0.001853f, -0.999682f, 0.025132f, 27.144776f, 45.040260f }, +{ -304.267487f, -24.549698f, 160.777710f, -0.020407f, -0.999774f, 0.005967f, 59.130113f, 63.056674f }, +{ -325.013000f, -24.549555f, 267.962860f, 0.003703f, -0.999746f, 0.022221f, 54.449330f, 20.094447f }, +{ -203.997513f, -24.549549f, 198.811157f, -0.010313f, -0.999774f, 0.018587f, 81.753890f, 47.811998f }, +{ -138.303391f, -24.549589f, 316.369080f, 0.008523f, -0.999823f, 0.016755f, 96.576363f, 0.692140f }, +{ -44.948593f, -24.549578f, 178.065643f, -0.007338f, -0.999733f, 0.021901f, 117.639871f, 56.127275f }, +{ 79.524475f, -24.549589f, 302.538696f, 0.018197f, -0.999766f, 0.011712f, 145.724552f, 6.235663f }, +{ 107.185158f, -24.549576f, 164.235291f, 0.002913f, -0.999764f, 0.021512f, 151.965595f, 61.670797f }, +{ 257.177246f, -24.933891f, 247.388947f, -0.002196f, -0.999908f, 0.013383f, 189.411841f, 18.708570f }, +{ 248.097778f, -24.933882f, 127.560898f, 0.006178f, -0.999976f, 0.003207f, 187.071440f, 69.986058f }, +{ 449.640747f, -24.933884f, 170.658722f, 0.002530f, -0.999944f, 0.010309f, 236.999758f, 51.969644f }, +{ 357.436859f, -24.933876f, 80.888054f, 0.006209f, -0.999981f, -0.000250f, 214.376000f, 93.546010f }, +{ 521.126526f, -24.933874f, 43.160934f, 0.006734f, -0.999927f, 0.010037f, 254.942760f, 108.790640f }, +{ 404.311340f, -24.933870f, -2.458469f, 0.006431f, -0.999963f, -0.005670f, 225.297815f, 129.578823f }, +{ 501.943878f, -24.933863f, -69.597458f, 0.008351f, -0.999957f, 0.004028f, 250.261958f, 158.682259f }, +{ 380.763092f, -24.933832f, -86.167274f, 0.003817f, -0.999973f, -0.006297f, 219.836900f, 165.611674f }, +{ 459.521820f, -24.933853f, -187.305740f, 0.007558f, -0.999970f, -0.001392f, 239.340159f, 209.959770f }, +{ 277.039581f, -24.933857f, -148.476547f, 0.001550f, -0.999981f, -0.006005f, 195.652869f, 196.100972f }, +{ 310.612000f, -24.933817f, -250.478271f, 0.010282f, -0.999945f, -0.002099f, 202.674041f, 237.677320f }, +{ 143.869293f, -24.933823f, -182.877960f, 0.000385f, -0.999975f, -0.007022f, 162.887410f, 208.573894f }, +{ 126.038422f, -24.933817f, -261.421204f, 0.007580f, -0.999942f, -0.007664f, 158.986767f, 243.220826f }, +{ -12.511669f, -24.933794f, -160.756546f, 0.000504f, -0.999969f, -0.007865f, 125.441172f, 198.872725f }, +{ -76.663612f, -24.933783f, -297.401611f, 0.011523f, -0.999829f, -0.014451f, 110.618699f, 254.307860f }, +{ -148.031876f, -24.933823f, -192.176437f, -0.004257f, -0.999964f, -0.007337f, 94.235969f, 212.731524f }, +{ -229.626144f, -24.933783f, -288.089294f, 0.004915f, -0.999922f, -0.011510f, 74.732718f, 254.307860f }, +{ -271.880676f, -24.933825f, -170.771347f, -0.005194f, -0.999973f, -0.005174f, 65.371153f, 204.416240f }, +{ -371.136383f, -24.933788f, -242.218704f, 0.003027f, -0.999922f, -0.012100f, 38.846733f, 234.905569f }, +{ -331.104309f, -24.933798f, -120.729073f, -0.004534f, -0.999987f, -0.002245f, 48.208294f, 182.242196f }, +{ -457.056519f, -24.933796f, -151.361816f, -0.000889f, -0.999896f, -0.014400f, 17.003084f, 194.715083f }, +{ -375.726990f, -24.933802f, -71.798042f, -0.008099f, -0.999961f, 0.003607f, 36.506343f, 160.068151f }, +{ -521.126587f, -24.933805f, -27.175323f, -0.006509f, -0.999977f, 0.001914f, 0.620349f, 139.279968f }, +{ -393.095642f, -24.933809f, 1.511459f, -0.005247f, -0.999950f, 0.008552f, 32.605693f, 124.035300f }, +{ -489.623932f, -24.933847f, 94.842606f, -0.009209f, -0.999957f, -0.000960f, 9.981924f, 85.230734f }, +{ -339.383545f, -24.933847f, 99.110413f, -0.004875f, -0.999978f, 0.004578f, 45.867897f, 82.458980f }, +{ -420.171265f, -24.933825f, 190.964874f, -0.009048f, -0.999950f, 0.004143f, 27.144776f, 45.040260f }, +{ -291.672363f, -24.934004f, 144.238663f, -0.000427f, -0.999928f, 0.011948f, 59.130113f, 63.056674f }, +{ -309.379486f, -24.933861f, 249.619171f, -0.011270f, -0.999908f, 0.007562f, 54.449330f, 20.094447f }, +{ -195.040344f, -24.933855f, 180.815704f, 0.002731f, -0.999942f, 0.010459f, 81.753890f, 47.811998f }, +{ -136.935654f, -24.933895f, 293.288574f, -0.005146f, -0.999926f, 0.011049f, 96.576363f, 0.692140f }, +{ -48.893070f, -24.933884f, 161.229355f, 0.003108f, -0.999963f, 0.008062f, 117.639871f, 56.127275f }, +{ 72.555756f, -24.933893f, 275.836060f, -0.004433f, -0.999894f, 0.013872f, 145.724552f, 6.235663f }, +{ 102.042297f, -24.933882f, 146.974792f, 0.007025f, -0.999961f, 0.005404f, 151.965595f, 61.670797f } +}; + +static Face face_0[] = { +{ 61, 60, 59, 3, 0 }, +{ 55, 54, 53, 3, 0 }, +{ 57, 56, 55, 3, 0 }, +{ 39, 38, 37, 3, 0 }, +{ 37, 36, 35, 3, 0 }, +{ 53, 52, 51, 3, 0 }, +{ 41, 40, 39, 3, 0 }, +{ 43, 42, 41, 3, 0 }, +{ 59, 58, 57, 3, 0 }, +{ 63, 62, 61, 3, 0 }, +{ 45, 44, 43, 3, 0 }, +{ 35, 34, 67, 3, 0 }, +{ 67, 66, 65, 3, 0 }, +{ 51, 50, 49, 3, 0 }, +{ 49, 48, 47, 3, 0 }, +{ 65, 64, 63, 3, 0 }, +{ 47, 46, 45, 3, 0 }, +{ 41, 39, 37, 3, 0 }, +{ 43, 41, 37, 3, 0 }, +{ 43, 37, 35, 3, 0 }, +{ 45, 43, 35, 3, 0 }, +{ 45, 35, 67, 3, 0 }, +{ 47, 45, 67, 3, 0 }, +{ 47, 67, 65, 3, 0 }, +{ 49, 47, 65, 3, 0 }, +{ 49, 65, 63, 3, 0 }, +{ 51, 49, 63, 3, 0 }, +{ 51, 63, 61, 3, 0 }, +{ 53, 51, 61, 3, 0 }, +{ 53, 61, 59, 3, 0 }, +{ 53, 59, 57, 3, 0 }, +{ 53, 57, 55, 3, 0 }, +{ 61, 27, 26, 4, 2 }, +{ 26, 60, 61, 4, 0 }, +{ 60, 26, 25, 4, 2 }, +{ 25, 59, 60, 4, 0 }, +{ 55, 21, 20, 4, 2 }, +{ 20, 54, 55, 4, 0 }, +{ 54, 20, 19, 4, 2 }, +{ 19, 53, 54, 4, 0 }, +{ 57, 23, 22, 4, 2 }, +{ 22, 56, 57, 4, 0 }, +{ 56, 22, 21, 4, 2 }, +{ 21, 55, 56, 4, 0 }, +{ 39, 5, 4, 4, 2 }, +{ 4, 38, 39, 4, 0 }, +{ 38, 4, 3, 4, 2 }, +{ 3, 37, 38, 4, 0 }, +{ 37, 3, 2, 4, 2 }, +{ 2, 36, 37, 4, 0 }, +{ 36, 2, 1, 4, 2 }, +{ 1, 35, 36, 4, 0 }, +{ 53, 19, 18, 4, 2 }, +{ 18, 52, 53, 4, 0 }, +{ 52, 18, 17, 4, 2 }, +{ 17, 51, 52, 4, 0 }, +{ 41, 7, 6, 4, 2 }, +{ 6, 40, 41, 4, 0 }, +{ 40, 6, 5, 4, 2 }, +{ 5, 39, 40, 4, 0 }, +{ 43, 9, 8, 4, 2 }, +{ 8, 42, 43, 4, 0 }, +{ 42, 8, 7, 4, 2 }, +{ 7, 41, 42, 4, 0 }, +{ 59, 25, 24, 4, 2 }, +{ 24, 58, 59, 4, 0 }, +{ 58, 24, 23, 4, 2 }, +{ 23, 57, 58, 4, 0 }, +{ 63, 29, 28, 4, 2 }, +{ 28, 62, 63, 4, 0 }, +{ 62, 28, 27, 4, 2 }, +{ 27, 61, 62, 4, 0 }, +{ 45, 11, 10, 4, 2 }, +{ 10, 44, 45, 4, 0 }, +{ 44, 10, 9, 4, 2 }, +{ 9, 43, 44, 4, 0 }, +{ 35, 1, 0, 4, 2 }, +{ 0, 34, 35, 4, 0 }, +{ 34, 0, 33, 4, 2 }, +{ 33, 67, 34, 4, 0 }, +{ 67, 33, 32, 4, 2 }, +{ 32, 66, 67, 4, 0 }, +{ 66, 32, 31, 4, 2 }, +{ 31, 65, 66, 4, 0 }, +{ 51, 17, 16, 4, 2 }, +{ 16, 50, 51, 4, 0 }, +{ 50, 16, 15, 4, 2 }, +{ 15, 49, 50, 4, 0 }, +{ 49, 15, 14, 4, 2 }, +{ 14, 48, 49, 4, 0 }, +{ 48, 14, 13, 4, 2 }, +{ 13, 47, 48, 4, 0 }, +{ 65, 31, 30, 4, 2 }, +{ 30, 64, 65, 4, 0 }, +{ 64, 30, 29, 4, 2 }, +{ 29, 63, 64, 4, 0 }, +{ 47, 13, 12, 4, 2 }, +{ 12, 46, 47, 4, 0 }, +{ 46, 12, 11, 4, 2 }, +{ 11, 45, 46, 4, 0 } +}; + +static Vert vert_1[] = { +{ -227.530014f, -20.966743f, 18.889576f, -0.132901f, 0.000004f, -0.991129f, 11.312357f, 104.759467f }, +{ -227.530014f, -20.966749f, 49.094059f, -0.113407f, 0.000000f, 0.993549f, 24.483732f, 68.571409f }, +{ -220.271423f, -20.966749f, 49.922577f, -0.278891f, 0.000000f, 0.960323f, 33.541598f, 70.744057f }, +{ -214.348251f, -20.966755f, 52.198391f, -0.521000f, 0.000000f, 0.853557f, 41.630631f, 70.600333f }, +{ -209.753510f, -20.966747f, 55.606861f, -0.731747f, 0.000000f, 0.681577f, 48.621978f, 68.520264f }, +{ -206.480209f, -20.966747f, 59.833366f, -0.886449f, 0.000000f, 0.462826f, 54.386820f, 64.883859f }, +{ -204.521362f, -20.966749f, 64.563301f, -0.976238f, 0.000000f, 0.216703f, 58.796339f, 60.071098f }, +{ -203.869965f, -20.966747f, 69.481987f, -0.998414f, 0.000000f, -0.056296f, 61.721703f, 54.462037f }, +{ -204.699646f, -20.966759f, 74.975159f, -0.937504f, 0.000000f, -0.347976f, 63.123094f, 47.518821f }, +{ -207.067520f, -20.966751f, 79.783142f, -0.793604f, 0.000000f, -0.608435f, 62.382769f, 40.725774f }, +{ -210.791794f, -20.966751f, 83.766113f, -0.597880f, 0.000001f, -0.801586f, 59.657563f, 34.329668f }, +{ -215.690674f, -20.966751f, 86.784210f, -0.383174f, 0.000001f, -0.923676f, 55.104290f, 28.577385f }, +{ -221.582382f, -20.966751f, 88.697617f, -0.170028f, 0.000001f, -0.985439f, 48.879779f, 23.715683f }, +{ -228.285126f, -20.966751f, 89.366486f, -0.004631f, 0.000001f, -0.999989f, 41.140841f, 19.991411f }, +{ -233.272552f, -20.966751f, 89.153244f, 0.101449f, 0.000001f, -0.994841f, 35.072373f, 18.071997f }, +{ -238.232040f, -20.966751f, 88.499512f, 0.188036f, 0.000001f, -0.982162f, 28.845299f, 16.692535f }, +{ -243.261429f, -20.966751f, 87.384338f, 0.268237f, 0.000001f, -0.963353f, 22.333248f, 15.835422f }, +{ -248.458618f, -20.966747f, 85.786713f, 0.337432f, 0.000001f, -0.941350f, 15.409765f, 15.483181f }, +{ -253.921509f, -20.966747f, 83.685699f, 0.393673f, 0.000001f, -0.919251f, 7.948429f, 15.618211f }, +{ -259.747955f, -20.966747f, 81.060303f, 0.410820f, 0.000001f, -0.911717f, -0.177157f, 16.222941f }, +{ -259.747955f, -20.966751f, 111.264603f, -0.366219f, -0.000001f, 0.930529f, 12.994208f, -19.965071f }, +{ -253.885376f, -20.966755f, 113.571884f, -0.315937f, -0.000001f, 0.948780f, 21.024357f, -20.172935f }, +{ -247.666229f, -20.966757f, 115.459656f, -0.243578f, -0.000001f, 0.969881f, 29.298774f, -19.722674f }, +{ -241.153412f, -20.966763f, 116.927917f, -0.175846f, -0.000001f, 0.984418f, 37.742109f, -18.641708f }, +{ -234.409882f, -20.966763f, 117.976685f, -0.111723f, -0.000001f, 0.993739f, 46.278933f, -16.957548f }, +{ -227.498550f, -20.966763f, 118.605942f, -0.050166f, -0.000001f, 0.998741f, 54.833858f, -14.697611f }, +{ -220.482346f, -20.966763f, 118.815689f, 0.049994f, -0.000001f, 0.998749f, 63.331494f, -11.889319f }, +{ -205.143631f, -20.966763f, 117.432495f, 0.221684f, -0.000001f, 0.975119f, 81.105759f, -3.543264f }, +{ -191.825546f, -20.966755f, 113.455368f, 0.430806f, -0.000001f, 0.902444f, 95.327940f, 7.029456f }, +{ -180.870651f, -20.966755f, 107.142990f, 0.647042f, -0.000001f, 0.762454f, 105.700410f, 19.369521f }, +{ -172.621567f, -20.966755f, 98.754059f, 0.840384f, 0.000000f, 0.541992f, 111.925502f, 33.017599f }, +{ -167.420868f, -20.966753f, 88.547287f, 0.966795f, 0.000000f, 0.255554f, 113.705577f, 47.514307f }, +{ -165.611176f, -20.966751f, 76.781357f, 0.999957f, 0.000000f, -0.009295f, 110.742945f, 62.400328f }, +{ -166.340637f, -20.966751f, 68.696579f, 0.976852f, 0.000000f, -0.213918f, 106.343396f, 71.768664f }, +{ -168.510422f, -20.966749f, 61.101204f, 0.918400f, 0.000000f, -0.395654f, 100.431605f, 79.922555f }, +{ -172.092514f, -20.966755f, 54.065182f, 0.827210f, 0.000000f, -0.561892f, 93.071636f, 86.790413f }, +{ -177.058975f, -20.966747f, 47.658421f, 0.712639f, 0.000000f, -0.701531f, 84.327446f, 92.300650f }, +{ -183.381851f, -20.966743f, 41.950832f, 0.586577f, 0.000000f, -0.809893f, 74.263017f, 96.381707f }, +{ -191.033142f, -20.966743f, 37.012333f, 0.830953f, 0.000000f, 0.556343f, 62.942380f, 98.962027f }, +{ -181.454453f, -20.966751f, 32.298737f, 0.560396f, -0.000001f, 0.828225f, 72.363203f, 108.786445f }, +{ -173.805496f, -20.966743f, 26.319462f, 0.724928f, -0.000003f, 0.688825f, 78.920131f, 119.285616f }, +{ -168.002350f, -20.966745f, 19.235668f, 0.857930f, -0.000002f, 0.513767f, 82.783855f, 130.303376f }, +{ -163.961121f, -20.966740f, 11.208173f, 0.946024f, 0.000000f, 0.324095f, 84.125031f, 141.683643f }, +{ -161.597916f, -20.966740f, 2.397420f, 0.990004f, 0.000000f, 0.141040f, 83.114247f, 153.270415f }, +{ -160.828827f, -20.966740f, -7.035602f, 0.998047f, 0.000000f, -0.062465f, 79.922191f, 164.907572f }, +{ -162.772522f, -20.966736f, -21.426922f, 0.945614f, 0.000000f, -0.325292f, 71.317727f, 181.302331f }, +{ -168.407867f, -20.966743f, -33.734730f, 0.805843f, 0.000000f, -0.592129f, 59.198844f, 193.590982f }, +{ -177.441193f, -20.966736f, -43.721256f, 0.600640f, 0.000000f, -0.799519f, 44.021060f, 201.616710f }, +{ -189.578857f, -20.966732f, -51.148808f, 0.373832f, 0.000000f, -0.927496f, 26.239853f, 205.222777f }, +{ -204.527191f, -20.966740f, -55.779682f, 0.160102f, 0.000000f, -0.987101f, 6.310721f, 204.252461f }, +{ -221.992554f, -20.966740f, -57.376118f, 0.002576f, 0.000000f, -0.999997f, -15.310837f, 198.548949f }, +{ -229.371170f, -20.966740f, -57.068485f, -0.093624f, 0.000000f, -0.995608f, -24.017065f, 194.962735f }, +{ -236.805725f, -20.966740f, -56.173542f, -0.168365f, 0.000000f, -0.985725f, -32.534211f, 190.648469f }, +{ -244.142380f, -20.966740f, -54.733250f, -0.240737f, 0.000000f, -0.970590f, -40.696227f, 185.723508f }, +{ -251.227341f, -20.966732f, -52.789539f, -0.314259f, 0.000000f, -0.949337f, -48.337180f, 180.305151f }, +{ -257.906799f, -20.966732f, -50.384388f, -0.392630f, 0.000000f, -0.919696f, -55.291061f, 174.510773f }, +{ -264.026886f, -20.966732f, -47.559727f, -0.419059f, 0.000000f, -0.907959f, -61.391828f, 168.457698f }, +{ -264.026886f, -20.966738f, -14.334979f, 0.543306f, 0.000000f, 0.839534f, -46.903330f, 128.650867f }, +{ -257.339294f, -20.966736f, -18.662861f, 0.501817f, 0.000000f, 0.864974f, -40.778150f, 136.752428f }, +{ -251.050217f, -20.966736f, -22.109791f, 0.426524f, 0.000000f, 0.904476f, -34.746278f, 143.624739f }, +{ -245.054810f, -20.966736f, -24.717709f, 0.331870f, 0.000000f, 0.943325f, -28.700379f, 149.363753f }, +{ -239.248169f, -20.966736f, -26.528568f, 0.220540f, 0.000000f, 0.975378f, -22.533070f, 154.065492f }, +{ -233.525421f, -20.966736f, -27.584324f, 0.100336f, 0.000000f, 0.994954f, -16.136991f, 157.825952f }, +{ -227.781708f, -20.966736f, -27.926914f, -0.045215f, 0.000000f, 0.998977f, -9.404798f, 160.741110f }, +{ -220.280746f, -20.966736f, -27.192783f, -0.239464f, 0.000000f, 0.970905f, -0.097693f, 163.132527f }, +{ -213.751633f, -20.966736f, -25.074284f, -0.460291f, 0.000000f, 0.887768f, 8.648720f, 163.441519f }, +{ -208.369156f, -20.966736f, -21.697269f, -0.678343f, 0.000000f, 0.734745f, 16.570136f, 161.742661f }, +{ -204.308121f, -20.966736f, -17.187603f, -0.860689f, 0.000000f, 0.509130f, 23.402251f, 158.110511f }, +{ -201.743317f, -20.966747f, -11.671123f, -0.971980f, 0.000000f, 0.235065f, 28.880766f, 152.619616f }, +{ -200.849533f, -20.966740f, -5.273685f, -0.999103f, 0.000000f, -0.042355f, 32.741388f, 145.344557f }, +{ -201.724655f, -20.966740f, 1.288052f, -0.949258f, 0.000000f, -0.314499f, 34.554308f, 137.101264f }, +{ -204.242859f, -20.966745f, 7.031773f, -0.823833f, 0.000000f, -0.566833f, 34.041921f, 129.121540f }, +{ -208.243301f, -20.966740f, 11.810628f, -0.639055f, 0.000000f, -0.769161f, 31.332898f, 121.651460f }, +{ -213.565170f, -20.966740f, 15.477796f, -0.424211f, 0.000001f, -0.905563f, 26.555888f, 114.937053f }, +{ -220.047684f, -20.966743f, 17.886265f, -0.205822f, 0.000004f, -0.978589f, 19.839473f, 109.224409f }, +{ -148.686584f, -20.966757f, 116.550354f, 0.000000f, -0.000001f, 1.000000f, 148.362720f, 22.133174f }, +{ -72.924095f, -20.966761f, 116.550354f, 0.071640f, -0.000001f, 0.997431f, 239.134392f, 55.171337f }, +{ -44.133286f, -20.966759f, 113.442535f, 0.268782f, -0.000001f, 0.963201f, 272.273660f, 71.449816f }, +{ -20.467419f, -20.966759f, 104.692368f, 0.513694f, -0.000001f, 0.857974f, 296.812166f, 92.253563f }, +{ -1.975434f, -20.966759f, 91.159866f, 0.734379f, 0.000000f, 0.678739f, 313.066387f, 116.530870f }, +{ 11.293716f, -20.966763f, 73.704994f, 0.894190f, 0.000000f, 0.447688f, 321.352617f, 143.230046f }, +{ 19.291100f, -20.966763f, 53.187717f, 0.979694f, 0.000000f, 0.200499f, 321.987274f, 171.299429f }, +{ 21.967770f, -20.966759f, 30.467985f, 0.999373f, 0.000000f, -0.035418f, 315.286714f, 199.687265f }, +{ 19.338877f, -20.966749f, 6.999157f, 0.959992f, 0.000000f, -0.280027f, 301.902798f, 226.659149f }, +{ 11.340330f, -20.966751f, -13.645114f, 0.842717f, 0.000000f, -0.538357f, 283.317205f, 247.905254f }, +{ -2.195676f, -20.966743f, -30.821491f, 0.643022f, 0.000000f, -0.765848f, 259.609426f, 262.581684f }, +{ -21.436935f, -20.966740f, -43.886723f, 0.400098f, 0.000000f, -0.916472f, 230.858877f, 269.844599f }, +{ -46.551262f, -20.966736f, -52.197575f, 0.167743f, 0.000000f, -0.985831f, 197.145034f, 268.850158f }, +{ -77.706444f, -20.966743f, -55.110798f, 0.031064f, 0.000000f, -0.999517f, 158.547374f, 258.754495f }, +{ -148.686584f, -20.966743f, -55.110798f, 0.000000f, 0.000000f, -1.000000f, 73.505490f, 227.801797f }, +{ -105.897141f, -20.966753f, 85.087540f, 0.894427f, 0.000000f, -0.447214f, 185.908946f, 78.488452f }, +{ -105.897141f, -20.966742f, -23.647968f, 0.447214f, 0.000000f, 0.894427f, 138.492050f, 208.765350f }, +{ -77.958153f, -20.966742f, -23.647968f, -0.079186f, 0.000000f, 0.996860f, 171.965974f, 220.948864f }, +{ -58.874207f, -20.966740f, -21.368664f, -0.304705f, 0.000000f, 0.952447f, 195.824559f, 226.540055f }, +{ -44.341877f, -20.966745f, -15.146022f, -0.579111f, 0.000000f, 0.815249f, 215.949404f, 225.421851f }, +{ -33.878738f, -20.966743f, -5.902942f, -0.798828f, 0.000000f, 0.601559f, 232.516059f, 218.910357f }, +{ -27.002363f, -20.966749f, 5.437657f, -0.929901f, 0.000000f, 0.367810f, 245.700060f, 208.321713f }, +{ -23.230320f, -20.966747f, 17.952679f, -0.987642f, -0.000001f, 0.156725f, 255.676941f, 194.972086f }, +{ -22.080179f, -20.966755f, 30.719687f, -0.999434f, 0.000000f, -0.033649f, 262.622269f, 180.177463f }, +{ -23.442402f, -20.966751f, 44.972424f, -0.970480f, 0.000000f, -0.241182f, 267.205431f, 162.507202f }, +{ -27.692215f, -20.966751f, 57.903645f, -0.878100f, 0.000000f, -0.478477f, 267.752663f, 145.160958f }, +{ -35.074326f, -20.966751f, 68.947113f, -0.700409f, 0.000000f, -0.713742f, 263.723906f, 128.710531f }, +{ -45.833443f, -20.966755f, 77.536469f, -0.453361f, 0.000001f, -0.891327f, 254.578922f, 113.727776f }, +{ -60.214287f, -20.966755f, 83.105392f, -0.193834f, 0.000001f, -0.981034f, 239.777576f, 100.784454f }, +{ -78.461555f, -20.966755f, 85.087540f, -0.036044f, 0.000001f, -0.999350f, 218.779751f, 90.452444f }, +{ 53.459190f, 2.970489f, -63.834198f, 0.000000f, 0.000000f, -1.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970482f, 19.696451f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970485f, 19.696451f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970482f, 37.767296f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970482f, 37.767296f, -0.894427f, 0.000000f, 0.447214f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970471f, 52.887688f, -0.994427f, 0.000000f, 0.105425f, 0.000000f, 255.000000f }, +{ 54.761124f, 2.970478f, 61.040325f, -0.930341f, 0.000000f, 0.366696f, 0.000000f, 255.000000f }, +{ 58.744659f, 2.970474f, 68.629539f, -0.769108f, -0.000001f, 0.639119f, 0.000000f, 255.000000f }, +{ 65.526382f, 2.970473f, 75.245560f, -0.554146f, -0.000001f, 0.832420f, 0.000000f, 255.000000f }, +{ 75.222885f, 2.970474f, 80.478622f, -0.334245f, -0.000001f, 0.942486f, 0.000000f, 255.000000f }, +{ 87.950760f, 2.970474f, 83.918953f, -0.139337f, -0.000002f, 0.990245f, 0.000000f, 255.000000f }, +{ 103.826599f, 2.970474f, 85.156792f, -0.014576f, -0.000002f, 0.999894f, 0.000000f, 255.000000f }, +{ 107.486267f, 2.970474f, 85.094475f, 0.038307f, -0.000002f, 0.999266f, 0.000000f, 255.000000f }, +{ 111.371353f, 2.970474f, 84.904106f, 0.070572f, -0.000002f, 0.997507f, 0.000000f, 255.000000f }, +{ 115.334160f, 2.970474f, 84.580559f, 0.105682f, -0.000002f, 0.994400f, 0.000000f, 255.000000f }, +{ 119.227013f, 2.970474f, 84.118721f, 0.147635f, -0.000002f, 0.989042f, 0.000000f, 255.000000f }, +{ 122.902229f, 2.970474f, 83.513466f, 0.202285f, -0.000002f, 0.979327f, 0.000000f, 255.000000f }, +{ 126.212128f, 2.970474f, 82.759666f, 0.996088f, 0.000000f, -0.088370f, 0.000000f, 255.000000f }, +{ 114.179916f, 2.970478f, 65.426537f, 0.125438f, 0.000002f, -0.992102f, 0.000000f, 255.000000f }, +{ 112.235428f, 2.970474f, 65.933624f, -0.222749f, 0.000002f, -0.974876f, 0.000000f, 255.000000f }, +{ 110.283180f, 2.970474f, 66.348511f, -0.174788f, 0.000002f, -0.984606f, 0.000000f, 255.000000f }, +{ 108.268738f, 2.970474f, 66.671196f, -0.124447f, 0.000002f, -0.992226f, 0.000000f, 255.000000f }, +{ 106.137703f, 2.970474f, 66.901688f, -0.075842f, 0.000002f, -0.997120f, 0.000000f, 255.000000f }, +{ 103.835670f, 2.970474f, 67.039986f, -0.032153f, 0.000002f, -0.999483f, 0.000000f, 255.000000f }, +{ 101.308228f, 2.970474f, 67.086082f, 0.055747f, 0.000002f, -0.998445f, 0.000000f, 255.000000f }, +{ 95.838806f, 2.970474f, 66.577293f, 0.226773f, 0.000002f, -0.973948f, 0.000000f, 255.000000f }, +{ 91.224388f, 2.970478f, 65.167015f, 0.433606f, 0.000001f, -0.901103f, 0.000000f, 255.000000f }, +{ 87.527145f, 2.970478f, 63.029404f, 0.640544f, 0.000000f, -0.767921f, 0.000000f, 255.000000f }, +{ 84.809280f, 2.970478f, 60.338612f, 0.827378f, 0.000000f, -0.561646f, 0.000000f, 255.000000f }, +{ 83.132957f, 2.970478f, 57.268784f, 0.960620f, 0.000000f, -0.277867f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970479f, 53.994072f, 0.998339f, 0.000000f, -0.057605f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970478f, 37.767296f, 0.447214f, 0.000000f, 0.894427f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970478f, 37.767296f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970482f, 19.696451f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970482f, 19.696451f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970489f, -63.834198f, 0.000000f, 0.000000f, -1.000000f, 0.000000f, 255.000000f }, +{ 109.261765f, 2.970490f, -33.040283f, -0.936759f, 0.000000f, 0.349975f, 0.000000f, 255.000000f }, +{ 158.509918f, 2.970482f, 10.661288f, -0.945897f, 0.000000f, -0.324468f, 0.000000f, 255.000000f }, +{ 110.660858f, 2.970478f, 56.206810f, -0.475466f, 0.000000f, 0.879734f, 0.000000f, 255.000000f }, +{ 147.037323f, 2.970478f, 56.206810f, 0.529090f, -0.000002f, 0.848566f, 0.000000f, 255.000000f }, +{ 175.299042f, 2.970477f, 25.597071f, -0.347260f, -0.000006f, 0.937769f, 0.000000f, 255.000000f }, +{ 203.001129f, 2.970478f, 56.206810f, -0.267475f, 0.000000f, 0.963565f, 0.000000f, 255.000000f }, +{ 237.139038f, 2.970478f, 56.206810f, 0.947348f, 0.000000f, -0.320206f, 0.000000f, 255.000000f }, +{ 189.569809f, 2.970482f, 11.767657f, 0.937358f, 0.000000f, 0.348368f, 0.000000f, 255.000000f }, +{ 239.097778f, 2.970486f, -33.040283f, 0.470435f, 0.000000f, -0.882435f, 0.000000f, 255.000000f }, +{ 202.161682f, 2.970486f, -33.040283f, -0.518991f, 0.000000f, -0.854780f, 0.000000f, 255.000000f }, +{ 173.620132f, 2.970482f, -3.168332f, 0.311085f, 0.000000f, -0.950382f, 0.000000f, 255.000000f }, +{ 143.679504f, 2.970490f, -33.040283f, 0.252382f, 0.000000f, -0.967628f, 0.000000f, 255.000000f }, +{ 246.695496f, 2.970477f, 44.635109f, -0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 246.695496f, 2.970479f, 54.095207f, -0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 243.335144f, 2.970479f, 54.095207f, -0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 243.335144f, 2.970478f, 56.104118f, -0.447214f, 0.000000f, 0.894427f, 0.000000f, 255.000000f }, +{ 252.174316f, 2.970478f, 56.104118f, 0.894427f, 0.000000f, 0.447214f, 0.000000f, 255.000000f }, +{ 252.174316f, 2.970475f, 54.095207f, 0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 248.813965f, 2.970479f, 54.095207f, 0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 248.813965f, 2.970477f, 44.635109f, 0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 253.836212f, 2.970477f, 44.635109f, -0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 253.836212f, 2.970478f, 56.341530f, 0.287199f, 0.000000f, 0.957871f, 0.000000f, 255.000000f }, +{ 258.931549f, 2.970471f, 51.191429f, -0.319282f, 0.000000f, 0.947660f, 0.000000f, 255.000000f }, +{ 264.026886f, 2.970478f, 56.341530f, 0.877850f, 0.000000f, 0.478935f, 0.000000f, 255.000000f }, +{ 264.026886f, 2.970477f, 44.635109f, 0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 261.908356f, 2.970477f, 44.635109f, -0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 261.908356f, 2.970467f, 51.721062f, 0.301814f, 0.000000f, -0.953367f, 0.000000f, 255.000000f }, +{ 258.931549f, 2.970471f, 48.634651f, -0.326641f, 0.000000f, -0.945149f, 0.000000f, 255.000000f }, +{ 255.954681f, 2.970471f, 51.721062f, 0.879074f, 0.000000f, -0.476685f, 0.000000f, 255.000000f }, +{ 255.954681f, 2.970477f, 44.635109f, 0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 53.398365f, 9.484123f, -118.046249f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 53.398365f, 9.484118f, -89.641510f, -0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 58.399651f, 9.484118f, -89.641510f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 58.399651f, 9.484123f, -118.046249f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 64.683319f, 9.484123f, -118.046249f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 64.683319f, 9.484118f, -89.641510f, -0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -89.641510f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -92.719223f, -0.390384f, -0.000002f, 0.920652f, 0.000000f, 255.000000f }, +{ 71.361206f, 9.484118f, -90.693527f, -0.520918f, -0.000002f, 0.853607f, 0.000000f, 255.000000f }, +{ 75.070610f, 9.484118f, -89.192673f, 0.065749f, -0.000003f, 0.997836f, 0.000000f, 255.000000f }, +{ 78.221947f, 9.484118f, -90.116470f, 0.641452f, -0.000002f, 0.767163f, 0.000000f, 255.000000f }, +{ 80.447113f, 9.484106f, -92.906830f, 0.914903f, -0.000001f, 0.403674f, 0.000000f, 255.000000f }, +{ 81.069901f, 9.484118f, -95.010895f, 0.988384f, 0.000000f, 0.151978f, 0.000000f, 255.000000f }, +{ 81.290161f, 9.484118f, -97.592270f, 0.999598f, 0.000000f, 0.028362f, 0.000000f, 255.000000f }, +{ 81.290161f, 9.484123f, -118.046249f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 76.288872f, 9.484123f, -118.046249f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 76.288872f, 9.484118f, -97.720505f, -0.997195f, 0.000000f, -0.074851f, 0.000000f, 255.000000f }, +{ 76.046646f, 9.484118f, -95.573715f, -0.873911f, 0.000001f, -0.486087f, 0.000000f, 255.000000f }, +{ 74.507790f, 9.484118f, -93.751663f, -0.206069f, 0.000002f, -0.978537f, 0.000000f, 255.000000f }, +{ 72.154381f, 9.484118f, -93.999222f, 0.497835f, 0.000001f, -0.867272f, 0.000000f, 255.000000f }, +{ 70.869621f, 9.484118f, -95.136749f, 0.791861f, 0.000001f, -0.610702f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -97.015213f, 0.982874f, 0.000000f, -0.184277f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484123f, -118.046249f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 116.042702f, 9.484123f, -111.377884f, 0.874270f, -0.000001f, 0.485440f, 0.000000f, 255.000000f }, +{ 116.042702f, 9.484123f, -116.315048f, 0.760144f, 0.000001f, -0.649755f, 0.000000f, 255.000000f }, +{ 112.247803f, 9.484123f, -118.552078f, 0.152177f, 0.000001f, -0.988353f, 0.000000f, 255.000000f }, +{ 107.574234f, 9.484123f, -118.394455f, -0.459333f, 0.000001f, -0.888264f, 0.000000f, 255.000000f }, +{ 103.539482f, 9.484123f, -115.040680f, -0.838627f, 0.000001f, -0.544706f, 0.000000f, 255.000000f }, +{ 102.209610f, 9.484123f, -112.118805f, -0.959193f, 0.000000f, -0.282751f, 0.000000f, 255.000000f }, +{ 101.385559f, 9.484118f, -108.374069f, -0.993577f, 0.000000f, -0.113155f, 0.000000f, 255.000000f }, +{ 101.102959f, 9.484118f, -103.811813f, -0.999878f, 0.000000f, 0.015607f, 0.000000f, 255.000000f }, +{ 101.339844f, 9.484118f, -99.454697f, -0.989803f, 0.000000f, 0.142441f, 0.000000f, 255.000000f }, +{ 102.036247f, 9.484118f, -95.777939f, -0.953092f, -0.000001f, 0.302681f, 0.000000f, 255.000000f }, +{ 103.170799f, 9.484106f, -92.831436f, -0.859240f, -0.000001f, 0.511573f, 0.000000f, 255.000000f }, +{ 104.722122f, 9.484118f, -90.665039f, -0.601898f, -0.000001f, 0.798573f, 0.000000f, 255.000000f }, +{ 107.933678f, 9.484118f, -88.927658f, -0.064729f, -0.000002f, 0.997903f, 0.000000f, 255.000000f }, +{ 111.632736f, 9.484118f, -89.470520f, 0.480740f, -0.000002f, 0.876863f, 0.000000f, 255.000000f }, +{ 113.549179f, 9.484118f, -91.009384f, 0.770417f, -0.000001f, 0.637540f, 0.000000f, 255.000000f }, +{ 114.952675f, 9.484106f, -93.103928f, 0.938897f, 0.000000f, 0.344197f, 0.000000f, 255.000000f }, +{ 116.387047f, 9.484118f, -99.154877f, 0.994578f, 0.000000f, 0.103992f, 0.000000f, 255.000000f }, +{ 116.619774f, 9.484118f, -104.965958f, 0.454185f, 0.000001f, -0.890908f, 0.000000f, 255.000000f }, +{ 106.104248f, 9.484118f, -104.965958f, 0.931736f, 0.000000f, -0.363137f, 0.000000f, 255.000000f }, +{ 106.676575f, 9.484123f, -110.009995f, 0.932112f, 0.000000f, 0.362171f, 0.000000f, 255.000000f }, +{ 108.374535f, 9.484123f, -113.130463f, 0.561654f, -0.000001f, 0.827372f, 0.000000f, 255.000000f }, +{ 111.169655f, 9.484123f, -114.199112f, -0.059665f, -0.000002f, 0.998218f, 0.000000f, 255.000000f }, +{ 113.774490f, 9.484123f, -113.485794f, -0.556104f, -0.000002f, 0.831112f, 0.000000f, 255.000000f }, +{ 106.040123f, 9.484118f, -101.247055f, 0.458115f, -0.000001f, 0.888893f, 0.000000f, 255.000000f }, +{ 111.618484f, 9.484118f, -101.247055f, -0.917639f, -0.000001f, 0.397415f, 0.000000f, 255.000000f }, +{ 111.312141f, 9.484118f, -96.746857f, -0.968412f, 0.000000f, -0.249357f, 0.000000f, 255.000000f }, +{ 110.364601f, 9.484118f, -94.098984f, -0.666434f, 0.000002f, -0.745564f, 0.000000f, 255.000000f }, +{ 108.733131f, 9.484106f, -93.232178f, 0.199195f, 0.000001f, -0.979960f, 0.000000f, 255.000000f }, +{ 107.208519f, 9.484118f, -94.113220f, 0.848531f, 0.000001f, -0.529146f, 0.000000f, 255.000000f }, +{ 106.325096f, 9.484118f, -96.775345f, 0.988917f, 0.000000f, -0.148471f, 0.000000f, 255.000000f }, +{ 122.262253f, 9.484123f, -118.046249f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 122.262253f, 9.484118f, -89.641510f, -0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 127.263535f, 9.484118f, -89.641510f, 0.888400f, -0.000001f, 0.459070f, 0.000000f, 255.000000f }, +{ 127.391785f, 9.484118f, -97.335800f, -0.832354f, -0.000001f, 0.554244f, 0.000000f, 255.000000f }, +{ 128.306671f, 9.484118f, -94.372665f, -0.943875f, -0.000001f, 0.330303f, 0.000000f, 255.000000f }, +{ 129.111130f, 9.484118f, -92.203903f, -0.906859f, -0.000001f, 0.421435f, 0.000000f, 255.000000f }, +{ 129.876404f, 9.484118f, -90.715500f, -0.732608f, -0.000001f, 0.680651f, 0.000000f, 255.000000f }, +{ 131.574371f, 9.484118f, -89.323883f, -0.237380f, -0.000001f, 0.971417f, 0.000000f, 255.000000f }, +{ 133.556717f, 9.484118f, -89.280533f, 0.272164f, -0.000002f, 0.962251f, 0.000000f, 255.000000f }, +{ 135.214310f, 9.484118f, -90.026230f, 0.953239f, -0.000001f, 0.302219f, 0.000000f, 255.000000f }, +{ 134.829590f, 9.484118f, -95.155746f, 0.189441f, 0.000002f, -0.981892f, 0.000000f, 255.000000f }, +{ 132.649551f, 9.484118f, -94.450439f, 0.149986f, 0.000002f, -0.988688f, 0.000000f, 255.000000f }, +{ 130.914764f, 9.484118f, -95.135269f, 0.671985f, 0.000002f, -0.740564f, 0.000000f, 255.000000f }, +{ 129.543335f, 9.484118f, -96.915451f, 0.885876f, 0.000001f, -0.463921f, 0.000000f, 255.000000f }, +{ 128.513855f, 9.484118f, -99.379593f, 0.955085f, 0.000001f, -0.296334f, 0.000000f, 255.000000f }, +{ 127.804985f, 9.484118f, -102.116226f, 0.982240f, 0.000000f, -0.187627f, 0.000000f, 255.000000f }, +{ 127.395340f, 9.484118f, -104.713943f, 0.998278f, 0.000000f, -0.058653f, 0.000000f, 255.000000f }, +{ 127.263535f, 9.484123f, -118.046249f, 0.445434f, 0.000001f, -0.895315f, 0.000000f, 255.000000f }, +{ 155.668289f, 9.484123f, -112.788498f, 0.872224f, -0.000001f, 0.489107f, 0.000000f, 255.000000f }, +{ 155.668289f, 9.484123f, -116.571518f, 0.821354f, 0.000001f, -0.570419f, 0.000000f, 255.000000f }, +{ 154.127060f, 9.484123f, -117.804031f, 0.488794f, 0.000002f, -0.872399f, 0.000000f, 255.000000f }, +{ 152.305023f, 9.484123f, -118.637589f, 0.117071f, 0.000003f, -0.993124f, 0.000000f, 255.000000f }, +{ 150.903000f, 9.484123f, -118.586227f, -0.347726f, 0.000002f, -0.937596f, 0.000000f, 255.000000f }, +{ 149.472794f, 9.484123f, -117.781754f, -0.743957f, 0.000001f, -0.668227f, 0.000000f, 255.000000f }, +{ 148.448669f, 9.484123f, -116.186508f, -0.922915f, 0.000001f, -0.385003f, 0.000000f, 255.000000f }, +{ 148.102249f, 9.484123f, -115.096786f, 0.319982f, 0.000002f, -0.947424f, 0.000000f, 255.000000f }, +{ 146.276031f, 9.484123f, -117.172348f, 0.536214f, 0.000002f, -0.844082f, 0.000000f, 255.000000f }, +{ 142.652115f, 9.484123f, -118.815689f, -0.095167f, 0.000003f, -0.995461f, 0.000000f, 255.000000f }, +{ 139.866501f, 9.484123f, -117.808792f, -0.663668f, 0.000002f, -0.748027f, 0.000000f, 255.000000f }, +{ 137.850311f, 9.484123f, -115.206024f, -0.935434f, 0.000001f, -0.353502f, 0.000000f, 255.000000f }, +{ 137.073761f, 9.484123f, -111.634354f, -0.994825f, 0.000000f, 0.101602f, 0.000000f, 255.000000f }, +{ 138.144791f, 9.484118f, -107.571106f, -0.821232f, -0.000001f, 0.570594f, 0.000000f, 255.000000f }, +{ 141.623840f, 9.484118f, -104.049301f, -0.614743f, -0.000001f, 0.788728f, 0.000000f, 255.000000f }, +{ 144.391052f, 9.484118f, -102.166397f, -0.533800f, -0.000001f, 0.845611f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -100.028793f, -0.946986f, 0.000000f, 0.321275f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -97.335800f, -0.985542f, 0.000000f, -0.169429f, 0.000000f, 255.000000f }, +{ 147.180527f, 9.484118f, -94.538605f, -0.721135f, 0.000001f, -0.692794f, 0.000000f, 255.000000f }, +{ 145.869064f, 9.484118f, -93.718704f, -0.178468f, 0.000002f, -0.983946f, 0.000000f, 255.000000f }, +{ 143.898575f, 9.484118f, -93.732071f, 0.275751f, 0.000003f, -0.961229f, 0.000000f, 255.000000f }, +{ 141.682312f, 9.484118f, -94.706924f, 0.547231f, 0.000002f, -0.836982f, 0.000000f, 255.000000f }, +{ 137.779068f, 9.484118f, -98.297592f, -0.401856f, 0.000002f, -0.915703f, 0.000000f, 255.000000f }, +{ 137.779068f, 9.484118f, -92.526871f, -0.805424f, -0.000001f, 0.592699f, 0.000000f, 255.000000f }, +{ 141.658264f, 9.484118f, -89.665543f, -0.393509f, -0.000002f, 0.919321f, 0.000000f, 255.000000f }, +{ 144.054428f, 9.484118f, -88.951340f, -0.070072f, -0.000003f, 0.997542f, 0.000000f, 255.000000f }, +{ 147.152328f, 9.484118f, -89.072159f, 0.314714f, -0.000002f, 0.949187f, 0.000000f, 255.000000f }, +{ 150.474655f, 9.484118f, -90.715500f, 0.737681f, -0.000002f, 0.675150f, 0.000000f, 255.000000f }, +{ 152.600082f, 9.484118f, -94.111435f, 0.963322f, 0.000000f, 0.268347f, 0.000000f, 255.000000f }, +{ 152.911179f, 9.484118f, -96.502243f, 0.999034f, 0.000000f, 0.043950f, 0.000000f, 255.000000f }, +{ 152.932556f, 9.484123f, -113.100784f, 0.988647f, 0.000000f, 0.150259f, 0.000000f, 255.000000f }, +{ 153.103531f, 9.484123f, -113.846451f, 0.722615f, -0.000001f, 0.691251f, 0.000000f, 255.000000f }, +{ 153.680603f, 9.484123f, -114.199112f, -0.065774f, -0.000002f, 0.997835f, 0.000000f, 255.000000f }, +{ 154.124680f, 9.484123f, -114.032883f, -0.508023f, -0.000002f, 0.861344f, 0.000000f, 255.000000f }, +{ 154.796753f, 9.484123f, -113.553177f, -0.634043f, -0.000002f, 0.773298f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484123f, -110.800797f, -0.988652f, 0.000000f, 0.150224f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -103.491226f, 0.063729f, 0.000001f, -0.997967f, 0.000000f, 255.000000f }, +{ 146.048050f, 9.484118f, -104.727600f, 0.606494f, 0.000001f, -0.795088f, 0.000000f, 255.000000f }, +{ 144.556686f, 9.484118f, -105.944382f, 0.698230f, 0.000002f, -0.715873f, 0.000000f, 255.000000f }, +{ 143.421539f, 9.484118f, -107.154037f, 0.856732f, 0.006809f, -0.515717f, 0.000000f, 255.000000f }, +{ 142.162918f, 9.484122f, -109.601837f, 0.996222f, 0.008519f, -0.086430f, 0.000000f, 255.000000f }, +{ 142.329147f, 9.484123f, -112.551010f, 0.896470f, -0.000001f, 0.443104f, 0.000000f, 255.000000f }, +{ 143.188812f, 9.484123f, -113.667160f, 0.487260f, -0.000002f, 0.873257f, 0.000000f, 255.000000f }, +{ 144.447449f, 9.484123f, -114.070877f, -0.092078f, -0.000002f, 0.995752f, 0.000000f, 255.000000f }, +{ 145.715591f, 9.484123f, -113.693283f, -0.563378f, -0.000001f, 0.826199f, 0.000000f, 255.000000f }, +{ 146.898224f, 9.484123f, -112.589005f, -0.789808f, -0.000001f, 0.613355f, 0.000000f, 255.000000f }, +{ 147.430771f, 9.484123f, -111.777725f, -0.878742f, -0.000001f, 0.477296f, 0.000000f, 255.000000f }, +{ 173.749878f, 9.484123f, -112.467911f, 0.866044f, -0.000001f, 0.499968f, 0.000000f, 255.000000f }, +{ 173.749878f, 9.484123f, -117.276840f, 0.738938f, 0.000002f, -0.673773f, 0.000000f, 255.000000f }, +{ 172.085159f, 9.484123f, -118.160263f, 0.289883f, 0.000003f, -0.957062f, 0.000000f, 255.000000f }, +{ 168.812698f, 9.484123f, -118.815689f, -0.052447f, 0.000003f, -0.998624f, 0.000000f, 255.000000f }, +{ 166.009262f, 9.484123f, -118.315506f, -0.398492f, 0.000002f, -0.917172f, 0.000000f, 255.000000f }, +{ 163.547806f, 9.484123f, -116.887375f, -0.667370f, 0.000002f, -0.744726f, 0.000000f, 255.000000f }, +{ 161.503128f, 9.484123f, -114.639938f, -0.842882f, 0.000001f, -0.538099f, 0.000000f, 255.000000f }, +{ 159.950012f, 9.484123f, -111.681854f, -0.942324f, 0.000000f, -0.334701f, 0.000000f, 255.000000f }, +{ 158.963303f, 9.484118f, -108.121765f, -0.989253f, 0.000000f, -0.146212f, 0.000000f, 255.000000f }, +{ 158.617767f, 9.484118f, -104.068314f, -0.998414f, 0.000000f, 0.056296f, 0.000000f, 255.000000f }, +{ 159.531387f, 9.484118f, -96.903595f, -0.905095f, -0.000001f, 0.425210f, 0.000000f, 255.000000f }, +{ 163.822617f, 9.484118f, -90.542221f, -0.501771f, -0.000002f, 0.865000f, 0.000000f, 255.000000f }, +{ 169.115997f, 9.484118f, -88.872086f, 0.060412f, -0.000003f, 0.998173f, 0.000000f, 255.000000f }, +{ 173.301041f, 9.484118f, -89.897995f, 0.917345f, -0.000001f, 0.398092f, 0.000000f, 255.000000f }, +{ 173.301041f, 9.484118f, -95.027512f, 0.153606f, 0.000003f, -0.988132f, 0.000000f, 255.000000f }, +{ 169.582138f, 9.484118f, -93.616898f, 0.141905f, 0.000002f, -0.989880f, 0.000000f, 255.000000f }, +{ 166.473557f, 9.484118f, -94.882645f, 0.742680f, 0.000001f, -0.669646f, 0.000000f, 255.000000f }, +{ 164.462112f, 9.484118f, -98.442444f, 0.967176f, 0.000000f, -0.254107f, 0.000000f, 255.000000f }, +{ 163.747299f, 9.484118f, -103.940063f, 0.998594f, 0.000000f, 0.053008f, 0.000000f, 255.000000f }, +{ 164.523849f, 9.484122f, -109.302322f, 0.912953f, -0.000001f, 0.408064f, 0.000000f, 255.000000f }, +{ 166.711029f, 9.484123f, -112.812241f, 0.468894f, -0.000002f, 0.883254f, 0.000000f, 255.000000f }, +{ 171.313354f, 9.484123f, -113.911758f, -0.280562f, -0.000002f, 0.959836f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484123f, -113.301437f, 0.869996f, -0.000001f, 0.493059f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484123f, -117.725662f, 0.673699f, 0.000002f, -0.739006f, 0.000000f, 255.000000f }, +{ 186.637802f, 9.484123f, -118.378738f, 0.251252f, 0.000003f, -0.967922f, 0.000000f, 255.000000f }, +{ 184.602036f, 9.484123f, -118.792831f, 0.027993f, 0.000002f, -0.999608f, 0.000000f, 255.000000f }, +{ 182.419891f, 9.484123f, -118.666077f, -0.249737f, 0.000002f, -0.968314f, 0.000000f, 255.000000f }, +{ 181.128311f, 9.484123f, -118.195877f, -0.534105f, 0.000002f, -0.845418f, 0.000000f, 255.000000f }, +{ 180.089645f, 9.484123f, -117.373001f, -0.779634f, 0.000001f, -0.626236f, 0.000000f, 255.000000f }, +{ 179.323486f, 9.484123f, -116.165436f, -0.929593f, 0.000001f, -0.368587f, 0.000000f, 255.000000f }, +{ 178.849426f, 9.484123f, -114.541092f, -0.989265f, 0.000000f, -0.146131f, 0.000000f, 255.000000f }, +{ 178.687042f, 9.484123f, -112.467911f, -0.999661f, 0.000000f, -0.026047f, 0.000000f, 255.000000f }, +{ 178.687042f, 9.484118f, -94.001602f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 175.416977f, 9.484118f, -94.001602f, -0.996832f, -0.000001f, 0.079535f, 0.000000f, 255.000000f }, +{ 178.200211f, 9.484118f, -89.945480f, -0.823749f, -0.000001f, 0.566955f, 0.000000f, 255.000000f }, +{ 180.755478f, 9.484117f, -86.238449f, -0.837145f, -0.000001f, 0.546981f, 0.000000f, 255.000000f }, +{ 183.239502f, 9.484117f, -82.331924f, -0.315664f, -0.000001f, 0.948871f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484117f, -82.331924f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484118f, -89.641510f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484118f, -89.641510f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484118f, -94.001602f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484118f, -94.001602f, 0.896316f, -0.004678f, -0.443391f, 0.000000f, 255.000000f }, +{ 183.724243f, 9.484123f, -111.466034f, 0.997969f, -0.005230f, 0.063485f, 0.000000f, 255.000000f }, +{ 183.847443f, 9.484123f, -112.446518f, 0.909068f, 0.001063f, 0.416646f, 0.000000f, 255.000000f }, +{ 184.448257f, 9.484123f, -113.686172f, 0.726480f, -0.015559f, 0.687011f, 0.000000f, 255.000000f }, +{ 184.972198f, 9.484123f, -113.977371f, 0.170193f, -0.000003f, 0.985411f, 0.000000f, 255.000000f }, +{ 186.488205f, 9.484123f, -113.985397f, -0.229252f, -0.000002f, 0.973367f, 0.000000f, 255.000000f }, +{ 192.280289f, 9.484123f, -118.046249f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 192.280289f, 9.484118f, -89.641510f, -0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 197.281570f, 9.484118f, -89.641510f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 197.281570f, 9.484123f, -118.046249f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 209.400085f, 9.484123f, -118.687454f, -0.775277f, 0.000002f, -0.631621f, 0.000000f, 255.000000f }, +{ 200.872238f, 9.484118f, -89.641510f, -0.487542f, -0.000001f, 0.873100f, 0.000000f, 255.000000f }, +{ 205.873535f, 9.484118f, -89.641510f, 0.791121f, -0.000001f, 0.611659f, 0.000000f, 255.000000f }, +{ 210.041275f, 9.484118f, -105.863632f, 0.395561f, -0.000001f, 0.918440f, 0.000000f, 255.000000f }, +{ 210.169510f, 9.484118f, -105.863632f, -0.791121f, -0.000001f, 0.611659f, 0.000000f, 255.000000f }, +{ 214.337250f, 9.484118f, -89.641510f, -0.395561f, -0.000001f, 0.918440f, 0.000000f, 255.000000f }, +{ 219.338531f, 9.484118f, -89.641510f, 0.975084f, 0.000000f, 0.221838f, 0.000000f, 255.000000f }, +{ 210.810699f, 9.484123f, -118.687454f, 0.387639f, 0.000002f, -0.921811f, 0.000000f, 255.000000f }, +{ -227.530014f, 20.966755f, 18.889763f, -0.132902f, 0.000004f, -0.991129f, 11.312366f, 104.759421f }, +{ -227.530014f, 20.966747f, 49.094074f, -0.113407f, 0.000000f, 0.993549f, 24.483732f, 68.571394f }, +{ -220.271423f, 20.966747f, 49.922592f, -0.196555f, 0.000000f, 0.980493f, 33.541610f, 70.744042f }, +{ -214.348251f, 20.966747f, 52.198406f, -0.441307f, 0.000000f, 0.897356f, 41.630631f, 70.600318f }, +{ -209.753510f, 20.966751f, 55.606876f, -0.666260f, 0.000000f, 0.745720f, 48.621982f, 68.520264f }, +{ -206.480209f, 20.966751f, 59.833382f, -0.841668f, 0.000000f, 0.539995f, 54.386827f, 64.883844f }, +{ -204.521362f, 20.966751f, 64.563332f, -0.953587f, 0.000000f, 0.301119f, 58.796350f, 60.071068f }, +{ -203.869965f, 20.966747f, 69.482018f, -0.999275f, 0.000000f, 0.038078f, 61.721714f, 54.462006f }, +{ -204.699646f, 20.966745f, 74.975189f, -0.968387f, 0.000000f, -0.249452f, 63.123110f, 47.518791f }, +{ -207.067520f, 20.966745f, 79.783180f, -0.849701f, 0.000000f, -0.527265f, 62.382784f, 40.725728f }, +{ -210.791794f, 20.966745f, 83.766144f, -0.667060f, 0.000001f, -0.745004f, 59.657578f, 34.329638f }, +{ -215.690674f, 20.966745f, 86.784241f, -0.455510f, 0.000001f, -0.890230f, 55.104305f, 28.577339f }, +{ -221.582382f, 20.966745f, 88.697647f, -0.240248f, 0.000001f, -0.970712f, 48.879791f, 23.715652f }, +{ -228.285126f, 20.966745f, 89.366524f, -0.052076f, 0.000001f, -0.998643f, 41.140860f, 19.991366f }, +{ -233.272552f, 20.966745f, 89.153275f, 0.072102f, 0.000001f, -0.997397f, 35.072392f, 18.071967f }, +{ -238.232040f, 20.966745f, 88.499550f, 0.159415f, 0.000001f, -0.987212f, 28.845318f, 16.692474f }, +{ -243.261429f, 20.966745f, 87.384369f, 0.242432f, 0.000001f, -0.970168f, 22.333258f, 15.835392f }, +{ -248.458618f, 20.966745f, 85.786751f, 0.315709f, 0.000001f, -0.948856f, 15.409784f, 15.483151f }, +{ -253.921509f, 20.966745f, 83.685738f, 0.376381f, 0.000001f, -0.926465f, 7.948449f, 15.618150f }, +{ -259.747955f, 20.966745f, 81.060341f, 0.410820f, 0.000001f, -0.911717f, -0.177137f, 16.222895f }, +{ -259.747955f, 20.966743f, 111.264641f, -0.366218f, -0.000001f, 0.930529f, 12.994218f, -19.965132f }, +{ -253.885376f, 20.966743f, 113.571915f, -0.341209f, -0.000001f, 0.939987f, 21.024369f, -20.172966f }, +{ -247.666229f, 20.966742f, 115.459694f, -0.267103f, -0.000001f, 0.963668f, 29.298793f, -19.722705f }, +{ -241.153412f, 20.966742f, 116.927956f, -0.197940f, -0.000001f, 0.980214f, 37.742128f, -18.641769f }, +{ -234.409882f, 20.966742f, 117.976715f, -0.132733f, -0.000001f, 0.991152f, 46.278944f, -16.957608f }, +{ -227.498550f, 20.966742f, 118.605980f, -0.070438f, -0.000001f, 0.997516f, 54.833877f, -14.697672f }, +{ -220.482346f, 20.966742f, 118.815727f, 0.010033f, -0.000001f, 0.999950f, 63.331513f, -11.889380f }, +{ -205.143631f, 20.966742f, 117.432526f, 0.155949f, -0.000001f, 0.987765f, 81.105774f, -3.543295f }, +{ -191.825546f, 20.966743f, 113.455399f, 0.359337f, -0.000001f, 0.933208f, 95.327947f, 7.029410f }, +{ -180.870651f, 20.966740f, 107.143021f, 0.575202f, -0.000001f, 0.818011f, 105.700425f, 19.369491f }, +{ -172.621567f, 20.966740f, 98.754097f, 0.780436f, -0.000001f, 0.625235f, 111.925517f, 33.017553f }, +{ -167.420868f, 20.966738f, 88.547325f, 0.933968f, 0.000000f, 0.357358f, 113.705593f, 47.514262f }, +{ -165.611176f, 20.966738f, 76.781395f, 0.997415f, 0.000000f, 0.071862f, 110.742960f, 62.400282f }, +{ -166.340637f, 20.966747f, 68.696609f, 0.988370f, 0.000000f, -0.152067f, 106.343412f, 71.768634f }, +{ -168.510422f, 20.966751f, 61.101219f, 0.941956f, 0.000000f, -0.335737f, 100.431613f, 79.922540f }, +{ -172.092514f, 20.966747f, 54.065197f, 0.860949f, 0.000000f, -0.508692f, 93.071636f, 86.790398f }, +{ -177.058975f, 20.966749f, 47.658436f, 0.752871f, 0.000000f, -0.658168f, 84.327446f, 92.300634f }, +{ -183.381851f, 20.966749f, 41.950848f, 0.629290f, 0.000000f, -0.777170f, 74.263017f, 96.381691f }, +{ -191.033142f, 20.966749f, 37.012348f, 0.889699f, 0.000000f, -0.456548f, 62.942388f, 98.962011f }, +{ -181.454453f, 20.966749f, 32.298752f, 0.502007f, 0.000000f, 0.864864f, 72.363211f, 108.786445f }, +{ -173.805496f, 20.966751f, 26.319649f, 0.672072f, -0.000002f, 0.740485f, 78.920146f, 119.285570f }, +{ -168.002350f, 20.966755f, 19.235847f, 0.817837f, -0.000002f, 0.575450f, 82.783870f, 130.303345f }, +{ -163.961121f, 20.966755f, 11.208177f, 0.921693f, -0.000001f, 0.387921f, 84.125031f, 141.683643f }, +{ -161.597916f, 20.966753f, 2.397416f, 0.979689f, 0.000000f, 0.200522f, 83.114247f, 153.270422f }, +{ -160.828827f, 20.966753f, -7.035606f, 0.999954f, 0.000000f, 0.009609f, 79.922183f, 164.907587f }, +{ -162.772522f, 20.966755f, -21.426933f, 0.973138f, 0.000000f, -0.230221f, 71.317727f, 181.302347f }, +{ -168.407867f, 20.966755f, -33.734711f, 0.862300f, 0.000000f, -0.506399f, 59.198847f, 193.590963f }, +{ -177.441193f, 20.966757f, -43.721252f, 0.674528f, 0.000000f, -0.738249f, 44.021060f, 201.616710f }, +{ -189.578857f, 20.966757f, -51.148804f, 0.449703f, 0.000000f, -0.893178f, 26.239853f, 205.222777f }, +{ -204.527191f, 20.966757f, -55.779663f, 0.228732f, 0.000000f, -0.973489f, 6.310730f, 204.252446f }, +{ -221.992554f, 20.966764f, -57.376114f, 0.046891f, 0.000000f, -0.998900f, -15.310837f, 198.548949f }, +{ -229.371170f, 20.966764f, -57.068481f, -0.067655f, 0.000000f, -0.997709f, -24.017065f, 194.962735f }, +{ -236.805725f, 20.966764f, -56.173538f, -0.143976f, 0.000000f, -0.989581f, -32.534211f, 190.648469f }, +{ -244.142380f, 20.966764f, -54.733246f, -0.216746f, 0.000000f, -0.976228f, -40.696227f, 185.723508f }, +{ -251.227341f, 20.966764f, -52.789536f, -0.289503f, 0.000000f, -0.957177f, -48.337180f, 180.305151f }, +{ -257.906799f, 20.966764f, -50.384384f, -0.365851f, 0.000000f, -0.930674f, -55.291061f, 174.510773f }, +{ -264.026886f, 20.966764f, -47.559723f, -0.419059f, 0.000000f, -0.907959f, -61.391828f, 168.457698f }, +{ -264.026886f, 20.966753f, -14.334975f, 0.543307f, 0.000000f, 0.839534f, -46.903330f, 128.650867f }, +{ -257.339294f, 20.966755f, -18.662872f, 0.522722f, 0.000000f, 0.852503f, -40.778150f, 136.752450f }, +{ -251.050217f, 20.966759f, -22.109795f, 0.453797f, 0.000000f, 0.891105f, -34.746278f, 143.624746f }, +{ -245.054810f, 20.966759f, -24.717712f, 0.365635f, 0.000000f, 0.930758f, -28.700388f, 149.363761f }, +{ -239.248169f, 20.966759f, -26.528572f, 0.259367f, 0.000000f, 0.965779f, -22.533070f, 154.065507f }, +{ -233.525421f, 20.966759f, -27.584328f, 0.141032f, 0.000000f, 0.990005f, -16.136991f, 157.825968f }, +{ -227.781708f, 20.966759f, -27.926926f, 0.007245f, 0.000000f, 0.999974f, -9.404798f, 160.741125f }, +{ -220.280746f, 20.966759f, -27.192787f, -0.168689f, 0.000000f, 0.985669f, -0.097693f, 163.132535f }, +{ -213.751633f, 20.966759f, -25.074295f, -0.385508f, 0.000000f, 0.922705f, 8.648710f, 163.441542f }, +{ -208.369156f, 20.966755f, -21.697281f, -0.607191f, 0.000000f, 0.794556f, 16.570136f, 161.742676f }, +{ -204.308121f, 20.966755f, -17.187607f, -0.805587f, 0.000000f, 0.592477f, 23.402251f, 158.110519f }, +{ -201.743317f, 20.966753f, -11.671119f, -0.943840f, 0.000000f, 0.330403f, 28.880766f, 152.619616f }, +{ -200.849533f, 20.966753f, -5.273689f, -0.998820f, 0.000000f, 0.048575f, 32.741376f, 145.344564f }, +{ -201.724655f, 20.966753f, 1.288060f, -0.974605f, 0.000000f, -0.223930f, 34.554308f, 137.101256f }, +{ -204.242859f, 20.966751f, 7.031769f, -0.873964f, 0.000000f, -0.485991f, 34.041921f, 129.121548f }, +{ -208.243301f, 20.966755f, 11.810632f, -0.706060f, 0.000000f, -0.708152f, 31.332898f, 121.651460f }, +{ -213.565170f, 20.966755f, 15.477799f, -0.497756f, 0.000000f, -0.867317f, 26.555888f, 114.937053f }, +{ -220.047684f, 20.966755f, 17.886444f, -0.278017f, 0.000003f, -0.960576f, 19.839494f, 109.224379f }, +{ -148.686584f, 20.966726f, 116.550392f, 0.000000f, -0.000001f, 1.000000f, 148.362750f, 22.133128f }, +{ -72.924095f, 20.966726f, 116.550392f, 0.035820f, -0.000001f, 0.999358f, 239.134392f, 55.171292f }, +{ -44.133286f, 20.966728f, 113.442566f, 0.188416f, -0.000001f, 0.982089f, 272.273660f, 71.449770f }, +{ -20.467419f, 20.966740f, 104.692406f, 0.431738f, -0.000001f, 0.901999f, 296.812196f, 92.253517f }, +{ -1.975434f, 20.966738f, 91.159897f, 0.665230f, -0.000001f, 0.746638f, 313.066387f, 116.530840f }, +{ 11.293716f, 20.966730f, 73.705025f, 0.848586f, 0.000000f, 0.529057f, 321.352617f, 143.230008f }, +{ 19.291100f, 20.966740f, 53.187733f, 0.959076f, 0.000000f, 0.283149f, 321.987274f, 171.299414f }, +{ 21.967770f, 20.966734f, 30.467978f, 0.999154f, 0.000000f, 0.041134f, 315.286714f, 199.687280f }, +{ 19.338877f, 20.966743f, 6.999154f, 0.980586f, 0.000000f, -0.196088f, 301.902798f, 226.659158f }, +{ 11.340330f, 20.966745f, -13.645118f, 0.892215f, 0.000000f, -0.451610f, 283.317205f, 247.905264f }, +{ -2.195676f, 20.966759f, -30.821503f, 0.718364f, 0.000000f, -0.695667f, 259.609396f, 262.581703f }, +{ -21.436935f, 20.966757f, -43.886719f, 0.483336f, 0.000000f, -0.875435f, 230.858877f, 269.844599f }, +{ -46.551262f, 20.966757f, -52.197571f, 0.241852f, 0.000000f, -0.970313f, 197.145034f, 268.850158f }, +{ -77.706444f, 20.966757f, -55.110794f, 0.062127f, 0.000000f, -0.998068f, 158.547374f, 258.754495f }, +{ -148.686584f, 20.966757f, -55.110794f, 0.000000f, 0.000000f, -1.000000f, 73.505490f, 227.801797f }, +{ -105.897141f, 20.966738f, 85.087578f, 0.447214f, 0.000001f, -0.894427f, 185.908961f, 78.488406f }, +{ -105.897141f, 20.966759f, -23.647980f, 0.894427f, 0.000000f, 0.447214f, 138.492035f, 208.765369f }, +{ -77.958153f, 20.966759f, -23.647980f, -0.039593f, 0.000000f, 0.999216f, 171.965959f, 220.948887f }, +{ -58.874207f, 20.966755f, -21.368675f, -0.212191f, 0.000000f, 0.977228f, 195.824544f, 226.540074f }, +{ -44.341877f, 20.966753f, -15.146018f, -0.488613f, 0.000000f, 0.872501f, 215.949404f, 225.421851f }, +{ -33.878738f, 20.966745f, -5.902946f, -0.733828f, 0.000000f, 0.679335f, 232.516059f, 218.910365f }, +{ -27.002363f, 20.966743f, 5.437653f, -0.895536f, 0.000000f, 0.444989f, 245.700045f, 208.321724f }, +{ -23.230320f, 20.966747f, 17.952866f, -0.974747f, -0.000001f, 0.223313f, 255.676941f, 194.972041f }, +{ -22.080179f, 20.966734f, 30.719679f, -0.999602f, 0.000000f, 0.028209f, 262.622269f, 180.177478f }, +{ -23.442402f, 20.966742f, 44.972439f, -0.985715f, 0.000000f, -0.168424f, 267.205431f, 162.507187f }, +{ -27.692215f, 20.966743f, 57.903660f, -0.917976f, 0.000000f, -0.396636f, 267.752663f, 145.160943f }, +{ -35.074326f, 20.966740f, 68.947144f, -0.770297f, 0.000000f, -0.637685f, 263.723906f, 128.710501f }, +{ -45.833443f, 20.966738f, 77.536499f, -0.541864f, 0.000001f, -0.840466f, 254.578922f, 113.727730f }, +{ -60.214287f, 20.966738f, 83.105423f, -0.278852f, 0.000001f, -0.960334f, 239.777591f, 100.784424f }, +{ -78.461555f, 20.966738f, 85.087578f, -0.072088f, 0.000001f, -0.997398f, 218.779751f, 90.452398f }, +{ 53.459190f, 21.106728f, -63.834198f, 0.000000f, 0.000000f, -1.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106720f, 19.696632f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106720f, 19.696632f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106718f, 37.767292f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106718f, 37.767292f, -0.447214f, 0.000000f, 0.894427f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106716f, 52.887684f, -0.998610f, 0.000000f, 0.052712f, 0.000000f, 255.000000f }, +{ 54.761124f, 21.106716f, 61.040321f, -0.964760f, 0.000000f, 0.263130f, 0.000000f, 255.000000f }, +{ 58.744659f, 21.106709f, 68.629570f, -0.832175f, -0.000001f, 0.554513f, 0.000000f, 255.000000f }, +{ 65.526382f, 21.106707f, 75.245590f, -0.629247f, -0.000001f, 0.777205f, 0.000000f, 255.000000f }, +{ 75.222885f, 21.106714f, 80.478653f, -0.406003f, -0.000001f, 0.913872f, 0.000000f, 255.000000f }, +{ 87.950760f, 21.106714f, 83.918983f, -0.200640f, -0.000002f, 0.979665f, 0.000000f, 255.000000f }, +{ 103.826599f, 21.106714f, 85.156822f, -0.046194f, -0.000002f, 0.998932f, 0.000000f, 255.000000f }, +{ 107.486267f, 21.106707f, 85.094505f, 0.027667f, -0.000002f, 0.999617f, 0.000000f, 255.000000f }, +{ 111.371353f, 21.106707f, 84.904137f, 0.059760f, -0.000002f, 0.998213f, 0.000000f, 255.000000f }, +{ 115.334160f, 21.106707f, 84.580589f, 0.093534f, -0.000002f, 0.995616f, 0.000000f, 255.000000f }, +{ 119.227013f, 21.106707f, 84.118752f, 0.132736f, -0.000002f, 0.991151f, 0.000000f, 255.000000f }, +{ 122.902229f, 21.106707f, 83.513496f, 0.182424f, -0.000002f, 0.983220f, 0.000000f, 255.000000f }, +{ 126.212128f, 21.106707f, 82.759697f, 0.675942f, -0.000001f, 0.736955f, 0.000000f, 255.000000f }, +{ 114.179916f, 21.106716f, 65.426567f, 0.550632f, 0.000001f, -0.834748f, 0.000000f, 255.000000f }, +{ 112.235428f, 21.106709f, 65.933655f, -0.237575f, 0.000002f, -0.971369f, 0.000000f, 255.000000f }, +{ 110.283180f, 21.106709f, 66.348541f, -0.191361f, 0.000002f, -0.981520f, 0.000000f, 255.000000f }, +{ 108.268738f, 21.106709f, 66.671227f, -0.141331f, 0.000002f, -0.989962f, 0.000000f, 255.000000f }, +{ 106.137703f, 21.106709f, 66.901718f, -0.091701f, 0.000002f, -0.995787f, 0.000000f, 255.000000f }, +{ 103.835670f, 21.106709f, 67.040016f, -0.046066f, 0.000002f, -0.998938f, 0.000000f, 255.000000f }, +{ 101.308228f, 21.106709f, 67.086113f, 0.018743f, 0.000002f, -0.999824f, 0.000000f, 255.000000f }, +{ 95.838806f, 21.106709f, 66.577324f, 0.159913f, 0.000002f, -0.987131f, 0.000000f, 255.000000f }, +{ 91.224388f, 21.106716f, 65.167046f, 0.363788f, 0.000001f, -0.931482f, 0.000000f, 255.000000f }, +{ 87.527145f, 21.106716f, 63.029400f, 0.572373f, 0.000000f, -0.819993f, 0.000000f, 255.000000f }, +{ 84.809280f, 21.106716f, 60.338608f, 0.768792f, 0.000000f, -0.639499f, 0.000000f, 255.000000f }, +{ 83.132957f, 21.106716f, 57.268780f, 0.924396f, 0.000000f, -0.381433f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106716f, 53.994068f, 0.993341f, 0.000000f, -0.115210f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106718f, 37.767292f, 0.894427f, 0.000000f, 0.447214f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106718f, 37.767292f, 0.000000f, 0.000000f, 1.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106720f, 19.696632f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106720f, 19.696632f, 0.000000f, 0.000010f, -1.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106728f, -63.834198f, 0.000000f, 0.000000f, -1.000000f, 0.000000f, 255.000000f }, +{ 109.261765f, 21.106724f, -33.040283f, -0.468379f, 0.000000f, -0.883527f, 0.000000f, 255.000000f }, +{ 158.509918f, 21.106720f, 10.661286f, -0.933984f, 0.000000f, 0.357316f, 0.000000f, 255.000000f }, +{ 110.660858f, 21.106716f, 56.206806f, -0.950931f, 0.000000f, -0.309402f, 0.000000f, 255.000000f }, +{ 147.037323f, 21.106716f, 56.206806f, 0.264544f, 0.000000f, 0.964374f, 0.000000f, 255.000000f }, +{ 175.299042f, 21.106712f, 25.597252f, 0.337904f, -0.000006f, 0.941181f, 0.000000f, 255.000000f }, +{ 203.001129f, 21.106716f, 56.206806f, -0.534949f, -0.000002f, 0.844884f, 0.000000f, 255.000000f }, +{ 237.139038f, 21.106712f, 56.206806f, 0.473674f, 0.000000f, 0.880700f, 0.000000f, 255.000000f }, +{ 189.569809f, 21.106720f, 11.767655f, 0.942807f, 0.000000f, -0.333339f, 0.000000f, 255.000000f }, +{ 239.097778f, 21.106724f, -33.040283f, 0.940870f, 0.000000f, 0.338768f, 0.000000f, 255.000000f }, +{ 202.161682f, 21.106724f, -33.040283f, -0.259495f, 0.000000f, -0.965744f, 0.000000f, 255.000000f }, +{ 173.620132f, 21.106722f, -3.168342f, -0.333727f, 0.000000f, -0.942670f, 0.000000f, 255.000000f }, +{ 143.679504f, 21.106724f, -33.040283f, 0.504764f, 0.000000f, -0.863257f, 0.000000f, 255.000000f }, +{ 246.695496f, 21.106710f, 44.635105f, -0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 246.695496f, 21.106709f, 54.095203f, -0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 243.335144f, 21.106709f, 54.095203f, -0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 243.335144f, 21.106712f, 56.104115f, -0.894427f, 0.000000f, 0.447214f, 0.000000f, 255.000000f }, +{ 252.174316f, 21.106712f, 56.104115f, 0.447214f, 0.000000f, 0.894427f, 0.000000f, 255.000000f }, +{ 252.174316f, 21.106709f, 54.095203f, 0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 248.813965f, 21.106709f, 54.095203f, 0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 248.813965f, 21.106710f, 44.635105f, 0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 253.836212f, 21.106710f, 44.635105f, -0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 253.836212f, 21.106712f, 56.341526f, -0.877850f, 0.000000f, 0.478935f, 0.000000f, 255.000000f }, +{ 258.931549f, 21.106709f, 51.191425f, 0.319282f, 0.000000f, 0.947660f, 0.000000f, 255.000000f }, +{ 264.026886f, 21.106712f, 56.341526f, -0.287199f, 0.000000f, 0.957871f, 0.000000f, 255.000000f }, +{ 264.026886f, 21.106710f, 44.635105f, 0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 261.908356f, 21.106710f, 44.635105f, -0.447214f, 0.000000f, -0.894427f, 0.000000f, 255.000000f }, +{ 261.908356f, 21.106709f, 51.721058f, -0.879075f, 0.000000f, -0.476683f, 0.000000f, 255.000000f }, +{ 258.931549f, 21.106709f, 48.634647f, 0.326650f, 0.000000f, -0.945145f, 0.000000f, 255.000000f }, +{ 255.954681f, 21.106709f, 51.721058f, -0.301802f, 0.000000f, -0.953371f, 0.000000f, 255.000000f }, +{ 255.954681f, 21.106710f, 44.635105f, 0.894427f, 0.000000f, -0.447214f, 0.000000f, 255.000000f }, +{ 53.398365f, 21.091320f, -118.046234f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 53.398365f, 21.091311f, -89.641495f, -0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 58.399651f, 21.091311f, -89.641495f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 58.399651f, 21.091320f, -118.046234f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 64.683319f, 21.091320f, -118.046234f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 64.683319f, 21.091311f, -89.641495f, -0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -89.641495f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -92.719193f, 0.887750f, -0.000001f, 0.460327f, 0.000000f, 255.000000f }, +{ 71.361206f, 21.091311f, -90.693512f, -0.656342f, -0.000001f, 0.754463f, 0.000000f, 255.000000f }, +{ 75.070610f, 21.091311f, -89.192642f, -0.164366f, -0.000002f, 0.986400f, 0.000000f, 255.000000f }, +{ 78.221947f, 21.091311f, -90.116440f, 0.467430f, -0.000002f, 0.884030f, 0.000000f, 255.000000f }, +{ 80.447113f, 21.091311f, -92.906815f, 0.854905f, -0.000001f, 0.518785f, 0.000000f, 255.000000f }, +{ 81.069901f, 21.091311f, -95.010880f, 0.975826f, 0.000000f, 0.218549f, 0.000000f, 255.000000f }, +{ 81.290161f, 21.091311f, -97.592255f, 0.998390f, 0.000000f, 0.056724f, 0.000000f, 255.000000f }, +{ 81.290161f, 21.091320f, -118.046234f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 76.288872f, 21.091320f, -118.046234f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 76.288872f, 21.091311f, -97.720490f, -0.999299f, 0.000000f, -0.037426f, 0.000000f, 255.000000f }, +{ 76.046646f, 21.091311f, -95.573685f, -0.953521f, 0.000001f, -0.301328f, 0.000000f, 255.000000f }, +{ 74.507790f, 21.091311f, -93.751633f, -0.528723f, 0.000002f, -0.848795f, 0.000000f, 255.000000f }, +{ 72.154381f, 21.091311f, -93.999207f, 0.303533f, 0.000002f, -0.952821f, 0.000000f, 255.000000f }, +{ 70.869621f, 21.091311f, -95.136734f, 0.730358f, 0.000001f, -0.683065f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -97.015182f, 0.929606f, 0.000001f, -0.368555f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091320f, -118.046234f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 116.042702f, 21.091320f, -111.377853f, -0.239564f, -0.000003f, 0.970881f, 0.000000f, 255.000000f }, +{ 116.042702f, 21.091320f, -116.315018f, 0.945756f, 0.000001f, -0.324877f, 0.000000f, 255.000000f }, +{ 112.247803f, 21.091320f, -118.552063f, 0.339296f, 0.000002f, -0.940680f, 0.000000f, 255.000000f }, +{ 107.574234f, 21.091320f, -118.394440f, -0.247366f, 0.000001f, -0.968922f, 0.000000f, 255.000000f }, +{ 103.539482f, 21.091320f, -115.040665f, -0.746247f, 0.000001f, -0.665669f, 0.000000f, 255.000000f }, +{ 102.209610f, 21.091320f, -112.118790f, -0.936927f, 0.000000f, -0.349526f, 0.000000f, 255.000000f }, +{ 101.385559f, 21.091312f, -108.374054f, -0.986407f, 0.000000f, -0.164321f, 0.000000f, 255.000000f }, +{ 101.102959f, 21.091311f, -103.811798f, -0.999732f, 0.000000f, -0.023155f, 0.000000f, 255.000000f }, +{ 101.339844f, 21.091307f, -99.454666f, -0.995145f, 0.000000f, 0.098417f, 0.000000f, 255.000000f }, +{ 102.036247f, 21.091311f, -95.777908f, -0.969592f, -0.000001f, 0.244727f, 0.000000f, 255.000000f }, +{ 103.170799f, 21.091311f, -92.831406f, -0.899584f, -0.000001f, 0.436747f, 0.000000f, 255.000000f }, +{ 104.722122f, 21.091311f, -90.665024f, -0.716919f, -0.000001f, 0.697157f, 0.000000f, 255.000000f }, +{ 107.933678f, 21.091311f, -88.927628f, -0.281539f, -0.000002f, 0.959550f, 0.000000f, 255.000000f }, +{ 111.632736f, 21.091311f, -89.470505f, 0.315299f, -0.000002f, 0.948992f, 0.000000f, 255.000000f }, +{ 113.549179f, 21.091311f, -91.009354f, 0.701500f, -0.000002f, 0.712669f, 0.000000f, 255.000000f }, +{ 114.952675f, 21.091311f, -93.103912f, 0.890786f, -0.000001f, 0.454424f, 0.000000f, 255.000000f }, +{ 116.387047f, 21.091307f, -99.154861f, 0.985821f, 0.000000f, 0.167802f, 0.000000f, 255.000000f }, +{ 116.619774f, 21.091309f, -104.965942f, 0.908369f, 0.000001f, -0.418169f, 0.000000f, 255.000000f }, +{ 106.104248f, 21.091312f, -104.965942f, 0.465868f, 0.000001f, -0.884854f, 0.000000f, 255.000000f }, +{ 106.676575f, 21.091320f, -110.009979f, 0.971167f, 0.000000f, 0.238399f, 0.000000f, 255.000000f }, +{ 108.374535f, 21.091320f, -113.130447f, 0.745484f, -0.000001f, 0.666523f, 0.000000f, 255.000000f }, +{ 111.169655f, 21.091320f, -114.199097f, 0.156933f, -0.000001f, 0.987609f, 0.000000f, 255.000000f }, +{ 113.774490f, 21.091320f, -113.485764f, -0.413582f, -0.000002f, 0.910467f, 0.000000f, 255.000000f }, +{ 106.040123f, 21.091307f, -101.247040f, 0.916229f, -0.000001f, 0.400654f, 0.000000f, 255.000000f }, +{ 111.618484f, 21.091307f, -101.247040f, -0.458820f, -0.000001f, 0.888529f, 0.000000f, 255.000000f }, +{ 111.312141f, 21.091311f, -96.746841f, -0.987291f, 0.000000f, -0.158925f, 0.000000f, 255.000000f }, +{ 110.364601f, 21.091311f, -94.098953f, -0.833881f, 0.000001f, -0.551945f, 0.000000f, 255.000000f }, +{ 108.733131f, 21.091311f, -93.232162f, -0.164167f, 0.000002f, -0.986433f, 0.000000f, 255.000000f }, +{ 107.208519f, 21.091311f, -94.113205f, 0.689773f, 0.000001f, -0.724025f, 0.000000f, 255.000000f }, +{ 106.325096f, 21.091311f, -96.775330f, 0.972507f, 0.000000f, -0.232875f, 0.000000f, 255.000000f }, +{ 122.262253f, 21.091320f, -118.046234f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 122.262253f, 21.091311f, -89.641495f, -0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 127.263535f, 21.091311f, -89.641495f, 0.444200f, -0.000001f, 0.895928f, 0.000000f, 255.000000f }, +{ 127.391785f, 21.091311f, -97.335770f, 0.953952f, -0.000001f, 0.299959f, 0.000000f, 255.000000f }, +{ 128.306671f, 21.091311f, -94.372635f, -0.949849f, -0.000001f, 0.312709f, 0.000000f, 255.000000f }, +{ 129.111130f, 21.091311f, -92.203873f, -0.922966f, -0.000001f, 0.384882f, 0.000000f, 255.000000f }, +{ 129.876404f, 21.091311f, -90.715469f, -0.819365f, -0.000002f, 0.573272f, 0.000000f, 255.000000f }, +{ 131.574371f, 21.091311f, -89.323868f, -0.451781f, -0.000002f, 0.892129f, 0.000000f, 255.000000f }, +{ 133.556717f, 21.091311f, -89.280518f, 0.124905f, -0.000001f, 0.992169f, 0.000000f, 255.000000f }, +{ 135.214310f, 21.091311f, -90.026199f, 0.720568f, -0.000001f, 0.693384f, 0.000000f, 255.000000f }, +{ 134.829590f, 21.091311f, -95.155716f, 0.837365f, 0.000001f, -0.546645f, 0.000000f, 255.000000f }, +{ 132.649551f, 21.091311f, -94.450424f, -0.087364f, 0.000002f, -0.996176f, 0.000000f, 255.000000f }, +{ 130.914764f, 21.091311f, -95.135239f, 0.525644f, 0.000002f, -0.850705f, 0.000000f, 255.000000f }, +{ 129.543335f, 21.091311f, -96.915436f, 0.842037f, 0.000001f, -0.539420f, 0.000000f, 255.000000f }, +{ 128.513855f, 21.091307f, -99.379562f, 0.939937f, 0.000001f, -0.341349f, 0.000000f, 255.000000f }, +{ 127.804985f, 21.091307f, -102.116196f, 0.975653f, 0.000001f, -0.219322f, 0.000000f, 255.000000f }, +{ 127.395340f, 21.091309f, -104.713913f, 0.994216f, 0.000000f, -0.107397f, 0.000000f, 255.000000f }, +{ 127.263535f, 21.091320f, -118.046234f, 0.890868f, 0.000001f, -0.454263f, 0.000000f, 255.000000f }, +{ 155.668289f, 21.091312f, -112.788467f, -0.207596f, -0.000003f, 0.978215f, 0.000000f, 255.000000f }, +{ 155.668289f, 21.091312f, -116.571503f, 0.958465f, 0.000000f, -0.285210f, 0.000000f, 255.000000f }, +{ 154.127060f, 21.091320f, -117.804016f, 0.558773f, 0.000001f, -0.829321f, 0.000000f, 255.000000f }, +{ 152.305023f, 21.091320f, -118.637558f, 0.271646f, 0.000002f, -0.962397f, 0.000000f, 255.000000f }, +{ 150.903000f, 21.091320f, -118.586197f, -0.192636f, 0.000003f, -0.981270f, 0.000000f, 255.000000f }, +{ 149.472794f, 21.091320f, -117.781738f, -0.623712f, 0.000001f, -0.781654f, 0.000000f, 255.000000f }, +{ 148.448669f, 21.091320f, -116.186478f, -0.885465f, 0.000001f, -0.464706f, 0.000000f, 255.000000f }, +{ 148.102249f, 21.091320f, -115.096756f, -0.673915f, 0.000002f, -0.738809f, 0.000000f, 255.000000f }, +{ 146.276031f, 21.091320f, -117.172318f, 0.651081f, 0.000002f, -0.759008f, 0.000000f, 255.000000f }, +{ 142.652115f, 21.091320f, -118.815659f, 0.173318f, 0.000003f, -0.984866f, 0.000000f, 255.000000f }, +{ 139.866501f, 21.091320f, -117.808762f, -0.507992f, 0.000002f, -0.861362f, 0.000000f, 255.000000f }, +{ 137.850311f, 21.091320f, -115.206009f, -0.871837f, 0.000001f, -0.489796f, 0.000000f, 255.000000f }, +{ 137.073761f, 21.091320f, -111.634323f, -0.998311f, 0.000000f, -0.058104f, 0.000000f, 255.000000f }, +{ 138.144791f, 21.091309f, -107.571091f, -0.909053f, -0.000001f, 0.416680f, 0.000000f, 255.000000f }, +{ 141.623840f, 21.091307f, -104.049286f, -0.664570f, -0.000001f, 0.747226f, 0.000000f, 255.000000f }, +{ 144.391052f, 21.091307f, -102.166382f, -0.548261f, -0.000001f, 0.836307f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091307f, -100.028778f, -0.766243f, -0.000001f, 0.642551f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091311f, -97.335770f, -0.996405f, 0.000000f, -0.084715f, 0.000000f, 255.000000f }, +{ 147.180527f, 21.091311f, -94.538589f, -0.876729f, 0.000001f, -0.480984f, 0.000000f, 255.000000f }, +{ 145.869064f, 21.091311f, -93.718689f, -0.363965f, 0.000001f, -0.931413f, 0.000000f, 255.000000f }, +{ 143.898575f, 21.091311f, -93.732040f, 0.141328f, 0.000002f, -0.989963f, 0.000000f, 255.000000f }, +{ 141.682312f, 21.091311f, -94.706894f, 0.547231f, 0.000002f, -0.836982f, 0.000000f, 255.000000f }, +{ 137.779068f, 21.091307f, -98.297562f, -0.401856f, 0.000002f, -0.915703f, 0.000000f, 255.000000f }, +{ 137.779068f, 21.091311f, -92.526840f, -0.955079f, -0.000001f, 0.296350f, 0.000000f, 255.000000f }, +{ 141.658264f, 21.091311f, -89.665527f, -0.497538f, -0.000001f, 0.867442f, 0.000000f, 255.000000f }, +{ 144.054428f, 21.091311f, -88.951309f, -0.179589f, -0.000002f, 0.983742f, 0.000000f, 255.000000f }, +{ 147.152328f, 21.091311f, -89.072128f, 0.177231f, -0.000003f, 0.984169f, 0.000000f, 255.000000f }, +{ 150.474655f, 21.091311f, -90.715469f, 0.598228f, -0.000002f, 0.801326f, 0.000000f, 255.000000f }, +{ 152.600082f, 21.091311f, -94.111420f, 0.914330f, -0.000001f, 0.404969f, 0.000000f, 255.000000f }, +{ 152.911179f, 21.091311f, -96.502228f, 0.996242f, 0.000000f, 0.086610f, 0.000000f, 255.000000f }, +{ 152.932556f, 21.091312f, -113.100754f, 0.997125f, 0.000000f, 0.075777f, 0.000000f, 255.000000f }, +{ 153.103531f, 21.091312f, -113.846436f, 0.884948f, -0.000001f, 0.465690f, 0.000000f, 255.000000f }, +{ 153.680603f, 21.091312f, -114.199097f, 0.253386f, -0.000001f, 0.967365f, 0.000000f, 255.000000f }, +{ 154.124680f, 21.091312f, -114.032852f, -0.430647f, -0.000002f, 0.902520f, 0.000000f, 255.000000f }, +{ 154.796753f, 21.091312f, -113.553146f, -0.607827f, -0.000002f, 0.794070f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091312f, -110.800781f, -0.953798f, 0.000000f, 0.300449f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091307f, -103.491211f, -0.866611f, 0.000001f, -0.498984f, 0.000000f, 255.000000f }, +{ 146.048050f, 21.091309f, -104.727585f, 0.580141f, 0.000001f, -0.814516f, 0.000000f, 255.000000f }, +{ 144.556686f, 21.091309f, -105.944351f, 0.665820f, 0.000002f, -0.746113f, 0.000000f, 255.000000f }, +{ 143.421539f, 21.091309f, -107.154007f, 0.767879f, 0.000002f, -0.640594f, 0.000000f, 255.000000f }, +{ 142.628372f, 21.091309f, -108.369003f, 0.891623f, 0.013556f, -0.452576f, 0.000000f, 255.000000f }, +{ 142.162918f, 21.091312f, -109.601822f, 0.949579f, 0.009083f, -0.313397f, 0.000000f, 255.000000f }, +{ 142.010925f, 21.091312f, -110.864899f, 0.999304f, 0.016713f, 0.033337f, 0.000000f, 255.000000f }, +{ 142.329147f, 21.091312f, -112.550995f, 0.955846f, 0.011386f, 0.293649f, 0.000000f, 255.000000f }, +{ 143.188812f, 21.091320f, -113.667130f, 0.656317f, -0.000002f, 0.754485f, 0.000000f, 255.000000f }, +{ 144.447449f, 21.091320f, -114.070847f, 0.112970f, -0.000003f, 0.993598f, 0.000000f, 255.000000f }, +{ 145.715591f, 21.091312f, -113.693268f, -0.427813f, -0.000002f, 0.903867f, 0.000000f, 255.000000f }, +{ 146.898224f, 21.091312f, -112.588989f, -0.738315f, -0.000001f, 0.674456f, 0.000000f, 255.000000f }, +{ 147.430771f, 21.091312f, -111.777710f, -0.858087f, -0.000001f, 0.513505f, 0.000000f, 255.000000f }, +{ 173.749878f, 21.091312f, -112.467880f, -0.011390f, -0.000002f, 0.999935f, 0.000000f, 255.000000f }, +{ 173.749878f, 21.091312f, -117.276810f, 0.941545f, 0.000001f, -0.336887f, 0.000000f, 255.000000f }, +{ 172.085159f, 21.091312f, -118.160233f, 0.381529f, 0.000002f, -0.924357f, 0.000000f, 255.000000f }, +{ 168.812698f, 21.091312f, -118.815659f, 0.073515f, 0.000003f, -0.997294f, 0.000000f, 255.000000f }, +{ 166.009262f, 21.091312f, -118.315475f, -0.288270f, 0.000003f, -0.957549f, 0.000000f, 255.000000f }, +{ 163.547806f, 21.091312f, -116.887344f, -0.587254f, 0.000002f, -0.809402f, 0.000000f, 255.000000f }, +{ 161.503128f, 21.091312f, -114.639908f, -0.793964f, 0.000002f, -0.607965f, 0.000000f, 255.000000f }, +{ 159.950012f, 21.091312f, -111.681839f, -0.916096f, 0.000001f, -0.400960f, 0.000000f, 255.000000f }, +{ 158.963303f, 21.091309f, -108.121750f, -0.978307f, 0.000000f, -0.207162f, 0.000000f, 255.000000f }, +{ 158.617767f, 21.091307f, -104.068283f, -0.999894f, 0.000000f, -0.014533f, 0.000000f, 255.000000f }, +{ 159.531387f, 21.091311f, -96.903564f, -0.960752f, -0.000001f, 0.277410f, 0.000000f, 255.000000f }, +{ 163.822617f, 21.091311f, -90.542206f, -0.686978f, -0.000001f, 0.726678f, 0.000000f, 255.000000f }, +{ 169.115997f, 21.091311f, -88.872055f, -0.125351f, -0.000002f, 0.992112f, 0.000000f, 255.000000f }, +{ 173.301041f, 21.091311f, -89.897964f, 0.605053f, -0.000002f, 0.796185f, 0.000000f, 255.000000f }, +{ 173.301041f, 21.091311f, -95.027481f, 0.869424f, 0.000001f, -0.494066f, 0.000000f, 255.000000f }, +{ 169.582138f, 21.091311f, -93.616867f, -0.117972f, 0.000003f, -0.993017f, 0.000000f, 255.000000f }, +{ 166.473557f, 21.091311f, -94.882629f, 0.569661f, 0.000002f, -0.821880f, 0.000000f, 255.000000f }, +{ 164.462112f, 21.091307f, -98.442429f, 0.926161f, 0.000000f, -0.377127f, 0.000000f, 255.000000f }, +{ 163.747299f, 21.091307f, -103.940048f, 0.999259f, 0.000000f, -0.038502f, 0.000000f, 255.000000f }, +{ 164.523849f, 21.091312f, -109.302292f, 0.960848f, -0.000001f, 0.277074f, 0.000000f, 255.000000f }, +{ 166.711029f, 21.091312f, -112.812210f, 0.688926f, -0.000002f, 0.724832f, 0.000000f, 255.000000f }, +{ 171.313354f, 21.091312f, -113.911743f, -0.016062f, -0.000002f, 0.999871f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091312f, -113.301422f, 0.166049f, -0.000002f, 0.986117f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091312f, -117.725632f, 0.929230f, 0.000001f, -0.369503f, 0.000000f, 255.000000f }, +{ 186.637802f, 21.091312f, -118.378708f, 0.302607f, 0.000003f, -0.953115f, 0.000000f, 255.000000f }, +{ 184.602036f, 21.091312f, -118.792801f, 0.114406f, 0.000003f, -0.993434f, 0.000000f, 255.000000f }, +{ 182.419891f, 21.091312f, -118.666061f, -0.154137f, 0.000002f, -0.988049f, 0.000000f, 255.000000f }, +{ 181.128311f, 21.091312f, -118.195847f, -0.440071f, 0.000002f, -0.897963f, 0.000000f, 255.000000f }, +{ 180.089645f, 21.091312f, -117.372986f, -0.704223f, 0.000001f, -0.709979f, 0.000000f, 255.000000f }, +{ 179.323486f, 21.091312f, -116.165421f, -0.890730f, 0.000001f, -0.454533f, 0.000000f, 255.000000f }, +{ 178.849426f, 21.091312f, -114.541061f, -0.976876f, 0.000000f, -0.213806f, 0.000000f, 255.000000f }, +{ 178.687042f, 21.091312f, -112.467880f, -0.998642f, 0.000000f, -0.052093f, 0.000000f, 255.000000f }, +{ 178.687042f, 21.091311f, -94.001587f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 175.416977f, 21.091311f, -94.001587f, -0.498416f, 0.000001f, -0.866938f, 0.000000f, 255.000000f }, +{ 178.200211f, 21.091311f, -89.945450f, -0.824150f, -0.000001f, 0.566372f, 0.000000f, 255.000000f }, +{ 180.755478f, 21.091311f, -86.238419f, -0.830310f, -0.000001f, 0.557302f, 0.000000f, 255.000000f }, +{ 183.239502f, 21.091309f, -82.331909f, -0.631328f, -0.000001f, 0.775516f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091309f, -82.331909f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091311f, -89.641495f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091311f, -89.641495f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091311f, -94.001587f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091311f, -94.001587f, 0.448748f, 0.000001f, -0.893658f, 0.000000f, 255.000000f }, +{ 183.847443f, 21.091312f, -112.446503f, 0.993879f, -0.002630f, 0.110439f, 0.000000f, 255.000000f }, +{ 184.081055f, 21.091312f, -113.181198f, 0.839241f, 0.017509f, 0.543478f, 0.000000f, 255.000000f }, +{ 184.972198f, 21.091312f, -113.977341f, 0.558370f, 0.001114f, 0.829591f, 0.000000f, 255.000000f }, +{ 186.488205f, 21.091312f, -113.985367f, -0.111941f, -0.000003f, 0.993715f, 0.000000f, 255.000000f }, +{ 192.280289f, 21.091312f, -118.046234f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 192.280289f, 21.091311f, -89.641495f, -0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 197.281570f, 21.091311f, -89.641495f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 197.281570f, 21.091312f, -118.046234f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 209.400085f, 21.091312f, -118.687424f, -0.387639f, 0.000002f, -0.921811f, 0.000000f, 255.000000f }, +{ 200.872238f, 21.091311f, -89.641495f, -0.975084f, 0.000000f, 0.221837f, 0.000000f, 255.000000f }, +{ 205.873535f, 21.091311f, -89.641495f, 0.395561f, -0.000001f, 0.918440f, 0.000000f, 255.000000f }, +{ 210.041275f, 21.091309f, -105.863617f, 0.791121f, -0.000001f, 0.611659f, 0.000000f, 255.000000f }, +{ 210.169510f, 21.091309f, -105.863617f, -0.395561f, -0.000001f, 0.918440f, 0.000000f, 255.000000f }, +{ 214.337250f, 21.091311f, -89.641495f, -0.791121f, -0.000001f, 0.611659f, 0.000000f, 255.000000f }, +{ 219.338531f, 21.091311f, -89.641495f, 0.487542f, -0.000001f, 0.873100f, 0.000000f, 255.000000f }, +{ 210.810699f, 21.091312f, -118.687424f, 0.775278f, 0.000002f, -0.631621f, 0.000000f, 255.000000f }, +{ 196.095139f, 9.401914f, -83.842834f, 0.586264f, 0.000000f, -0.810120f, 0.000000f, 255.000000f }, +{ 197.530334f, 9.401917f, -82.099869f, 0.987392f, 0.000000f, -0.158291f, 0.000000f, 255.000000f }, +{ 197.312714f, 9.401917f, -79.852554f, 0.810120f, 0.000000f, 0.586264f, 0.000000f, 255.000000f }, +{ 195.569748f, 9.401917f, -78.417358f, 0.158291f, 0.000000f, 0.987392f, 0.000000f, 255.000000f }, +{ 193.322433f, 9.401917f, -78.634979f, -0.586264f, 0.000000f, 0.810120f, 0.000000f, 255.000000f }, +{ 191.887238f, 9.401917f, -80.377945f, -0.987392f, 0.000000f, 0.158291f, 0.000000f, 255.000000f }, +{ 192.104858f, 9.401917f, -82.625259f, -0.810120f, 0.000000f, -0.586264f, 0.000000f, 255.000000f }, +{ 193.847824f, 9.401914f, -84.060455f, -0.158291f, 0.000000f, -0.987392f, 0.000000f, 255.000000f }, +{ 196.095139f, 21.005835f, -83.842834f, 0.344805f, 0.000000f, -0.938674f, 0.000000f, 255.000000f }, +{ 197.530334f, 21.005833f, -82.099869f, 0.907558f, 0.000000f, -0.419928f, 0.000000f, 255.000000f }, +{ 197.312714f, 21.005833f, -79.852554f, 0.938674f, 0.000000f, 0.344805f, 0.000000f, 255.000000f }, +{ 195.569748f, 21.005836f, -78.417358f, 0.419928f, 0.000000f, 0.907558f, 0.000000f, 255.000000f }, +{ 193.322433f, 21.005836f, -78.634979f, -0.344805f, 0.000000f, 0.938674f, 0.000000f, 255.000000f }, +{ 191.887238f, 21.005833f, -80.377945f, -0.907558f, 0.000000f, 0.419928f, 0.000000f, 255.000000f }, +{ 192.104858f, 21.005835f, -82.625259f, -0.938674f, 0.000000f, -0.344805f, 0.000000f, 255.000000f }, +{ 193.847824f, 21.005835f, -84.060455f, -0.419928f, 0.000000f, -0.907558f, 0.000000f, 255.000000f }, +{ 57.212021f, 9.401914f, -83.842834f, 0.586264f, 0.000000f, -0.810120f, 0.000000f, 255.000000f }, +{ 58.647217f, 9.401917f, -82.099869f, 0.987392f, 0.000000f, -0.158291f, 0.000000f, 255.000000f }, +{ 58.429596f, 9.401917f, -79.852554f, 0.810120f, 0.000000f, 0.586264f, 0.000000f, 255.000000f }, +{ 56.686630f, 9.401917f, -78.417358f, 0.158291f, 0.000000f, 0.987392f, 0.000000f, 255.000000f }, +{ 54.439316f, 9.401917f, -78.634979f, -0.586264f, 0.000000f, 0.810120f, 0.000000f, 255.000000f }, +{ 53.004120f, 9.401917f, -80.377945f, -0.987392f, 0.000000f, 0.158291f, 0.000000f, 255.000000f }, +{ 53.221741f, 9.401917f, -82.625259f, -0.810120f, 0.000000f, -0.586264f, 0.000000f, 255.000000f }, +{ 54.964706f, 9.401914f, -84.060455f, -0.158291f, 0.000000f, -0.987392f, 0.000000f, 255.000000f }, +{ 57.212021f, 21.005835f, -83.842834f, 0.344805f, 0.000000f, -0.938674f, 0.000000f, 255.000000f }, +{ 58.647217f, 21.005833f, -82.099869f, 0.907558f, 0.000000f, -0.419928f, 0.000000f, 255.000000f }, +{ 58.429596f, 21.005833f, -79.852554f, 0.938674f, 0.000000f, 0.344805f, 0.000000f, 255.000000f }, +{ 56.686630f, 21.005836f, -78.417358f, 0.419928f, 0.000000f, 0.907558f, 0.000000f, 255.000000f }, +{ 54.439316f, 21.005836f, -78.634979f, -0.344805f, 0.000000f, 0.938674f, 0.000000f, 255.000000f }, +{ 53.004120f, 21.005833f, -80.377945f, -0.907558f, 0.000000f, 0.419928f, 0.000000f, 255.000000f }, +{ 53.221741f, 21.005835f, -82.625259f, -0.938674f, 0.000000f, -0.344805f, 0.000000f, 255.000000f }, +{ 54.964706f, 21.005835f, -84.060455f, -0.419928f, 0.000000f, -0.907558f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484123f, -113.301437f, 0.869996f, -0.000001f, 0.493059f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484123f, -117.725662f, 0.688899f, 0.000002f, -0.724858f, 0.000000f, 255.000000f }, +{ 95.979660f, 9.484123f, -118.792831f, 0.103299f, 0.000002f, -0.994650f, 0.000000f, 255.000000f }, +{ 92.633392f, 9.484123f, -118.666077f, -0.344449f, 0.000001f, -0.938805f, 0.000000f, 255.000000f }, +{ 90.303146f, 9.484123f, -117.373001f, -0.810154f, 0.000001f, -0.586217f, 0.000000f, 255.000000f }, +{ 89.062927f, 9.484123f, -114.541092f, -0.982148f, 0.000000f, -0.188111f, 0.000000f, 255.000000f }, +{ 88.900543f, 9.484123f, -112.467911f, -0.999661f, 0.000000f, -0.026047f, 0.000000f, 255.000000f }, +{ 88.900543f, 9.484118f, -94.001602f, -0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 85.630478f, 9.484118f, -94.001602f, -0.996832f, -0.000001f, 0.079535f, 0.000000f, 255.000000f }, +{ 88.413712f, 9.484118f, -89.945480f, -0.823749f, -0.000001f, 0.566955f, 0.000000f, 255.000000f }, +{ 90.968979f, 9.484117f, -86.238449f, -0.837145f, -0.000001f, 0.546981f, 0.000000f, 255.000000f }, +{ 93.453003f, 9.484117f, -82.331924f, -0.315664f, -0.000001f, 0.948871f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484117f, -82.331924f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484118f, -89.641510f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484118f, -89.641510f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484118f, -94.001602f, 0.447214f, 0.000001f, -0.894427f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484118f, -94.001602f, 0.897364f, 0.000532f, -0.441290f, 0.000000f, 255.000000f }, +{ 94.060944f, 9.484123f, -112.446518f, 0.908382f, 0.000909f, 0.418140f, 0.000000f, 255.000000f }, +{ 95.185699f, 9.484123f, -113.977371f, 0.300433f, -0.000003f, 0.953803f, 0.000000f, 255.000000f }, +{ 96.701706f, 9.484123f, -113.985397f, -0.229252f, -0.000002f, 0.973367f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091312f, -113.301422f, 0.166049f, -0.000002f, 0.986117f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091312f, -117.725632f, 0.932011f, 0.000001f, -0.362429f, 0.000000f, 255.000000f }, +{ 95.979660f, 21.091312f, -118.792801f, 0.245227f, 0.000003f, -0.969466f, 0.000000f, 255.000000f }, +{ 92.633392f, 21.091312f, -118.666061f, -0.191620f, 0.000002f, -0.981469f, 0.000000f, 255.000000f }, +{ 90.303146f, 21.091312f, -117.372986f, -0.659538f, 0.000001f, -0.751671f, 0.000000f, 255.000000f }, +{ 89.062927f, 21.091312f, -114.541061f, -0.954830f, 0.000001f, -0.297154f, 0.000000f, 255.000000f }, +{ 88.900543f, 21.091312f, -112.467880f, -0.998642f, 0.000000f, -0.052093f, 0.000000f, 255.000000f }, +{ 88.900543f, 21.091311f, -94.001587f, -0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 85.630478f, 21.091311f, -94.001587f, -0.498416f, 0.000001f, -0.866938f, 0.000000f, 255.000000f }, +{ 88.413712f, 21.091311f, -89.945450f, -0.824150f, -0.000001f, 0.566372f, 0.000000f, 255.000000f }, +{ 90.968979f, 21.091311f, -86.238419f, -0.830310f, -0.000001f, 0.557302f, 0.000000f, 255.000000f }, +{ 93.453003f, 21.091309f, -82.331909f, -0.631328f, -0.000001f, 0.775516f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091309f, -82.331909f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091311f, -89.641495f, 0.894427f, -0.000001f, 0.447214f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091311f, -89.641495f, 0.447214f, -0.000001f, 0.894427f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091311f, -94.001587f, 0.894427f, 0.000001f, -0.447214f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091311f, -94.001587f, 0.448616f, 0.000001f, -0.893725f, 0.000000f, 255.000000f }, +{ 94.047279f, 21.091312f, -112.455856f, 0.976683f, 0.000910f, 0.214684f, 0.000000f, 255.000000f }, +{ 95.185699f, 21.091312f, -113.977341f, 0.592555f, 0.000522f, 0.805530f, 0.000000f, 255.000000f }, +{ 96.701706f, 21.091312f, -113.985367f, -0.111941f, -0.000003f, 0.993715f, 0.000000f, 255.000000f }, +{ 236.900940f, 9.484123f, -111.377884f, 0.874270f, -0.000001f, 0.485440f, 0.000000f, 255.000000f }, +{ 236.900940f, 9.484123f, -116.315048f, 0.760144f, 0.000001f, -0.649754f, 0.000000f, 255.000000f }, +{ 233.106049f, 9.484123f, -118.552078f, 0.152177f, 0.000001f, -0.988353f, 0.000000f, 255.000000f }, +{ 228.432480f, 9.484123f, -118.394455f, -0.459334f, 0.000001f, -0.888264f, 0.000000f, 255.000000f }, +{ 224.397736f, 9.484123f, -115.040680f, -0.838627f, 0.000001f, -0.544707f, 0.000000f, 255.000000f }, +{ 223.067856f, 9.484123f, -112.118805f, -0.959193f, 0.000000f, -0.282752f, 0.000000f, 255.000000f }, +{ 222.243805f, 9.484118f, -108.374069f, -0.993577f, 0.000000f, -0.113154f, 0.000000f, 255.000000f }, +{ 221.961212f, 9.484118f, -103.811813f, -0.999878f, 0.000000f, 0.015606f, 0.000000f, 255.000000f }, +{ 222.198090f, 9.484118f, -99.454697f, -0.989803f, 0.000000f, 0.142441f, 0.000000f, 255.000000f }, +{ 222.894501f, 9.484118f, -95.777939f, -0.953092f, -0.000001f, 0.302682f, 0.000000f, 255.000000f }, +{ 224.029053f, 9.484106f, -92.831436f, -0.859240f, -0.000001f, 0.511572f, 0.000000f, 255.000000f }, +{ 225.580368f, 9.484118f, -90.665039f, -0.601898f, -0.000001f, 0.798573f, 0.000000f, 255.000000f }, +{ 228.791931f, 9.484118f, -88.927658f, -0.064729f, -0.000002f, 0.997903f, 0.000000f, 255.000000f }, +{ 232.490982f, 9.484118f, -89.470520f, 0.480740f, -0.000002f, 0.876863f, 0.000000f, 255.000000f }, +{ 234.407425f, 9.484118f, -91.009384f, 0.770418f, -0.000001f, 0.637539f, 0.000000f, 255.000000f }, +{ 235.810913f, 9.484106f, -93.103928f, 0.938897f, 0.000000f, 0.344198f, 0.000000f, 255.000000f }, +{ 237.245300f, 9.484118f, -99.154877f, 0.994578f, 0.000000f, 0.103993f, 0.000000f, 255.000000f }, +{ 237.478027f, 9.484118f, -104.965958f, 0.454185f, 0.000001f, -0.890908f, 0.000000f, 255.000000f }, +{ 226.962494f, 9.484118f, -104.965958f, 0.931736f, 0.000000f, -0.363137f, 0.000000f, 255.000000f }, +{ 227.534821f, 9.484123f, -110.009995f, 0.932111f, 0.000000f, 0.362173f, 0.000000f, 255.000000f }, +{ 229.232788f, 9.484123f, -113.130463f, 0.561655f, -0.000001f, 0.827372f, 0.000000f, 255.000000f }, +{ 232.027893f, 9.484123f, -114.199112f, -0.059664f, -0.000002f, 0.998219f, 0.000000f, 255.000000f }, +{ 234.632736f, 9.484123f, -113.485794f, -0.556105f, -0.000002f, 0.831112f, 0.000000f, 255.000000f }, +{ 226.898376f, 9.484118f, -101.247055f, 0.458115f, -0.000001f, 0.888893f, 0.000000f, 255.000000f }, +{ 232.476730f, 9.484118f, -101.247055f, -0.917640f, -0.000001f, 0.397413f, 0.000000f, 255.000000f }, +{ 232.170380f, 9.484118f, -96.746857f, -0.968412f, 0.000000f, -0.249358f, 0.000000f, 255.000000f }, +{ 231.222839f, 9.484118f, -94.098984f, -0.666434f, 0.000002f, -0.745564f, 0.000000f, 255.000000f }, +{ 229.591370f, 9.484106f, -93.232178f, 0.199198f, 0.000001f, -0.979959f, 0.000000f, 255.000000f }, +{ 228.066772f, 9.484118f, -94.113220f, 0.848531f, 0.000001f, -0.529145f, 0.000000f, 255.000000f }, +{ 227.183350f, 9.484118f, -96.775345f, 0.988917f, 0.000000f, -0.148471f, 0.000000f, 255.000000f }, +{ 236.900940f, 21.091320f, -111.377853f, -0.239566f, -0.000003f, 0.970880f, 0.000000f, 255.000000f }, +{ 236.900940f, 21.091320f, -116.315018f, 0.945756f, 0.000001f, -0.324877f, 0.000000f, 255.000000f }, +{ 233.106049f, 21.091320f, -118.552063f, 0.339296f, 0.000002f, -0.940680f, 0.000000f, 255.000000f }, +{ 228.432480f, 21.091320f, -118.394440f, -0.247366f, 0.000001f, -0.968922f, 0.000000f, 255.000000f }, +{ 224.397736f, 21.091320f, -115.040665f, -0.746247f, 0.000001f, -0.665669f, 0.000000f, 255.000000f }, +{ 223.067856f, 21.091320f, -112.118790f, -0.936926f, 0.000000f, -0.349528f, 0.000000f, 255.000000f }, +{ 222.243805f, 21.091312f, -108.374054f, -0.986407f, 0.000000f, -0.164320f, 0.000000f, 255.000000f }, +{ 221.961212f, 21.091311f, -103.811798f, -0.999732f, 0.000000f, -0.023155f, 0.000000f, 255.000000f }, +{ 222.198090f, 21.091307f, -99.454666f, -0.995145f, 0.000000f, 0.098417f, 0.000000f, 255.000000f }, +{ 222.894501f, 21.091311f, -95.777908f, -0.969592f, -0.000001f, 0.244728f, 0.000000f, 255.000000f }, +{ 224.029053f, 21.091311f, -92.831406f, -0.899585f, -0.000001f, 0.436746f, 0.000000f, 255.000000f }, +{ 225.580368f, 21.091311f, -90.665024f, -0.716920f, -0.000001f, 0.697156f, 0.000000f, 255.000000f }, +{ 228.791931f, 21.091311f, -88.927628f, -0.281538f, -0.000002f, 0.959550f, 0.000000f, 255.000000f }, +{ 232.490982f, 21.091311f, -89.470505f, 0.315299f, -0.000002f, 0.948992f, 0.000000f, 255.000000f }, +{ 234.407425f, 21.091311f, -91.009354f, 0.701501f, -0.000002f, 0.712669f, 0.000000f, 255.000000f }, +{ 235.810913f, 21.091311f, -93.103912f, 0.890786f, -0.000001f, 0.454423f, 0.000000f, 255.000000f }, +{ 237.245300f, 21.091307f, -99.154861f, 0.985820f, 0.000000f, 0.167804f, 0.000000f, 255.000000f }, +{ 237.478027f, 21.091309f, -104.965942f, 0.908369f, 0.000001f, -0.418169f, 0.000000f, 255.000000f }, +{ 226.962494f, 21.091312f, -104.965942f, 0.465868f, 0.000001f, -0.884854f, 0.000000f, 255.000000f }, +{ 227.534821f, 21.091320f, -110.009979f, 0.971167f, 0.000000f, 0.238399f, 0.000000f, 255.000000f }, +{ 229.232788f, 21.091320f, -113.130447f, 0.745484f, -0.000001f, 0.666524f, 0.000000f, 255.000000f }, +{ 232.027893f, 21.091320f, -114.199097f, 0.156935f, -0.000001f, 0.987609f, 0.000000f, 255.000000f }, +{ 234.632736f, 21.091320f, -113.485764f, -0.413582f, -0.000002f, 0.910467f, 0.000000f, 255.000000f }, +{ 226.898376f, 21.091307f, -101.247040f, 0.916229f, -0.000001f, 0.400654f, 0.000000f, 255.000000f }, +{ 232.476730f, 21.091307f, -101.247040f, -0.458820f, -0.000001f, 0.888529f, 0.000000f, 255.000000f }, +{ 232.170380f, 21.091311f, -96.746841f, -0.987291f, 0.000000f, -0.158926f, 0.000000f, 255.000000f }, +{ 231.222839f, 21.091311f, -94.098953f, -0.833881f, 0.000001f, -0.551945f, 0.000000f, 255.000000f }, +{ 229.591370f, 21.091311f, -93.232162f, -0.164166f, 0.000002f, -0.986433f, 0.000000f, 255.000000f }, +{ 228.066772f, 21.091311f, -94.113205f, 0.689776f, 0.000001f, -0.724023f, 0.000000f, 255.000000f }, +{ 227.183350f, 21.091311f, -96.775330f, 0.972507f, 0.000000f, -0.232875f, 0.000000f, 255.000000f }, +{ -227.530014f, -20.966743f, 18.889576f, -1.000000f, 0.000000f, 0.000000f, 11.312357f, 104.759467f }, +{ -227.530014f, -20.966749f, 49.094059f, -1.000000f, 0.000000f, 0.000000f, 24.483732f, 68.571409f }, +{ -259.747955f, -20.966747f, 81.060303f, -1.000000f, 0.000000f, 0.000000f, -0.177157f, 16.222941f }, +{ -259.747955f, -20.966751f, 111.264603f, -1.000000f, 0.000000f, 0.000000f, 12.994208f, -19.965071f }, +{ -264.026886f, -20.966732f, -47.559727f, -1.000000f, 0.000000f, 0.000000f, -61.391828f, 168.457698f }, +{ -264.026886f, -20.966738f, -14.334979f, -1.000000f, 0.000000f, 0.000000f, -46.903330f, 128.650867f }, +{ -148.686584f, -20.966757f, 116.550354f, -1.000000f, 0.000000f, 0.000000f, 148.362720f, 22.133174f }, +{ -148.686584f, -20.966743f, -55.110798f, -1.000000f, 0.000000f, 0.000000f, 73.505490f, 227.801797f }, +{ 53.459190f, 2.970489f, -63.834198f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970482f, 19.696451f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970485f, 19.696451f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970482f, 37.767296f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970478f, 37.767296f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970482f, 19.696451f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970482f, 19.696451f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970489f, -63.834198f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ -227.530014f, 20.966755f, 18.889763f, -1.000000f, 0.000000f, 0.000000f, 11.312366f, 104.759421f }, +{ -227.530014f, 20.966747f, 49.094074f, -1.000000f, 0.000000f, 0.000000f, 24.483732f, 68.571394f }, +{ -259.747955f, 20.966745f, 81.060341f, -1.000000f, 0.000000f, 0.000000f, -0.177137f, 16.222895f }, +{ -259.747955f, 20.966743f, 111.264641f, -1.000000f, 0.000000f, 0.000000f, 12.994218f, -19.965132f }, +{ -264.026886f, 20.966764f, -47.559723f, -1.000000f, 0.000000f, 0.000000f, -61.391828f, 168.457698f }, +{ -264.026886f, 20.966753f, -14.334975f, -1.000000f, 0.000000f, 0.000000f, -46.903330f, 128.650867f }, +{ -148.686584f, 20.966726f, 116.550392f, -1.000000f, 0.000000f, 0.000000f, 148.362750f, 22.133128f }, +{ -148.686584f, 20.966757f, -55.110794f, -1.000000f, 0.000000f, 0.000000f, 73.505490f, 227.801797f }, +{ 53.459190f, 21.106728f, -63.834198f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106720f, 19.696632f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106720f, 19.696632f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106718f, 37.767292f, -1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106718f, 37.767292f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106720f, 19.696632f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106720f, 19.696632f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106728f, -63.834198f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ -227.530014f, -20.966743f, 18.889576f, 0.000000f, -1.000000f, 0.000000f, 11.312357f, 104.759467f }, +{ -227.530014f, -20.966749f, 49.094059f, 0.000000f, -1.000000f, 0.000000f, 24.483732f, 68.571409f }, +{ -220.271423f, -20.966749f, 49.922577f, 0.000000f, -1.000000f, 0.000000f, 33.541598f, 70.744057f }, +{ -214.348251f, -20.966755f, 52.198391f, 0.000000f, -1.000000f, 0.000000f, 41.630631f, 70.600333f }, +{ -209.753510f, -20.966747f, 55.606861f, 0.000001f, -1.000000f, 0.000000f, 48.621978f, 68.520264f }, +{ -206.480209f, -20.966747f, 59.833366f, 0.000000f, -1.000000f, 0.000000f, 54.386820f, 64.883859f }, +{ -204.521362f, -20.966749f, 64.563301f, 0.000000f, -1.000000f, 0.000000f, 58.796339f, 60.071098f }, +{ -203.869965f, -20.966747f, 69.481987f, 0.000000f, -1.000000f, 0.000000f, 61.721703f, 54.462037f }, +{ -204.699646f, -20.966759f, 74.975159f, 0.000000f, -1.000000f, 0.000000f, 63.123094f, 47.518821f }, +{ -207.067520f, -20.966751f, 79.783142f, 0.000000f, -1.000000f, 0.000000f, 62.382769f, 40.725774f }, +{ -210.791794f, -20.966751f, 83.766113f, 0.000000f, -1.000000f, 0.000000f, 59.657563f, 34.329668f }, +{ -215.690674f, -20.966751f, 86.784210f, 0.000000f, -1.000000f, 0.000000f, 55.104290f, 28.577385f }, +{ -221.582382f, -20.966751f, 88.697617f, 0.000000f, -1.000000f, 0.000000f, 48.879779f, 23.715683f }, +{ -228.285126f, -20.966751f, 89.366486f, 0.000000f, -1.000000f, 0.000000f, 41.140841f, 19.991411f }, +{ -233.272552f, -20.966751f, 89.153244f, 0.000000f, -1.000000f, 0.000000f, 35.072373f, 18.071997f }, +{ -238.232040f, -20.966751f, 88.499512f, 0.000000f, -1.000000f, 0.000000f, 28.845299f, 16.692535f }, +{ -243.261429f, -20.966751f, 87.384338f, 0.000000f, -1.000000f, 0.000000f, 22.333248f, 15.835422f }, +{ -248.458618f, -20.966747f, 85.786713f, 0.000000f, -1.000000f, 0.000000f, 15.409765f, 15.483181f }, +{ -253.921509f, -20.966747f, 83.685699f, 0.000000f, -1.000000f, 0.000000f, 7.948429f, 15.618211f }, +{ -259.747955f, -20.966747f, 81.060303f, 0.000000f, -1.000000f, 0.000000f, -0.177157f, 16.222941f }, +{ -259.747955f, -20.966751f, 111.264603f, 0.000000f, -1.000000f, 0.000000f, 12.994208f, -19.965071f }, +{ -253.885376f, -20.966755f, 113.571884f, 0.000000f, -1.000000f, 0.000000f, 21.024357f, -20.172935f }, +{ -247.666229f, -20.966757f, 115.459656f, 0.000000f, -1.000000f, 0.000000f, 29.298774f, -19.722674f }, +{ -241.153412f, -20.966763f, 116.927917f, 0.000000f, -1.000000f, 0.000000f, 37.742109f, -18.641708f }, +{ -234.409882f, -20.966763f, 117.976685f, 0.000000f, -1.000000f, 0.000000f, 46.278933f, -16.957548f }, +{ -227.498550f, -20.966763f, 118.605942f, 0.000000f, -1.000000f, 0.000000f, 54.833858f, -14.697611f }, +{ -220.482346f, -20.966763f, 118.815689f, 0.000000f, -1.000000f, 0.000000f, 63.331494f, -11.889319f }, +{ -205.143631f, -20.966763f, 117.432495f, 0.000000f, -1.000000f, 0.000000f, 81.105759f, -3.543264f }, +{ -191.825546f, -20.966755f, 113.455368f, 0.000000f, -1.000000f, 0.000000f, 95.327940f, 7.029456f }, +{ -180.870651f, -20.966755f, 107.142990f, 0.000000f, -1.000000f, 0.000000f, 105.700410f, 19.369521f }, +{ -172.621567f, -20.966755f, 98.754059f, 0.000000f, -1.000000f, 0.000000f, 111.925502f, 33.017599f }, +{ -167.420868f, -20.966753f, 88.547287f, 0.000000f, -1.000000f, 0.000000f, 113.705577f, 47.514307f }, +{ -165.611176f, -20.966751f, 76.781357f, 0.000000f, -1.000000f, 0.000000f, 110.742945f, 62.400328f }, +{ -166.340637f, -20.966751f, 68.696579f, 0.000000f, -1.000000f, -0.000001f, 106.343396f, 71.768664f }, +{ -168.510422f, -20.966749f, 61.101204f, 0.000000f, -1.000000f, 0.000000f, 100.431605f, 79.922555f }, +{ -172.092514f, -20.966755f, 54.065182f, 0.000000f, -1.000000f, 0.000000f, 93.071636f, 86.790413f }, +{ -177.058975f, -20.966747f, 47.658421f, 0.000000f, -1.000000f, -0.000001f, 84.327446f, 92.300650f }, +{ -183.381851f, -20.966743f, 41.950832f, 0.000000f, -1.000000f, 0.000000f, 74.263017f, 96.381707f }, +{ -191.033142f, -20.966743f, 37.012333f, 0.000000f, -1.000000f, 0.000000f, 62.942380f, 98.962027f }, +{ -181.454453f, -20.966751f, 32.298737f, 0.000000f, -1.000000f, 0.000000f, 72.363203f, 108.786445f }, +{ -173.805496f, -20.966743f, 26.319462f, 0.000000f, -1.000000f, 0.000000f, 78.920131f, 119.285616f }, +{ -168.002350f, -20.966745f, 19.235668f, 0.000000f, -1.000000f, 0.000000f, 82.783855f, 130.303376f }, +{ -163.961121f, -20.966740f, 11.208173f, 0.000000f, -1.000000f, 0.000000f, 84.125031f, 141.683643f }, +{ -161.597916f, -20.966740f, 2.397420f, 0.000000f, -1.000000f, 0.000000f, 83.114247f, 153.270415f }, +{ -160.828827f, -20.966740f, -7.035602f, 0.000000f, -1.000000f, 0.000000f, 79.922191f, 164.907572f }, +{ -162.772522f, -20.966736f, -21.426922f, 0.000000f, -1.000000f, 0.000000f, 71.317727f, 181.302331f }, +{ -168.407867f, -20.966743f, -33.734730f, 0.000000f, -1.000000f, 0.000000f, 59.198844f, 193.590982f }, +{ -177.441193f, -20.966736f, -43.721256f, 0.000000f, -1.000000f, 0.000000f, 44.021060f, 201.616710f }, +{ -189.578857f, -20.966732f, -51.148808f, 0.000000f, -1.000000f, 0.000000f, 26.239853f, 205.222777f }, +{ -204.527191f, -20.966740f, -55.779682f, 0.000000f, -1.000000f, 0.000000f, 6.310721f, 204.252461f }, +{ -221.992554f, -20.966740f, -57.376118f, 0.000000f, -1.000000f, 0.000000f, -15.310837f, 198.548949f }, +{ -229.371170f, -20.966740f, -57.068485f, 0.000000f, -1.000000f, 0.000000f, -24.017065f, 194.962735f }, +{ -236.805725f, -20.966740f, -56.173542f, 0.000000f, -1.000000f, 0.000000f, -32.534211f, 190.648469f }, +{ -244.142380f, -20.966740f, -54.733250f, 0.000000f, -1.000000f, 0.000000f, -40.696227f, 185.723508f }, +{ -251.227341f, -20.966732f, -52.789539f, 0.000000f, -1.000000f, 0.000000f, -48.337180f, 180.305151f }, +{ -257.906799f, -20.966732f, -50.384388f, 0.000000f, -1.000000f, 0.000000f, -55.291061f, 174.510773f }, +{ -264.026886f, -20.966732f, -47.559727f, 0.000000f, -1.000000f, 0.000000f, -61.391828f, 168.457698f }, +{ -264.026886f, -20.966738f, -14.334979f, 0.000000f, -1.000000f, 0.000000f, -46.903330f, 128.650867f }, +{ -257.339294f, -20.966736f, -18.662861f, 0.000000f, -1.000000f, 0.000000f, -40.778150f, 136.752428f }, +{ -251.050217f, -20.966736f, -22.109791f, 0.000000f, -1.000000f, 0.000000f, -34.746278f, 143.624739f }, +{ -245.054810f, -20.966736f, -24.717709f, 0.000000f, -1.000000f, 0.000000f, -28.700379f, 149.363753f }, +{ -239.248169f, -20.966736f, -26.528568f, 0.000000f, -1.000000f, 0.000000f, -22.533070f, 154.065492f }, +{ -233.525421f, -20.966736f, -27.584324f, 0.000000f, -1.000000f, 0.000000f, -16.136991f, 157.825952f }, +{ -227.781708f, -20.966736f, -27.926914f, 0.000000f, -1.000000f, 0.000000f, -9.404798f, 160.741110f }, +{ -220.280746f, -20.966736f, -27.192783f, 0.000000f, -1.000000f, 0.000000f, -0.097693f, 163.132527f }, +{ -213.751633f, -20.966736f, -25.074284f, 0.000000f, -1.000000f, 0.000000f, 8.648720f, 163.441519f }, +{ -208.369156f, -20.966736f, -21.697269f, 0.000000f, -1.000000f, 0.000000f, 16.570136f, 161.742661f }, +{ -204.308121f, -20.966736f, -17.187603f, 0.000000f, -1.000000f, -0.000001f, 23.402251f, 158.110511f }, +{ -201.743317f, -20.966747f, -11.671123f, 0.000000f, -1.000000f, 0.000000f, 28.880766f, 152.619616f }, +{ -200.849533f, -20.966740f, -5.273685f, 0.000000f, -1.000000f, 0.000000f, 32.741388f, 145.344557f }, +{ -201.724655f, -20.966740f, 1.288052f, 0.000000f, -1.000000f, 0.000000f, 34.554308f, 137.101264f }, +{ -204.242859f, -20.966745f, 7.031773f, 0.000000f, -1.000000f, 0.000000f, 34.041921f, 129.121540f }, +{ -208.243301f, -20.966740f, 11.810628f, 0.000000f, -1.000000f, 0.000000f, 31.332898f, 121.651460f }, +{ -213.565170f, -20.966740f, 15.477796f, 0.000001f, -1.000000f, 0.000000f, 26.555888f, 114.937053f }, +{ -220.047684f, -20.966743f, 17.886265f, 0.000000f, -1.000000f, 0.000000f, 19.839473f, 109.224409f }, +{ -148.686584f, -20.966757f, 116.550354f, 0.000000f, -1.000000f, 0.000000f, 148.362720f, 22.133174f }, +{ -72.924095f, -20.966761f, 116.550354f, 0.000000f, -1.000000f, 0.000000f, 239.134392f, 55.171337f }, +{ -44.133286f, -20.966759f, 113.442535f, 0.000000f, -1.000000f, 0.000000f, 272.273660f, 71.449816f }, +{ -20.467419f, -20.966759f, 104.692368f, 0.000000f, -1.000000f, 0.000000f, 296.812166f, 92.253563f }, +{ -1.975434f, -20.966759f, 91.159866f, 0.000000f, -1.000000f, 0.000000f, 313.066387f, 116.530870f }, +{ 11.293716f, -20.966763f, 73.704994f, 0.000000f, -1.000000f, 0.000000f, 321.352617f, 143.230046f }, +{ 19.291100f, -20.966763f, 53.187717f, 0.000000f, -1.000000f, 0.000000f, 321.987274f, 171.299429f }, +{ 21.967770f, -20.966759f, 30.467985f, 0.000000f, -1.000000f, 0.000000f, 315.286714f, 199.687265f }, +{ 19.338877f, -20.966749f, 6.999157f, 0.000000f, -1.000000f, 0.000000f, 301.902798f, 226.659149f }, +{ 11.340330f, -20.966751f, -13.645114f, 0.000000f, -1.000000f, 0.000000f, 283.317205f, 247.905254f }, +{ -2.195676f, -20.966743f, -30.821491f, 0.000000f, -1.000000f, 0.000000f, 259.609426f, 262.581684f }, +{ -21.436935f, -20.966740f, -43.886723f, 0.000000f, -1.000000f, 0.000000f, 230.858877f, 269.844599f }, +{ -46.551262f, -20.966736f, -52.197575f, 0.000000f, -1.000000f, 0.000000f, 197.145034f, 268.850158f }, +{ -77.706444f, -20.966743f, -55.110798f, 0.000000f, -1.000000f, 0.000000f, 158.547374f, 258.754495f }, +{ -148.686584f, -20.966743f, -55.110798f, 0.000000f, -1.000000f, 0.000000f, 73.505490f, 227.801797f }, +{ -105.897141f, -20.966753f, 85.087540f, 0.000000f, -1.000000f, 0.000000f, 185.908946f, 78.488452f }, +{ -105.897141f, -20.966742f, -23.647968f, 0.000000f, -1.000000f, 0.000000f, 138.492050f, 208.765350f }, +{ -77.958153f, -20.966742f, -23.647968f, 0.000000f, -1.000000f, 0.000000f, 171.965974f, 220.948864f }, +{ -58.874207f, -20.966740f, -21.368664f, 0.000000f, -1.000000f, 0.000000f, 195.824559f, 226.540055f }, +{ -44.341877f, -20.966745f, -15.146022f, 0.000000f, -1.000000f, 0.000000f, 215.949404f, 225.421851f }, +{ -33.878738f, -20.966743f, -5.902942f, 0.000000f, -1.000000f, 0.000000f, 232.516059f, 218.910357f }, +{ -27.002363f, -20.966749f, 5.437657f, 0.000000f, -1.000000f, 0.000000f, 245.700060f, 208.321713f }, +{ -23.230320f, -20.966747f, 17.952679f, 0.000000f, -1.000000f, 0.000000f, 255.676941f, 194.972086f }, +{ -22.080179f, -20.966755f, 30.719687f, 0.000000f, -1.000000f, 0.000000f, 262.622269f, 180.177463f }, +{ -23.442402f, -20.966751f, 44.972424f, 0.000000f, -1.000000f, 0.000000f, 267.205431f, 162.507202f }, +{ -27.692215f, -20.966751f, 57.903645f, 0.000000f, -1.000000f, 0.000000f, 267.752663f, 145.160958f }, +{ -35.074326f, -20.966751f, 68.947113f, 0.000000f, -1.000000f, 0.000000f, 263.723906f, 128.710531f }, +{ -45.833443f, -20.966755f, 77.536469f, 0.000000f, -1.000000f, 0.000000f, 254.578922f, 113.727776f }, +{ -60.214287f, -20.966755f, 83.105392f, 0.000000f, -1.000000f, 0.000000f, 239.777576f, 100.784454f }, +{ -78.461555f, -20.966755f, 85.087540f, 0.000000f, -1.000000f, 0.000000f, 218.779751f, 90.452444f }, +{ 53.459190f, 2.970489f, -63.834198f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970482f, 19.696451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970485f, 19.696451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 2.970482f, 37.767296f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970482f, 37.767296f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 2.970471f, 52.887688f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 54.761124f, 2.970478f, 61.040325f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.744659f, 2.970474f, 68.629539f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 65.526382f, 2.970473f, 75.245560f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 75.222885f, 2.970474f, 80.478622f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 87.950760f, 2.970474f, 83.918953f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.826599f, 2.970474f, 85.156792f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.486267f, 2.970474f, 85.094475f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.371353f, 2.970474f, 84.904106f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 115.334160f, 2.970474f, 84.580559f, 0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 119.227013f, 2.970474f, 84.118721f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 122.902229f, 2.970474f, 83.513466f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 126.212128f, 2.970474f, 82.759666f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 114.179916f, 2.970478f, 65.426537f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 112.235428f, 2.970474f, 65.933624f, 0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 110.283180f, 2.970474f, 66.348511f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 108.268738f, 2.970474f, 66.671196f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.137703f, 2.970474f, 66.901688f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.835670f, 2.970474f, 67.039986f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 101.308228f, 2.970474f, 67.086082f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.838806f, 2.970474f, 66.577293f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 91.224388f, 2.970478f, 65.167015f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 87.527145f, 2.970478f, 63.029404f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 84.809280f, 2.970478f, 60.338612f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 83.132957f, 2.970478f, 57.268784f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970479f, 53.994072f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970478f, 37.767296f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970478f, 37.767296f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 2.970482f, 19.696451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970482f, 19.696451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 2.970489f, -63.834198f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 109.261765f, 2.970490f, -33.040283f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 158.509918f, 2.970482f, 10.661288f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 110.660858f, 2.970478f, 56.206810f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.037323f, 2.970478f, 56.206810f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 175.299042f, 2.970477f, 25.597071f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 203.001129f, 2.970478f, 56.206810f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 237.139038f, 2.970478f, 56.206810f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 189.569809f, 2.970482f, 11.767657f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 239.097778f, 2.970486f, -33.040283f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 202.161682f, 2.970486f, -33.040283f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.620132f, 2.970482f, -3.168332f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.679504f, 2.970490f, -33.040283f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 246.695496f, 2.970477f, 44.635109f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 246.695496f, 2.970479f, 54.095207f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 243.335144f, 2.970479f, 54.095207f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 243.335144f, 2.970478f, 56.104118f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 252.174316f, 2.970478f, 56.104118f, -0.000001f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 252.174316f, 2.970475f, 54.095207f, -0.000001f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 248.813965f, 2.970479f, 54.095207f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 248.813965f, 2.970477f, 44.635109f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 253.836212f, 2.970477f, 44.635109f, -0.000002f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 253.836212f, 2.970478f, 56.341530f, -0.000001f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 258.931549f, 2.970471f, 51.191429f, -0.000001f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 264.026886f, 2.970478f, 56.341530f, 0.000002f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 264.026886f, 2.970477f, 44.635109f, 0.000003f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 261.908356f, 2.970477f, 44.635109f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 261.908356f, 2.970467f, 51.721062f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 258.931549f, 2.970471f, 48.634651f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 255.954681f, 2.970471f, 51.721062f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 255.954681f, 2.970477f, 44.635109f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 53.398365f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.398365f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.399651f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.399651f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 64.683319f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 64.683319f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -92.719223f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 71.361206f, 9.484118f, -90.693527f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 75.070610f, 9.484118f, -89.192673f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 78.221947f, 9.484118f, -90.116470f, -0.000001f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 80.447113f, 9.484106f, -92.906830f, -0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 81.069901f, 9.484118f, -95.010895f, 0.000000f, -1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 81.290161f, 9.484118f, -97.592270f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 81.290161f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.288872f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.288872f, 9.484118f, -97.720505f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.046646f, 9.484118f, -95.573715f, 0.000000f, -1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 74.507790f, 9.484118f, -93.751663f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 72.154381f, 9.484118f, -93.999222f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 70.869621f, 9.484118f, -95.136749f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484118f, -97.015213f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.042702f, 9.484123f, -111.377884f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.042702f, 9.484123f, -116.315048f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 112.247803f, 9.484123f, -118.552078f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.574234f, 9.484123f, -118.394455f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.539482f, 9.484123f, -115.040680f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 102.209610f, 9.484123f, -112.118805f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 101.385559f, 9.484118f, -108.374069f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 101.102959f, 9.484118f, -103.811813f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 101.339844f, 9.484118f, -99.454697f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 102.036247f, 9.484118f, -95.777939f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 103.170799f, 9.484106f, -92.831436f, 0.000002f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 104.722122f, 9.484118f, -90.665039f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.933678f, 9.484118f, -88.927658f, 0.000000f, -1.000000f, 0.000003f, 0.000000f, 255.000000f }, +{ 111.632736f, 9.484118f, -89.470520f, 0.000001f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 113.549179f, 9.484118f, -91.009384f, 0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 114.952675f, 9.484106f, -93.103928f, -0.000002f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.387047f, 9.484118f, -99.154877f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 116.619774f, 9.484118f, -104.965958f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.104248f, 9.484118f, -104.965958f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.676575f, 9.484123f, -110.009995f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 108.374535f, 9.484123f, -113.130463f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.169655f, 9.484123f, -114.199112f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 113.774490f, 9.484123f, -113.485794f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.040123f, 9.484118f, -101.247055f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.618484f, 9.484118f, -101.247055f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.312141f, 9.484118f, -96.746857f, -0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 110.364601f, 9.484118f, -94.098984f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 108.733131f, 9.484106f, -93.232178f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.208519f, 9.484118f, -94.113220f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 106.325096f, 9.484118f, -96.775345f, 0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 122.262253f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 122.262253f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.263535f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.391785f, 9.484118f, -97.335800f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 128.306671f, 9.484118f, -94.372665f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.111130f, 9.484118f, -92.203903f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.876404f, 9.484118f, -90.715500f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 131.574371f, 9.484118f, -89.323883f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 133.556717f, 9.484118f, -89.280533f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 135.214310f, 9.484118f, -90.026230f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 134.829590f, 9.484118f, -95.155746f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 132.649551f, 9.484118f, -94.450439f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 130.914764f, 9.484118f, -95.135269f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.543335f, 9.484118f, -96.915451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 128.513855f, 9.484118f, -99.379593f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.804985f, 9.484118f, -102.116226f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.395340f, 9.484118f, -104.713943f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.263535f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 155.668289f, 9.484123f, -112.788498f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 155.668289f, 9.484123f, -116.571518f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 154.127060f, 9.484123f, -117.804031f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.305023f, 9.484123f, -118.637589f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 150.903000f, 9.484123f, -118.586227f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 149.472794f, 9.484123f, -117.781754f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 148.448669f, 9.484123f, -116.186508f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 148.102249f, 9.484123f, -115.096786f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 146.276031f, 9.484123f, -117.172348f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 142.652115f, 9.484123f, -118.815689f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 139.866501f, 9.484123f, -117.808792f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 137.850311f, 9.484123f, -115.206024f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 137.073761f, 9.484123f, -111.634354f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 138.144791f, 9.484118f, -107.571106f, 0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 141.623840f, 9.484118f, -104.049301f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.391052f, 9.484118f, -102.166397f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -100.028793f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -97.335800f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.180527f, 9.484118f, -94.538605f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 145.869064f, 9.484118f, -93.718704f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.898575f, 9.484118f, -93.732071f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 141.682312f, 9.484118f, -94.706924f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 137.779068f, 9.484118f, -98.297592f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 137.779068f, 9.484118f, -92.526871f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 141.658264f, 9.484118f, -89.665543f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.054428f, 9.484118f, -88.951340f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.152328f, 9.484118f, -89.072159f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 150.474655f, 9.484118f, -90.715500f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.600082f, 9.484118f, -94.111435f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.911179f, 9.484118f, -96.502243f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.932556f, 9.484123f, -113.100784f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 153.103531f, 9.484123f, -113.846451f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 153.680603f, 9.484123f, -114.199112f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 154.124680f, 9.484123f, -114.032883f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 154.796753f, 9.484123f, -113.553177f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484123f, -110.800797f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 9.484118f, -103.491226f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 146.048050f, 9.484118f, -104.727600f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.556686f, 9.484118f, -105.944382f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.421539f, 9.484118f, -107.154037f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 142.162918f, 9.484122f, -109.601837f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 142.329147f, 9.484123f, -112.551010f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.188812f, 9.484123f, -113.667160f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.447449f, 9.484123f, -114.070877f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 145.715591f, 9.484123f, -113.693283f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 146.898224f, 9.484123f, -112.589005f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.430771f, 9.484123f, -111.777725f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.749878f, 9.484123f, -112.467911f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.749878f, 9.484123f, -117.276840f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 172.085159f, 9.484123f, -118.160263f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 168.812698f, 9.484123f, -118.815689f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 166.009262f, 9.484123f, -118.315506f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 163.547806f, 9.484123f, -116.887375f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 161.503128f, 9.484123f, -114.639938f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 159.950012f, 9.484123f, -111.681854f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 158.963303f, 9.484118f, -108.121765f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 158.617767f, 9.484118f, -104.068314f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 159.531387f, 9.484118f, -96.903595f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 163.822617f, 9.484118f, -90.542221f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 169.115997f, 9.484118f, -88.872086f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.301041f, 9.484118f, -89.897995f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.301041f, 9.484118f, -95.027512f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 169.582138f, 9.484118f, -93.616898f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 166.473557f, 9.484118f, -94.882645f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 164.462112f, 9.484118f, -98.442444f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 163.747299f, 9.484118f, -103.940063f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 164.523849f, 9.484122f, -109.302322f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 166.711029f, 9.484123f, -112.812241f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 171.313354f, 9.484123f, -113.911758f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484123f, -113.301437f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484123f, -117.725662f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 186.637802f, 9.484123f, -118.378738f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.602036f, 9.484123f, -118.792831f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 182.419891f, 9.484123f, -118.666077f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 181.128311f, 9.484123f, -118.195877f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 180.089645f, 9.484123f, -117.373001f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 179.323486f, 9.484123f, -116.165436f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.849426f, 9.484123f, -114.541092f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.687042f, 9.484123f, -112.467911f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.687042f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 175.416977f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.200211f, 9.484118f, -89.945480f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 180.755478f, 9.484117f, -86.238449f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.239502f, 9.484117f, -82.331924f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484117f, -82.331924f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.724243f, 9.484123f, -111.466034f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.847443f, 9.484123f, -112.446518f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.448257f, 9.484123f, -113.686172f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.972198f, 9.484123f, -113.977371f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 186.488205f, 9.484123f, -113.985397f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 192.280289f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 192.280289f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.281570f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.281570f, 9.484123f, -118.046249f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 209.400085f, 9.484123f, -118.687454f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 200.872238f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 205.873535f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.041275f, 9.484118f, -105.863632f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.169510f, 9.484118f, -105.863632f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 214.337250f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 219.338531f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.810699f, 9.484123f, -118.687454f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ -227.530014f, 20.966755f, 18.889763f, 0.000000f, 1.000000f, 0.000000f, 11.312366f, 104.759421f }, +{ -227.530014f, 20.966747f, 49.094074f, 0.000000f, 1.000000f, 0.000000f, 24.483732f, 68.571394f }, +{ -220.271423f, 20.966747f, 49.922592f, 0.000000f, 1.000000f, 0.000000f, 33.541610f, 70.744042f }, +{ -214.348251f, 20.966747f, 52.198406f, 0.000000f, 1.000000f, 0.000000f, 41.630631f, 70.600318f }, +{ -209.753510f, 20.966751f, 55.606876f, 0.000000f, 1.000000f, 0.000000f, 48.621982f, 68.520264f }, +{ -206.480209f, 20.966751f, 59.833382f, 0.000000f, 1.000000f, 0.000000f, 54.386827f, 64.883844f }, +{ -204.521362f, 20.966751f, 64.563332f, 0.000000f, 1.000000f, 0.000000f, 58.796350f, 60.071068f }, +{ -203.869965f, 20.966747f, 69.482018f, 0.000000f, 1.000000f, 0.000000f, 61.721714f, 54.462006f }, +{ -204.699646f, 20.966745f, 74.975189f, 0.000000f, 1.000000f, 0.000000f, 63.123110f, 47.518791f }, +{ -207.067520f, 20.966745f, 79.783180f, 0.000000f, 1.000000f, 0.000000f, 62.382784f, 40.725728f }, +{ -210.791794f, 20.966745f, 83.766144f, 0.000000f, 1.000000f, 0.000000f, 59.657578f, 34.329638f }, +{ -215.690674f, 20.966745f, 86.784241f, 0.000000f, 1.000000f, 0.000000f, 55.104305f, 28.577339f }, +{ -221.582382f, 20.966745f, 88.697647f, 0.000000f, 1.000000f, 0.000000f, 48.879791f, 23.715652f }, +{ -228.285126f, 20.966745f, 89.366524f, 0.000000f, 1.000000f, 0.000000f, 41.140860f, 19.991366f }, +{ -233.272552f, 20.966745f, 89.153275f, 0.000000f, 1.000000f, 0.000000f, 35.072392f, 18.071967f }, +{ -238.232040f, 20.966745f, 88.499550f, 0.000000f, 1.000000f, 0.000000f, 28.845318f, 16.692474f }, +{ -243.261429f, 20.966745f, 87.384369f, 0.000000f, 1.000000f, 0.000000f, 22.333258f, 15.835392f }, +{ -248.458618f, 20.966745f, 85.786751f, 0.000000f, 1.000000f, 0.000000f, 15.409784f, 15.483151f }, +{ -253.921509f, 20.966745f, 83.685738f, 0.000000f, 1.000000f, 0.000000f, 7.948449f, 15.618150f }, +{ -259.747955f, 20.966745f, 81.060341f, 0.000000f, 1.000000f, 0.000000f, -0.177137f, 16.222895f }, +{ -259.747955f, 20.966743f, 111.264641f, 0.000000f, 1.000000f, 0.000000f, 12.994218f, -19.965132f }, +{ -253.885376f, 20.966743f, 113.571915f, 0.000000f, 1.000000f, 0.000000f, 21.024369f, -20.172966f }, +{ -247.666229f, 20.966742f, 115.459694f, 0.000000f, 1.000000f, 0.000000f, 29.298793f, -19.722705f }, +{ -241.153412f, 20.966742f, 116.927956f, 0.000000f, 1.000000f, 0.000000f, 37.742128f, -18.641769f }, +{ -234.409882f, 20.966742f, 117.976715f, 0.000000f, 1.000000f, 0.000000f, 46.278944f, -16.957608f }, +{ -227.498550f, 20.966742f, 118.605980f, 0.000000f, 1.000000f, 0.000000f, 54.833877f, -14.697672f }, +{ -220.482346f, 20.966742f, 118.815727f, 0.000000f, 1.000000f, 0.000000f, 63.331513f, -11.889380f }, +{ -205.143631f, 20.966742f, 117.432526f, 0.000000f, 1.000000f, 0.000000f, 81.105774f, -3.543295f }, +{ -191.825546f, 20.966743f, 113.455399f, 0.000000f, 1.000000f, 0.000000f, 95.327947f, 7.029410f }, +{ -180.870651f, 20.966740f, 107.143021f, 0.000000f, 1.000000f, 0.000000f, 105.700425f, 19.369491f }, +{ -172.621567f, 20.966740f, 98.754097f, 0.000000f, 1.000000f, 0.000000f, 111.925517f, 33.017553f }, +{ -167.420868f, 20.966738f, 88.547325f, 0.000000f, 1.000000f, 0.000000f, 113.705593f, 47.514262f }, +{ -165.611176f, 20.966738f, 76.781395f, 0.000000f, 1.000000f, 0.000000f, 110.742960f, 62.400282f }, +{ -166.340637f, 20.966747f, 68.696609f, 0.000000f, 1.000000f, 0.000000f, 106.343412f, 71.768634f }, +{ -168.510422f, 20.966751f, 61.101219f, 0.000000f, 1.000000f, 0.000000f, 100.431613f, 79.922540f }, +{ -172.092514f, 20.966747f, 54.065197f, 0.000000f, 1.000000f, 0.000000f, 93.071636f, 86.790398f }, +{ -177.058975f, 20.966749f, 47.658436f, 0.000000f, 1.000000f, 0.000000f, 84.327446f, 92.300634f }, +{ -183.381851f, 20.966749f, 41.950848f, 0.000000f, 1.000000f, 0.000000f, 74.263017f, 96.381691f }, +{ -191.033142f, 20.966749f, 37.012348f, 0.000000f, 1.000000f, 0.000000f, 62.942388f, 98.962011f }, +{ -181.454453f, 20.966749f, 32.298752f, 0.000000f, 1.000000f, 0.000000f, 72.363211f, 108.786445f }, +{ -173.805496f, 20.966751f, 26.319649f, 0.000000f, 1.000000f, 0.000000f, 78.920146f, 119.285570f }, +{ -168.002350f, 20.966755f, 19.235847f, 0.000000f, 1.000000f, 0.000000f, 82.783870f, 130.303345f }, +{ -163.961121f, 20.966755f, 11.208177f, 0.000000f, 1.000000f, 0.000000f, 84.125031f, 141.683643f }, +{ -161.597916f, 20.966753f, 2.397416f, 0.000000f, 1.000000f, 0.000000f, 83.114247f, 153.270422f }, +{ -160.828827f, 20.966753f, -7.035606f, 0.000000f, 1.000000f, 0.000000f, 79.922183f, 164.907587f }, +{ -162.772522f, 20.966755f, -21.426933f, 0.000000f, 1.000000f, 0.000000f, 71.317727f, 181.302347f }, +{ -168.407867f, 20.966755f, -33.734711f, 0.000000f, 1.000000f, 0.000000f, 59.198847f, 193.590963f }, +{ -177.441193f, 20.966757f, -43.721252f, 0.000000f, 1.000000f, 0.000000f, 44.021060f, 201.616710f }, +{ -189.578857f, 20.966757f, -51.148804f, 0.000000f, 1.000000f, 0.000000f, 26.239853f, 205.222777f }, +{ -204.527191f, 20.966757f, -55.779663f, 0.000000f, 1.000000f, 0.000000f, 6.310730f, 204.252446f }, +{ -221.992554f, 20.966764f, -57.376114f, 0.000000f, 1.000000f, 0.000000f, -15.310837f, 198.548949f }, +{ -229.371170f, 20.966764f, -57.068481f, 0.000000f, 1.000000f, 0.000000f, -24.017065f, 194.962735f }, +{ -236.805725f, 20.966764f, -56.173538f, 0.000000f, 1.000000f, 0.000000f, -32.534211f, 190.648469f }, +{ -244.142380f, 20.966764f, -54.733246f, 0.000000f, 1.000000f, 0.000000f, -40.696227f, 185.723508f }, +{ -251.227341f, 20.966764f, -52.789536f, 0.000000f, 1.000000f, 0.000000f, -48.337180f, 180.305151f }, +{ -257.906799f, 20.966764f, -50.384384f, 0.000000f, 1.000000f, 0.000000f, -55.291061f, 174.510773f }, +{ -264.026886f, 20.966764f, -47.559723f, 0.000000f, 1.000000f, 0.000000f, -61.391828f, 168.457698f }, +{ -264.026886f, 20.966753f, -14.334975f, 0.000000f, 1.000000f, 0.000000f, -46.903330f, 128.650867f }, +{ -257.339294f, 20.966755f, -18.662872f, 0.000000f, 1.000000f, 0.000000f, -40.778150f, 136.752450f }, +{ -251.050217f, 20.966759f, -22.109795f, 0.000000f, 1.000000f, 0.000000f, -34.746278f, 143.624746f }, +{ -245.054810f, 20.966759f, -24.717712f, 0.000000f, 1.000000f, 0.000000f, -28.700388f, 149.363761f }, +{ -239.248169f, 20.966759f, -26.528572f, 0.000000f, 1.000000f, 0.000000f, -22.533070f, 154.065507f }, +{ -233.525421f, 20.966759f, -27.584328f, 0.000000f, 1.000000f, 0.000000f, -16.136991f, 157.825968f }, +{ -227.781708f, 20.966759f, -27.926926f, 0.000000f, 1.000000f, 0.000000f, -9.404798f, 160.741125f }, +{ -220.280746f, 20.966759f, -27.192787f, 0.000000f, 1.000000f, 0.000000f, -0.097693f, 163.132535f }, +{ -213.751633f, 20.966759f, -25.074295f, 0.000000f, 1.000000f, 0.000000f, 8.648710f, 163.441542f }, +{ -208.369156f, 20.966755f, -21.697281f, 0.000000f, 1.000000f, 0.000000f, 16.570136f, 161.742676f }, +{ -204.308121f, 20.966755f, -17.187607f, 0.000000f, 1.000000f, 0.000000f, 23.402251f, 158.110519f }, +{ -201.743317f, 20.966753f, -11.671119f, 0.000000f, 1.000000f, 0.000000f, 28.880766f, 152.619616f }, +{ -200.849533f, 20.966753f, -5.273689f, 0.000000f, 1.000000f, 0.000000f, 32.741376f, 145.344564f }, +{ -201.724655f, 20.966753f, 1.288060f, 0.000000f, 1.000000f, 0.000000f, 34.554308f, 137.101256f }, +{ -204.242859f, 20.966751f, 7.031769f, 0.000000f, 1.000000f, 0.000000f, 34.041921f, 129.121548f }, +{ -208.243301f, 20.966755f, 11.810632f, 0.000000f, 1.000000f, 0.000000f, 31.332898f, 121.651460f }, +{ -213.565170f, 20.966755f, 15.477799f, 0.000000f, 1.000000f, 0.000000f, 26.555888f, 114.937053f }, +{ -220.047684f, 20.966755f, 17.886444f, 0.000000f, 1.000000f, 0.000000f, 19.839494f, 109.224379f }, +{ -148.686584f, 20.966726f, 116.550392f, 0.000000f, 1.000000f, 0.000000f, 148.362750f, 22.133128f }, +{ -72.924095f, 20.966726f, 116.550392f, 0.000000f, 1.000000f, 0.000000f, 239.134392f, 55.171292f }, +{ -44.133286f, 20.966728f, 113.442566f, 0.000000f, 1.000000f, 0.000000f, 272.273660f, 71.449770f }, +{ -20.467419f, 20.966740f, 104.692406f, 0.000000f, 1.000000f, 0.000000f, 296.812196f, 92.253517f }, +{ -1.975434f, 20.966738f, 91.159897f, 0.000000f, 1.000000f, 0.000000f, 313.066387f, 116.530840f }, +{ 11.293716f, 20.966730f, 73.705025f, 0.000000f, 1.000000f, 0.000000f, 321.352617f, 143.230008f }, +{ 19.291100f, 20.966740f, 53.187733f, 0.000000f, 1.000000f, 0.000000f, 321.987274f, 171.299414f }, +{ 21.967770f, 20.966734f, 30.467978f, 0.000000f, 1.000000f, 0.000000f, 315.286714f, 199.687280f }, +{ 19.338877f, 20.966743f, 6.999154f, 0.000000f, 1.000000f, 0.000000f, 301.902798f, 226.659158f }, +{ 11.340330f, 20.966745f, -13.645118f, 0.000000f, 1.000000f, 0.000000f, 283.317205f, 247.905264f }, +{ -2.195676f, 20.966759f, -30.821503f, 0.000000f, 1.000000f, 0.000000f, 259.609396f, 262.581703f }, +{ -21.436935f, 20.966757f, -43.886719f, 0.000000f, 1.000000f, 0.000000f, 230.858877f, 269.844599f }, +{ -46.551262f, 20.966757f, -52.197571f, 0.000000f, 1.000000f, 0.000000f, 197.145034f, 268.850158f }, +{ -77.706444f, 20.966757f, -55.110794f, 0.000000f, 1.000000f, 0.000000f, 158.547374f, 258.754495f }, +{ -148.686584f, 20.966757f, -55.110794f, 0.000000f, 1.000000f, 0.000000f, 73.505490f, 227.801797f }, +{ -105.897141f, 20.966738f, 85.087578f, 0.000000f, 1.000000f, 0.000000f, 185.908961f, 78.488406f }, +{ -105.897141f, 20.966759f, -23.647980f, 0.000000f, 1.000000f, 0.000000f, 138.492035f, 208.765369f }, +{ -77.958153f, 20.966759f, -23.647980f, 0.000000f, 1.000000f, 0.000000f, 171.965959f, 220.948887f }, +{ -58.874207f, 20.966755f, -21.368675f, 0.000000f, 1.000000f, 0.000000f, 195.824544f, 226.540074f }, +{ -44.341877f, 20.966753f, -15.146018f, 0.000000f, 1.000000f, 0.000000f, 215.949404f, 225.421851f }, +{ -33.878738f, 20.966745f, -5.902946f, 0.000000f, 1.000000f, 0.000000f, 232.516059f, 218.910365f }, +{ -27.002363f, 20.966743f, 5.437653f, 0.000000f, 1.000000f, 0.000000f, 245.700045f, 208.321724f }, +{ -23.230320f, 20.966747f, 17.952866f, 0.000000f, 1.000000f, 0.000000f, 255.676941f, 194.972041f }, +{ -22.080179f, 20.966734f, 30.719679f, 0.000000f, 1.000000f, 0.000000f, 262.622269f, 180.177478f }, +{ -23.442402f, 20.966742f, 44.972439f, 0.000000f, 1.000000f, 0.000000f, 267.205431f, 162.507187f }, +{ -27.692215f, 20.966743f, 57.903660f, 0.000000f, 1.000000f, 0.000000f, 267.752663f, 145.160943f }, +{ -35.074326f, 20.966740f, 68.947144f, 0.000000f, 1.000000f, 0.000000f, 263.723906f, 128.710501f }, +{ -45.833443f, 20.966738f, 77.536499f, 0.000000f, 1.000000f, 0.000000f, 254.578922f, 113.727730f }, +{ -60.214287f, 20.966738f, 83.105423f, 0.000000f, 1.000000f, 0.000000f, 239.777591f, 100.784424f }, +{ -78.461555f, 20.966738f, 85.087578f, 0.000000f, 1.000000f, 0.000000f, 218.779751f, 90.452398f }, +{ 53.459190f, 21.106728f, -63.834198f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106720f, 19.696632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106720f, 19.696632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 34.431496f, 21.106718f, 37.767292f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106718f, 37.767292f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.459190f, 21.106716f, 52.887684f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 54.761124f, 21.106716f, 61.040321f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.744659f, 21.106709f, 68.629570f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 65.526382f, 21.106707f, 75.245590f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 75.222885f, 21.106714f, 80.478653f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 87.950760f, 21.106714f, 83.918983f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.826599f, 21.106714f, 85.156822f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.486267f, 21.106707f, 85.094505f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.371353f, 21.106707f, 84.904137f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 115.334160f, 21.106707f, 84.580589f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 119.227013f, 21.106707f, 84.118752f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 122.902229f, 21.106707f, 83.513496f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 126.212128f, 21.106707f, 82.759697f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 114.179916f, 21.106716f, 65.426567f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 112.235428f, 21.106709f, 65.933655f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 110.283180f, 21.106709f, 66.348541f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 108.268738f, 21.106709f, 66.671227f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.137703f, 21.106709f, 66.901718f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.835670f, 21.106709f, 67.040016f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 101.308228f, 21.106709f, 67.086113f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.838806f, 21.106709f, 66.577324f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 91.224388f, 21.106716f, 65.167046f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 87.527145f, 21.106716f, 63.029400f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 84.809280f, 21.106716f, 60.338608f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 83.132957f, 21.106716f, 57.268780f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106716f, 53.994068f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106718f, 37.767292f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106718f, 37.767292f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.661545f, 21.106720f, 19.696632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106720f, 19.696632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 82.560364f, 21.106728f, -63.834198f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 109.261765f, 21.106724f, -33.040283f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 158.509918f, 21.106720f, 10.661286f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 110.660858f, 21.106716f, 56.206806f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.037323f, 21.106716f, 56.206806f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 175.299042f, 21.106712f, 25.597252f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 203.001129f, 21.106716f, 56.206806f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 237.139038f, 21.106712f, 56.206806f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 189.569809f, 21.106720f, 11.767655f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 239.097778f, 21.106724f, -33.040283f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 202.161682f, 21.106724f, -33.040283f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.620132f, 21.106722f, -3.168342f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.679504f, 21.106724f, -33.040283f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 246.695496f, 21.106710f, 44.635105f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 246.695496f, 21.106709f, 54.095203f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 243.335144f, 21.106709f, 54.095203f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 243.335144f, 21.106712f, 56.104115f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 252.174316f, 21.106712f, 56.104115f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 252.174316f, 21.106709f, 54.095203f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 248.813965f, 21.106709f, 54.095203f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 248.813965f, 21.106710f, 44.635105f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 253.836212f, 21.106710f, 44.635105f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 253.836212f, 21.106712f, 56.341526f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 258.931549f, 21.106709f, 51.191425f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 264.026886f, 21.106712f, 56.341526f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 264.026886f, 21.106710f, 44.635105f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 261.908356f, 21.106710f, 44.635105f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 261.908356f, 21.106709f, 51.721058f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 258.931549f, 21.106709f, 48.634647f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 255.954681f, 21.106709f, 51.721058f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 255.954681f, 21.106710f, 44.635105f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.398365f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.398365f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.399651f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.399651f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 64.683319f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 64.683319f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -92.719193f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 71.361206f, 21.091311f, -90.693512f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 75.070610f, 21.091311f, -89.192642f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 78.221947f, 21.091311f, -90.116440f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 80.447113f, 21.091311f, -92.906815f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 81.069901f, 21.091311f, -95.010880f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 81.290161f, 21.091311f, -97.592255f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 81.290161f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.288872f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.288872f, 21.091311f, -97.720490f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 76.046646f, 21.091311f, -95.573685f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 74.507790f, 21.091311f, -93.751633f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 72.154381f, 21.091311f, -93.999207f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 70.869621f, 21.091311f, -95.136734f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091311f, -97.015182f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 69.684608f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.042702f, 21.091320f, -111.377853f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.042702f, 21.091320f, -116.315018f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 112.247803f, 21.091320f, -118.552063f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.574234f, 21.091320f, -118.394440f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 103.539482f, 21.091320f, -115.040665f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 102.209610f, 21.091320f, -112.118790f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 101.385559f, 21.091312f, -108.374054f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 101.102959f, 21.091311f, -103.811798f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 101.339844f, 21.091307f, -99.454666f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 102.036247f, 21.091311f, -95.777908f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 103.170799f, 21.091311f, -92.831406f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 104.722122f, 21.091311f, -90.665024f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.933678f, 21.091311f, -88.927628f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.632736f, 21.091311f, -89.470505f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 113.549179f, 21.091311f, -91.009354f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 114.952675f, 21.091311f, -93.103912f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.387047f, 21.091307f, -99.154861f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 116.619774f, 21.091309f, -104.965942f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.104248f, 21.091312f, -104.965942f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 106.676575f, 21.091320f, -110.009979f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 108.374535f, 21.091320f, -113.130447f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.169655f, 21.091320f, -114.199097f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 113.774490f, 21.091320f, -113.485764f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.040123f, 21.091307f, -101.247040f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.618484f, 21.091307f, -101.247040f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 111.312141f, 21.091311f, -96.746841f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 110.364601f, 21.091311f, -94.098953f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 108.733131f, 21.091311f, -93.232162f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 107.208519f, 21.091311f, -94.113205f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 106.325096f, 21.091311f, -96.775330f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 122.262253f, 21.091320f, -118.046234f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 122.262253f, 21.091311f, -89.641495f, -0.000003f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 127.263535f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.391785f, 21.091311f, -97.335770f, -0.000004f, 1.000000f, -0.000003f, 0.000000f, 255.000000f }, +{ 128.306671f, 21.091311f, -94.372635f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.111130f, 21.091311f, -92.203873f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.876404f, 21.091311f, -90.715469f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 131.574371f, 21.091311f, -89.323868f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 133.556717f, 21.091311f, -89.280518f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 135.214310f, 21.091311f, -90.026199f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 134.829590f, 21.091311f, -95.155716f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 132.649551f, 21.091311f, -94.450424f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 130.914764f, 21.091311f, -95.135239f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 129.543335f, 21.091311f, -96.915436f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 128.513855f, 21.091307f, -99.379562f, -0.000005f, 1.000000f, -0.000004f, 0.000000f, 255.000000f }, +{ 127.804985f, 21.091307f, -102.116196f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.395340f, 21.091309f, -104.713913f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 127.263535f, 21.091320f, -118.046234f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 155.668289f, 21.091312f, -112.788467f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 155.668289f, 21.091312f, -116.571503f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 154.127060f, 21.091320f, -117.804016f, 0.000001f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 152.305023f, 21.091320f, -118.637558f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 150.903000f, 21.091320f, -118.586197f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 149.472794f, 21.091320f, -117.781738f, 0.000003f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 148.448669f, 21.091320f, -116.186478f, 0.000012f, 1.000000f, 0.000005f, 0.000000f, 255.000000f }, +{ 148.102249f, 21.091320f, -115.096756f, 0.000003f, 1.000000f, 0.000003f, 0.000000f, 255.000000f }, +{ 146.276031f, 21.091320f, -117.172318f, 0.000001f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 142.652115f, 21.091320f, -118.815659f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 139.866501f, 21.091320f, -117.808762f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 137.850311f, 21.091320f, -115.206009f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 137.073761f, 21.091320f, -111.634323f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 138.144791f, 21.091309f, -107.571091f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 141.623840f, 21.091307f, -104.049286f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.391052f, 21.091307f, -102.166382f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091307f, -100.028778f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091311f, -97.335770f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.180527f, 21.091311f, -94.538589f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 145.869064f, 21.091311f, -93.718689f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.898575f, 21.091311f, -93.732040f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 141.682312f, 21.091311f, -94.706894f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 137.779068f, 21.091307f, -98.297562f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 137.779068f, 21.091311f, -92.526840f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 141.658264f, 21.091311f, -89.665527f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.054428f, 21.091311f, -88.951309f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.152328f, 21.091311f, -89.072128f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 150.474655f, 21.091311f, -90.715469f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.600082f, 21.091311f, -94.111420f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.911179f, 21.091311f, -96.502228f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 152.932556f, 21.091312f, -113.100754f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 153.103531f, 21.091312f, -113.846436f, 0.000002f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 153.680603f, 21.091312f, -114.199097f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 154.124680f, 21.091312f, -114.032852f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 154.796753f, 21.091312f, -113.553146f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091312f, -110.800781f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 147.909882f, 21.091307f, -103.491211f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 146.048050f, 21.091309f, -104.727585f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 144.556686f, 21.091309f, -105.944351f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 143.421539f, 21.091309f, -107.154007f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 142.628372f, 21.091309f, -108.369003f, 0.000003f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 142.162918f, 21.091312f, -109.601822f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 142.010925f, 21.091312f, -110.864899f, 0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 142.329147f, 21.091312f, -112.550995f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 143.188812f, 21.091320f, -113.667130f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 144.447449f, 21.091320f, -114.070847f, 0.000002f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 145.715591f, 21.091312f, -113.693268f, 0.000000f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 146.898224f, 21.091312f, -112.588989f, -0.000002f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 147.430771f, 21.091312f, -111.777710f, 0.000004f, 1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 173.749878f, 21.091312f, -112.467880f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.749878f, 21.091312f, -117.276810f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 172.085159f, 21.091312f, -118.160233f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 168.812698f, 21.091312f, -118.815659f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 166.009262f, 21.091312f, -118.315475f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 163.547806f, 21.091312f, -116.887344f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 161.503128f, 21.091312f, -114.639908f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 159.950012f, 21.091312f, -111.681839f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 158.963303f, 21.091309f, -108.121750f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 158.617767f, 21.091307f, -104.068283f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 159.531387f, 21.091311f, -96.903564f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 163.822617f, 21.091311f, -90.542206f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 169.115997f, 21.091311f, -88.872055f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.301041f, 21.091311f, -89.897964f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 173.301041f, 21.091311f, -95.027481f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 169.582138f, 21.091311f, -93.616867f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 166.473557f, 21.091311f, -94.882629f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 164.462112f, 21.091307f, -98.442429f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 163.747299f, 21.091307f, -103.940048f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 164.523849f, 21.091312f, -109.302292f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 166.711029f, 21.091312f, -112.812210f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 171.313354f, 21.091312f, -113.911743f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091312f, -113.301422f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091312f, -117.725632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 186.637802f, 21.091312f, -118.378708f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.602036f, 21.091312f, -118.792801f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 182.419891f, 21.091312f, -118.666061f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 181.128311f, 21.091312f, -118.195847f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 180.089645f, 21.091312f, -117.372986f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 179.323486f, 21.091312f, -116.165421f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.849426f, 21.091312f, -114.541061f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.687042f, 21.091312f, -112.467880f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.687042f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 175.416977f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 178.200211f, 21.091311f, -89.945450f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 180.755478f, 21.091311f, -86.238419f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.239502f, 21.091309f, -82.331909f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091309f, -82.331909f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 188.369019f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.688324f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 183.847443f, 21.091312f, -112.446503f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.081055f, 21.091312f, -113.181198f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 184.972198f, 21.091312f, -113.977341f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 186.488205f, 21.091312f, -113.985367f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 192.280289f, 21.091312f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 192.280289f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.281570f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.281570f, 21.091312f, -118.046234f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 209.400085f, 21.091312f, -118.687424f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 200.872238f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 205.873535f, 21.091311f, -89.641495f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.041275f, 21.091309f, -105.863617f, 0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.169510f, 21.091309f, -105.863617f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 214.337250f, 21.091311f, -89.641495f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 219.338531f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 210.810699f, 21.091312f, -118.687424f, -0.000001f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 196.095139f, 9.401914f, -83.842834f, 0.000000f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 197.530334f, 9.401917f, -82.099869f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 197.312714f, 9.401917f, -79.852554f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 195.569748f, 9.401917f, -78.417358f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 193.322433f, 9.401917f, -78.634979f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 191.887238f, 9.401917f, -80.377945f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 192.104858f, 9.401917f, -82.625259f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 193.847824f, 9.401914f, -84.060455f, 0.000000f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 196.095139f, 21.005835f, -83.842834f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.530334f, 21.005833f, -82.099869f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 197.312714f, 21.005833f, -79.852554f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 195.569748f, 21.005836f, -78.417358f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 193.322433f, 21.005836f, -78.634979f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 191.887238f, 21.005833f, -80.377945f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 192.104858f, 21.005835f, -82.625259f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 193.847824f, 21.005835f, -84.060455f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 194.708786f, 21.005833f, -81.238907f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 194.708786f, 9.401917f, -81.238907f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 57.212021f, 9.401914f, -83.842834f, 0.000000f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 58.647217f, 9.401917f, -82.099869f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 58.429596f, 9.401917f, -79.852554f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 56.686630f, 9.401917f, -78.417358f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 54.439316f, 9.401917f, -78.634979f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.004120f, 9.401917f, -80.377945f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 53.221741f, 9.401917f, -82.625259f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 54.964706f, 9.401914f, -84.060455f, 0.000000f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 57.212021f, 21.005835f, -83.842834f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.647217f, 21.005833f, -82.099869f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 58.429596f, 21.005833f, -79.852554f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 56.686630f, 21.005836f, -78.417358f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 54.439316f, 21.005836f, -78.634979f, 0.000000f, 1.000000f, -0.000002f, 0.000000f, 255.000000f }, +{ 53.004120f, 21.005833f, -80.377945f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 53.221741f, 21.005835f, -82.625259f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 54.964706f, 21.005835f, -84.060455f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 55.825668f, 21.005833f, -81.238907f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 55.825668f, 9.401917f, -81.238907f, 0.000000f, -1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484123f, -113.301437f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484123f, -117.725662f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.979660f, 9.484123f, -118.792831f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 92.633392f, 9.484123f, -118.666077f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 90.303146f, 9.484123f, -117.373001f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 89.062927f, 9.484123f, -114.541092f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.900543f, 9.484123f, -112.467911f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.900543f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 85.630478f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.413712f, 9.484118f, -89.945480f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 90.968979f, 9.484117f, -86.238449f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.453003f, 9.484117f, -82.331924f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484117f, -82.331924f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484118f, -89.641510f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 9.484118f, -94.001602f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 94.060944f, 9.484123f, -112.446518f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.185699f, 9.484123f, -113.977371f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 96.701706f, 9.484123f, -113.985397f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091312f, -113.301422f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091312f, -117.725632f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.979660f, 21.091312f, -118.792801f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 92.633392f, 21.091312f, -118.666061f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 90.303146f, 21.091312f, -117.372986f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 89.062927f, 21.091312f, -114.541061f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.900543f, 21.091312f, -112.467880f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.900543f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 85.630478f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 88.413712f, 21.091311f, -89.945450f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 90.968979f, 21.091311f, -86.238419f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.453003f, 21.091309f, -82.331909f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091309f, -82.331909f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091311f, -89.641495f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 98.582520f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 93.901825f, 21.091311f, -94.001587f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 94.047279f, 21.091312f, -112.455856f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 95.185699f, 21.091312f, -113.977341f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 96.701706f, 21.091312f, -113.985367f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 236.900940f, 9.484123f, -111.377884f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 236.900940f, 9.484123f, -116.315048f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 233.106049f, 9.484123f, -118.552078f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.432480f, 9.484123f, -118.394455f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 224.397736f, 9.484123f, -115.040680f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 223.067856f, 9.484123f, -112.118805f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 222.243805f, 9.484118f, -108.374069f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 221.961212f, 9.484118f, -103.811813f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 222.198090f, 9.484118f, -99.454697f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 222.894501f, 9.484118f, -95.777939f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 224.029053f, 9.484106f, -92.831436f, 0.000002f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 225.580368f, 9.484118f, -90.665039f, -0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.791931f, 9.484118f, -88.927658f, 0.000000f, -1.000000f, 0.000003f, 0.000000f, 255.000000f }, +{ 232.490982f, 9.484118f, -89.470520f, 0.000001f, -1.000000f, 0.000002f, 0.000000f, 255.000000f }, +{ 234.407425f, 9.484118f, -91.009384f, 0.000001f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 235.810913f, 9.484106f, -93.103928f, -0.000002f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 237.245300f, 9.484118f, -99.154877f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 237.478027f, 9.484118f, -104.965958f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 226.962494f, 9.484118f, -104.965958f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 227.534821f, 9.484123f, -110.009995f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 229.232788f, 9.484123f, -113.130463f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.027893f, 9.484123f, -114.199112f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 234.632736f, 9.484123f, -113.485794f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 226.898376f, 9.484118f, -101.247055f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.476730f, 9.484118f, -101.247055f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.170380f, 9.484118f, -96.746857f, -0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 231.222839f, 9.484118f, -94.098984f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 229.591370f, 9.484106f, -93.232178f, 0.000000f, -1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.066772f, 9.484118f, -94.113220f, 0.000000f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 227.183350f, 9.484118f, -96.775345f, 0.000001f, -1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 236.900940f, 21.091320f, -111.377853f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 236.900940f, 21.091320f, -116.315018f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 233.106049f, 21.091320f, -118.552063f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.432480f, 21.091320f, -118.394440f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 224.397736f, 21.091320f, -115.040665f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 223.067856f, 21.091320f, -112.118790f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 222.243805f, 21.091312f, -108.374054f, -0.000001f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 221.961212f, 21.091311f, -103.811798f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 222.198090f, 21.091307f, -99.454666f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 222.894501f, 21.091311f, -95.777908f, 0.000000f, 1.000000f, -0.000001f, 0.000000f, 255.000000f }, +{ 224.029053f, 21.091311f, -92.831406f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 225.580368f, 21.091311f, -90.665024f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.791931f, 21.091311f, -88.927628f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.490982f, 21.091311f, -89.470505f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 234.407425f, 21.091311f, -91.009354f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 235.810913f, 21.091311f, -93.103912f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 237.245300f, 21.091307f, -99.154861f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 237.478027f, 21.091309f, -104.965942f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 226.962494f, 21.091312f, -104.965942f, 0.000000f, 1.000000f, 0.000001f, 0.000000f, 255.000000f }, +{ 227.534821f, 21.091320f, -110.009979f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 229.232788f, 21.091320f, -113.130447f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.027893f, 21.091320f, -114.199097f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 234.632736f, 21.091320f, -113.485764f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 226.898376f, 21.091307f, -101.247040f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.476730f, 21.091307f, -101.247040f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 232.170380f, 21.091311f, -96.746841f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 231.222839f, 21.091311f, -94.098953f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 229.591370f, 21.091311f, -93.232162f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 228.066772f, 21.091311f, -94.113205f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f }, +{ 227.183350f, 21.091311f, -96.775330f, 0.000000f, 1.000000f, 0.000000f, 0.000000f, 255.000000f } +}; + +static Face face_1[] = { +{ 1, 2, 350, 0, 4 }, +{ 1, 350, 349, 0, 3 }, +{ 2, 3, 351, 0, 4 }, +{ 2, 351, 350, 0, 2 }, +{ 3, 4, 352, 0, 4 }, +{ 3, 352, 351, 0, 2 }, +{ 4, 5, 353, 0, 4 }, +{ 4, 353, 352, 0, 2 }, +{ 5, 6, 354, 0, 4 }, +{ 5, 354, 353, 0, 2 }, +{ 6, 7, 355, 0, 4 }, +{ 6, 355, 354, 0, 2 }, +{ 7, 8, 356, 0, 4 }, +{ 7, 356, 355, 0, 2 }, +{ 8, 9, 357, 0, 4 }, +{ 8, 357, 356, 0, 2 }, +{ 9, 10, 358, 0, 4 }, +{ 9, 358, 357, 0, 2 }, +{ 10, 11, 359, 0, 4 }, +{ 10, 359, 358, 0, 2 }, +{ 11, 12, 360, 0, 4 }, +{ 11, 360, 359, 0, 2 }, +{ 12, 13, 361, 0, 4 }, +{ 12, 361, 360, 0, 2 }, +{ 13, 14, 362, 0, 4 }, +{ 13, 362, 361, 0, 2 }, +{ 14, 15, 363, 0, 4 }, +{ 14, 363, 362, 0, 2 }, +{ 15, 16, 364, 0, 4 }, +{ 15, 364, 363, 0, 2 }, +{ 16, 17, 365, 0, 4 }, +{ 16, 365, 364, 0, 2 }, +{ 17, 18, 366, 0, 4 }, +{ 17, 366, 365, 0, 2 }, +{ 18, 19, 367, 0, 6 }, +{ 18, 367, 366, 0, 2 }, +{ 20, 21, 369, 0, 4 }, +{ 20, 369, 368, 0, 3 }, +{ 21, 22, 370, 0, 4 }, +{ 21, 370, 369, 0, 2 }, +{ 22, 23, 371, 0, 4 }, +{ 22, 371, 370, 0, 2 }, +{ 23, 24, 372, 0, 4 }, +{ 23, 372, 371, 0, 2 }, +{ 24, 25, 373, 0, 4 }, +{ 24, 373, 372, 0, 2 }, +{ 25, 26, 374, 0, 4 }, +{ 25, 374, 373, 0, 2 }, +{ 26, 27, 375, 0, 4 }, +{ 26, 375, 374, 0, 2 }, +{ 27, 28, 376, 0, 4 }, +{ 27, 376, 375, 0, 2 }, +{ 28, 29, 377, 0, 4 }, +{ 28, 377, 376, 0, 2 }, +{ 29, 30, 378, 0, 4 }, +{ 29, 378, 377, 0, 2 }, +{ 30, 31, 379, 0, 4 }, +{ 30, 379, 378, 0, 2 }, +{ 31, 32, 380, 0, 4 }, +{ 31, 380, 379, 0, 2 }, +{ 32, 33, 381, 0, 4 }, +{ 32, 381, 380, 0, 2 }, +{ 33, 34, 382, 0, 4 }, +{ 33, 382, 381, 0, 2 }, +{ 34, 35, 383, 0, 4 }, +{ 34, 383, 382, 0, 2 }, +{ 35, 36, 384, 0, 4 }, +{ 35, 384, 383, 0, 2 }, +{ 36, 37, 385, 0, 4 }, +{ 36, 385, 384, 0, 2 }, +{ 37, 38, 386, 0, 4 }, +{ 37, 386, 385, 0, 2 }, +{ 38, 39, 387, 0, 4 }, +{ 38, 387, 386, 0, 2 }, +{ 39, 40, 388, 0, 4 }, +{ 39, 388, 387, 0, 2 }, +{ 40, 41, 389, 0, 4 }, +{ 40, 389, 388, 0, 2 }, +{ 41, 42, 390, 0, 4 }, +{ 41, 390, 389, 0, 2 }, +{ 42, 43, 391, 0, 4 }, +{ 42, 391, 390, 0, 2 }, +{ 43, 44, 392, 0, 4 }, +{ 43, 392, 391, 0, 2 }, +{ 44, 45, 393, 0, 4 }, +{ 44, 393, 392, 0, 2 }, +{ 45, 46, 394, 0, 4 }, +{ 45, 394, 393, 0, 2 }, +{ 46, 47, 395, 0, 4 }, +{ 46, 395, 394, 0, 2 }, +{ 47, 48, 396, 0, 4 }, +{ 47, 396, 395, 0, 2 }, +{ 48, 49, 397, 0, 4 }, +{ 48, 397, 396, 0, 2 }, +{ 49, 50, 398, 0, 4 }, +{ 49, 398, 397, 0, 2 }, +{ 50, 51, 399, 0, 4 }, +{ 50, 399, 398, 0, 2 }, +{ 51, 52, 400, 0, 4 }, +{ 51, 400, 399, 0, 2 }, +{ 52, 53, 401, 0, 4 }, +{ 52, 401, 400, 0, 2 }, +{ 53, 54, 402, 0, 4 }, +{ 53, 402, 401, 0, 2 }, +{ 54, 55, 403, 0, 4 }, +{ 54, 403, 402, 0, 2 }, +{ 55, 56, 404, 0, 6 }, +{ 55, 404, 403, 0, 2 }, +{ 57, 58, 406, 0, 4 }, +{ 57, 406, 405, 0, 3 }, +{ 58, 59, 407, 0, 4 }, +{ 58, 407, 406, 0, 2 }, +{ 59, 60, 408, 0, 4 }, +{ 59, 408, 407, 0, 2 }, +{ 60, 61, 409, 0, 4 }, +{ 60, 409, 408, 0, 2 }, +{ 61, 62, 410, 0, 4 }, +{ 61, 410, 409, 0, 2 }, +{ 62, 63, 411, 0, 4 }, +{ 62, 411, 410, 0, 2 }, +{ 63, 64, 412, 0, 4 }, +{ 63, 412, 411, 0, 2 }, +{ 64, 65, 413, 0, 4 }, +{ 64, 413, 412, 0, 2 }, +{ 65, 66, 414, 0, 4 }, +{ 65, 414, 413, 0, 2 }, +{ 66, 67, 415, 0, 4 }, +{ 66, 415, 414, 0, 2 }, +{ 67, 68, 416, 0, 4 }, +{ 67, 416, 415, 0, 2 }, +{ 68, 69, 417, 0, 4 }, +{ 68, 417, 416, 0, 2 }, +{ 69, 70, 418, 0, 4 }, +{ 69, 418, 417, 0, 2 }, +{ 70, 71, 419, 0, 4 }, +{ 70, 419, 418, 0, 2 }, +{ 71, 72, 420, 0, 4 }, +{ 71, 420, 419, 0, 2 }, +{ 72, 73, 421, 0, 4 }, +{ 72, 421, 420, 0, 2 }, +{ 73, 74, 422, 0, 4 }, +{ 73, 422, 421, 0, 2 }, +{ 74, 0, 348, 0, 6 }, +{ 74, 348, 422, 0, 2 }, +{ 75, 76, 424, 0, 4 }, +{ 75, 424, 423, 0, 3 }, +{ 76, 77, 425, 0, 4 }, +{ 76, 425, 424, 0, 2 }, +{ 77, 78, 426, 0, 4 }, +{ 77, 426, 425, 0, 2 }, +{ 78, 79, 427, 0, 4 }, +{ 78, 427, 426, 0, 2 }, +{ 79, 80, 428, 0, 4 }, +{ 79, 428, 427, 0, 2 }, +{ 80, 81, 429, 0, 4 }, +{ 80, 429, 428, 0, 2 }, +{ 81, 82, 430, 0, 4 }, +{ 81, 430, 429, 0, 2 }, +{ 82, 83, 431, 0, 4 }, +{ 82, 431, 430, 0, 2 }, +{ 83, 84, 432, 0, 4 }, +{ 83, 432, 431, 0, 2 }, +{ 84, 85, 433, 0, 4 }, +{ 84, 433, 432, 0, 2 }, +{ 85, 86, 434, 0, 4 }, +{ 85, 434, 433, 0, 2 }, +{ 86, 87, 435, 0, 4 }, +{ 86, 435, 434, 0, 2 }, +{ 87, 88, 436, 0, 4 }, +{ 87, 436, 435, 0, 2 }, +{ 88, 89, 437, 0, 6 }, +{ 88, 437, 436, 0, 2 }, +{ 90, 91, 439, 0, 4 }, +{ 90, 439, 438, 0, 2 }, +{ 91, 92, 440, 0, 4 }, +{ 91, 440, 439, 0, 2 }, +{ 92, 93, 441, 0, 4 }, +{ 92, 441, 440, 0, 2 }, +{ 93, 94, 442, 0, 4 }, +{ 93, 442, 441, 0, 2 }, +{ 94, 95, 443, 0, 4 }, +{ 94, 443, 442, 0, 2 }, +{ 95, 96, 444, 0, 4 }, +{ 95, 444, 443, 0, 2 }, +{ 96, 97, 445, 0, 4 }, +{ 96, 445, 444, 0, 2 }, +{ 97, 98, 446, 0, 4 }, +{ 97, 446, 445, 0, 2 }, +{ 98, 99, 447, 0, 4 }, +{ 98, 447, 446, 0, 2 }, +{ 99, 100, 448, 0, 4 }, +{ 99, 448, 447, 0, 2 }, +{ 100, 101, 449, 0, 4 }, +{ 100, 449, 448, 0, 2 }, +{ 101, 102, 450, 0, 4 }, +{ 101, 450, 449, 0, 2 }, +{ 102, 103, 451, 0, 4 }, +{ 102, 451, 450, 0, 2 }, +{ 103, 104, 452, 0, 4 }, +{ 103, 452, 451, 0, 2 }, +{ 104, 90, 438, 0, 4 }, +{ 104, 438, 452, 0, 2 }, +{ 106, 107, 455, 1, 6 }, +{ 106, 455, 454, 1, 3 }, +{ 108, 109, 457, 1, 4 }, +{ 108, 457, 456, 1, 3 }, +{ 109, 110, 458, 1, 4 }, +{ 109, 458, 457, 1, 2 }, +{ 110, 111, 459, 1, 4 }, +{ 110, 459, 458, 1, 2 }, +{ 111, 112, 460, 1, 4 }, +{ 111, 460, 459, 1, 2 }, +{ 112, 113, 461, 1, 4 }, +{ 112, 461, 460, 1, 2 }, +{ 113, 114, 462, 1, 4 }, +{ 113, 462, 461, 1, 2 }, +{ 114, 115, 463, 1, 4 }, +{ 114, 463, 462, 1, 2 }, +{ 115, 116, 464, 1, 4 }, +{ 115, 464, 463, 1, 2 }, +{ 116, 117, 465, 1, 4 }, +{ 116, 465, 464, 1, 2 }, +{ 117, 118, 466, 1, 4 }, +{ 117, 466, 465, 1, 2 }, +{ 118, 119, 467, 1, 4 }, +{ 118, 467, 466, 1, 2 }, +{ 119, 120, 468, 1, 4 }, +{ 119, 468, 467, 1, 2 }, +{ 120, 121, 469, 1, 4 }, +{ 120, 469, 468, 1, 2 }, +{ 121, 122, 470, 1, 4 }, +{ 121, 470, 469, 1, 2 }, +{ 122, 123, 471, 1, 4 }, +{ 122, 471, 470, 1, 2 }, +{ 123, 124, 472, 1, 4 }, +{ 123, 472, 471, 1, 2 }, +{ 124, 125, 473, 1, 4 }, +{ 124, 473, 472, 1, 2 }, +{ 125, 126, 474, 1, 4 }, +{ 125, 474, 473, 1, 2 }, +{ 126, 127, 475, 1, 4 }, +{ 126, 475, 474, 1, 2 }, +{ 127, 128, 476, 1, 4 }, +{ 127, 476, 475, 1, 2 }, +{ 128, 129, 477, 1, 4 }, +{ 128, 477, 476, 1, 2 }, +{ 129, 130, 478, 1, 4 }, +{ 129, 478, 477, 1, 2 }, +{ 130, 131, 479, 1, 4 }, +{ 130, 479, 478, 1, 2 }, +{ 131, 132, 480, 1, 4 }, +{ 131, 480, 479, 1, 2 }, +{ 132, 133, 481, 1, 4 }, +{ 132, 481, 480, 1, 2 }, +{ 133, 134, 482, 1, 4 }, +{ 133, 482, 481, 1, 2 }, +{ 134, 135, 483, 1, 4 }, +{ 134, 483, 482, 1, 2 }, +{ 135, 136, 484, 1, 4 }, +{ 135, 484, 483, 1, 2 }, +{ 136, 137, 485, 1, 6 }, +{ 136, 485, 484, 1, 2 }, +{ 138, 139, 487, 1, 6 }, +{ 138, 487, 486, 1, 3 }, +{ 140, 105, 453, 1, 6 }, +{ 140, 453, 488, 1, 3 }, +{ 141, 142, 490, 1, 4 }, +{ 141, 490, 489, 1, 2 }, +{ 142, 143, 491, 1, 4 }, +{ 142, 491, 490, 1, 2 }, +{ 143, 144, 492, 1, 4 }, +{ 143, 492, 491, 1, 2 }, +{ 144, 145, 493, 1, 4 }, +{ 144, 493, 492, 1, 2 }, +{ 145, 146, 494, 1, 4 }, +{ 145, 494, 493, 1, 2 }, +{ 146, 147, 495, 1, 4 }, +{ 146, 495, 494, 1, 2 }, +{ 147, 148, 496, 1, 4 }, +{ 147, 496, 495, 1, 2 }, +{ 148, 149, 497, 1, 4 }, +{ 148, 497, 496, 1, 2 }, +{ 149, 150, 498, 1, 4 }, +{ 149, 498, 497, 1, 2 }, +{ 150, 151, 499, 1, 4 }, +{ 150, 499, 498, 1, 2 }, +{ 151, 152, 500, 1, 4 }, +{ 151, 500, 499, 1, 2 }, +{ 152, 141, 489, 1, 4 }, +{ 152, 489, 500, 1, 2 }, +{ 153, 154, 502, 1, 4 }, +{ 153, 502, 501, 1, 2 }, +{ 154, 155, 503, 1, 4 }, +{ 154, 503, 502, 1, 2 }, +{ 155, 156, 504, 1, 4 }, +{ 155, 504, 503, 1, 2 }, +{ 156, 157, 505, 1, 4 }, +{ 156, 505, 504, 1, 2 }, +{ 157, 158, 506, 1, 4 }, +{ 157, 506, 505, 1, 2 }, +{ 158, 159, 507, 1, 4 }, +{ 158, 507, 506, 1, 2 }, +{ 159, 160, 508, 1, 4 }, +{ 159, 508, 507, 1, 2 }, +{ 160, 153, 501, 1, 4 }, +{ 160, 501, 508, 1, 2 }, +{ 161, 162, 510, 1, 4 }, +{ 161, 510, 509, 1, 2 }, +{ 162, 163, 511, 1, 4 }, +{ 162, 511, 510, 1, 2 }, +{ 163, 164, 512, 1, 4 }, +{ 163, 512, 511, 1, 2 }, +{ 164, 165, 513, 1, 4 }, +{ 164, 513, 512, 1, 2 }, +{ 165, 166, 514, 1, 4 }, +{ 165, 514, 513, 1, 2 }, +{ 166, 167, 515, 1, 4 }, +{ 166, 515, 514, 1, 2 }, +{ 167, 168, 516, 1, 4 }, +{ 167, 516, 515, 1, 2 }, +{ 168, 169, 517, 1, 4 }, +{ 168, 517, 516, 1, 2 }, +{ 169, 170, 518, 1, 4 }, +{ 169, 518, 517, 1, 2 }, +{ 170, 161, 509, 1, 4 }, +{ 170, 509, 518, 1, 2 }, +{ 171, 172, 520, 1, 4 }, +{ 171, 520, 519, 1, 2 }, +{ 172, 173, 521, 1, 4 }, +{ 172, 521, 520, 1, 2 }, +{ 173, 174, 522, 1, 4 }, +{ 173, 522, 521, 1, 2 }, +{ 174, 171, 519, 1, 4 }, +{ 174, 519, 522, 1, 2 }, +{ 175, 176, 524, 1, 4 }, +{ 175, 524, 523, 1, 2 }, +{ 176, 177, 525, 1, 4 }, +{ 176, 525, 524, 1, 2 }, +{ 177, 178, 526, 1, 4 }, +{ 177, 526, 525, 1, 2 }, +{ 178, 179, 527, 1, 4 }, +{ 178, 527, 526, 1, 2 }, +{ 179, 180, 528, 1, 4 }, +{ 179, 528, 527, 1, 2 }, +{ 180, 181, 529, 1, 4 }, +{ 180, 529, 528, 1, 2 }, +{ 181, 182, 530, 1, 4 }, +{ 181, 530, 529, 1, 2 }, +{ 182, 183, 531, 1, 4 }, +{ 182, 531, 530, 1, 2 }, +{ 183, 184, 532, 1, 4 }, +{ 183, 532, 531, 1, 2 }, +{ 184, 185, 533, 1, 4 }, +{ 184, 533, 532, 1, 2 }, +{ 185, 186, 534, 1, 4 }, +{ 185, 534, 533, 1, 2 }, +{ 186, 187, 535, 1, 4 }, +{ 186, 535, 534, 1, 2 }, +{ 187, 188, 536, 1, 4 }, +{ 187, 536, 535, 1, 2 }, +{ 188, 189, 537, 1, 4 }, +{ 188, 537, 536, 1, 2 }, +{ 189, 190, 538, 1, 4 }, +{ 189, 538, 537, 1, 2 }, +{ 190, 191, 539, 1, 4 }, +{ 190, 539, 538, 1, 2 }, +{ 191, 192, 540, 1, 4 }, +{ 191, 540, 539, 1, 2 }, +{ 192, 193, 541, 1, 4 }, +{ 192, 541, 540, 1, 2 }, +{ 193, 175, 523, 1, 4 }, +{ 193, 523, 541, 1, 2 }, +{ 194, 195, 543, 1, 4 }, +{ 194, 543, 542, 1, 2 }, +{ 195, 196, 544, 1, 4 }, +{ 195, 544, 543, 1, 2 }, +{ 196, 197, 545, 1, 4 }, +{ 196, 545, 544, 1, 2 }, +{ 197, 198, 546, 1, 4 }, +{ 197, 546, 545, 1, 2 }, +{ 198, 199, 547, 1, 4 }, +{ 198, 547, 546, 1, 2 }, +{ 199, 200, 548, 1, 4 }, +{ 199, 548, 547, 1, 2 }, +{ 200, 201, 549, 1, 4 }, +{ 200, 549, 548, 1, 2 }, +{ 201, 202, 550, 1, 4 }, +{ 201, 550, 549, 1, 2 }, +{ 202, 203, 551, 1, 4 }, +{ 202, 551, 550, 1, 2 }, +{ 203, 204, 552, 1, 4 }, +{ 203, 552, 551, 1, 2 }, +{ 204, 205, 553, 1, 4 }, +{ 204, 553, 552, 1, 2 }, +{ 205, 206, 554, 1, 4 }, +{ 205, 554, 553, 1, 2 }, +{ 206, 207, 555, 1, 4 }, +{ 206, 555, 554, 1, 2 }, +{ 207, 208, 556, 1, 4 }, +{ 207, 556, 555, 1, 2 }, +{ 208, 209, 557, 1, 4 }, +{ 208, 557, 556, 1, 2 }, +{ 209, 210, 558, 1, 4 }, +{ 209, 558, 557, 1, 2 }, +{ 210, 211, 559, 1, 4 }, +{ 210, 559, 558, 1, 2 }, +{ 211, 212, 560, 1, 4 }, +{ 211, 560, 559, 1, 2 }, +{ 212, 213, 561, 1, 4 }, +{ 212, 561, 560, 1, 2 }, +{ 213, 214, 562, 1, 4 }, +{ 213, 562, 561, 1, 2 }, +{ 214, 215, 563, 1, 4 }, +{ 214, 563, 562, 1, 2 }, +{ 215, 216, 564, 1, 4 }, +{ 215, 564, 563, 1, 2 }, +{ 216, 194, 542, 1, 4 }, +{ 216, 542, 564, 1, 2 }, +{ 217, 218, 566, 1, 4 }, +{ 217, 566, 565, 1, 2 }, +{ 218, 219, 567, 1, 4 }, +{ 218, 567, 566, 1, 2 }, +{ 219, 220, 568, 1, 4 }, +{ 219, 568, 567, 1, 2 }, +{ 220, 221, 569, 1, 4 }, +{ 220, 569, 568, 1, 2 }, +{ 221, 222, 570, 1, 4 }, +{ 221, 570, 569, 1, 2 }, +{ 222, 223, 571, 1, 4 }, +{ 222, 571, 570, 1, 2 }, +{ 223, 217, 565, 1, 4 }, +{ 223, 565, 571, 1, 2 }, +{ 224, 225, 573, 1, 4 }, +{ 224, 573, 572, 1, 2 }, +{ 225, 226, 574, 1, 4 }, +{ 225, 574, 573, 1, 2 }, +{ 226, 227, 575, 1, 4 }, +{ 226, 575, 574, 1, 2 }, +{ 227, 228, 576, 1, 4 }, +{ 227, 576, 575, 1, 2 }, +{ 228, 229, 577, 1, 4 }, +{ 228, 577, 576, 1, 2 }, +{ 229, 230, 578, 1, 4 }, +{ 229, 578, 577, 1, 2 }, +{ 230, 231, 579, 1, 4 }, +{ 230, 579, 578, 1, 2 }, +{ 231, 232, 580, 1, 4 }, +{ 231, 580, 579, 1, 2 }, +{ 232, 233, 581, 1, 4 }, +{ 232, 581, 580, 1, 2 }, +{ 233, 234, 582, 1, 4 }, +{ 233, 582, 581, 1, 2 }, +{ 234, 235, 583, 1, 4 }, +{ 234, 583, 582, 1, 2 }, +{ 235, 236, 584, 1, 4 }, +{ 235, 584, 583, 1, 2 }, +{ 236, 237, 585, 1, 4 }, +{ 236, 585, 584, 1, 2 }, +{ 237, 238, 586, 1, 4 }, +{ 237, 586, 585, 1, 2 }, +{ 238, 239, 587, 1, 4 }, +{ 238, 587, 586, 1, 2 }, +{ 239, 240, 588, 1, 4 }, +{ 239, 588, 587, 1, 2 }, +{ 240, 241, 589, 1, 4 }, +{ 240, 589, 588, 1, 2 }, +{ 241, 224, 572, 1, 4 }, +{ 241, 572, 589, 1, 2 }, +{ 242, 243, 591, 1, 4 }, +{ 242, 591, 590, 1, 2 }, +{ 243, 244, 592, 1, 4 }, +{ 243, 592, 591, 1, 2 }, +{ 244, 245, 593, 1, 4 }, +{ 244, 593, 592, 1, 2 }, +{ 245, 246, 594, 1, 4 }, +{ 245, 594, 593, 1, 2 }, +{ 246, 247, 595, 1, 4 }, +{ 246, 595, 594, 1, 2 }, +{ 247, 248, 596, 1, 4 }, +{ 247, 596, 595, 1, 2 }, +{ 248, 249, 597, 1, 4 }, +{ 248, 597, 596, 1, 2 }, +{ 249, 250, 598, 1, 4 }, +{ 249, 598, 597, 1, 2 }, +{ 250, 251, 599, 1, 4 }, +{ 250, 599, 598, 1, 2 }, +{ 251, 252, 600, 1, 4 }, +{ 251, 600, 599, 1, 2 }, +{ 252, 253, 601, 1, 4 }, +{ 252, 601, 600, 1, 2 }, +{ 253, 254, 602, 1, 4 }, +{ 253, 602, 601, 1, 2 }, +{ 254, 255, 603, 1, 4 }, +{ 254, 603, 602, 1, 2 }, +{ 255, 256, 604, 1, 4 }, +{ 255, 604, 603, 1, 2 }, +{ 256, 257, 605, 1, 4 }, +{ 256, 605, 604, 1, 2 }, +{ 257, 258, 606, 1, 4 }, +{ 257, 606, 605, 1, 2 }, +{ 258, 259, 607, 1, 4 }, +{ 258, 607, 606, 1, 2 }, +{ 259, 260, 608, 1, 4 }, +{ 259, 608, 607, 1, 2 }, +{ 260, 261, 609, 1, 4 }, +{ 260, 609, 608, 1, 2 }, +{ 261, 262, 610, 1, 4 }, +{ 261, 610, 609, 1, 2 }, +{ 262, 263, 611, 1, 4 }, +{ 262, 611, 610, 1, 2 }, +{ 263, 264, 611, 1, 4 }, +{ 264, 612, 611, 1, 2 }, +{ 264, 265, 613, 1, 4 }, +{ 264, 613, 612, 1, 2 }, +{ 265, 266, 614, 1, 4 }, +{ 265, 614, 613, 1, 2 }, +{ 266, 267, 615, 1, 4 }, +{ 266, 615, 614, 1, 2 }, +{ 267, 268, 616, 1, 4 }, +{ 267, 616, 615, 1, 2 }, +{ 268, 269, 617, 1, 4 }, +{ 268, 617, 616, 1, 2 }, +{ 269, 270, 618, 1, 4 }, +{ 269, 618, 617, 1, 2 }, +{ 270, 271, 619, 1, 4 }, +{ 270, 619, 618, 1, 2 }, +{ 271, 272, 620, 1, 4 }, +{ 271, 620, 619, 1, 2 }, +{ 272, 273, 621, 1, 4 }, +{ 272, 621, 620, 1, 2 }, +{ 273, 274, 622, 1, 4 }, +{ 273, 622, 621, 1, 2 }, +{ 274, 275, 623, 1, 4 }, +{ 274, 623, 622, 1, 2 }, +{ 275, 276, 624, 1, 4 }, +{ 275, 624, 623, 1, 2 }, +{ 276, 242, 590, 1, 4 }, +{ 276, 590, 624, 1, 2 }, +{ 277, 278, 626, 1, 4 }, +{ 277, 626, 625, 1, 2 }, +{ 278, 279, 627, 1, 4 }, +{ 278, 627, 626, 1, 2 }, +{ 279, 280, 628, 1, 4 }, +{ 279, 628, 627, 1, 2 }, +{ 280, 281, 629, 1, 4 }, +{ 280, 629, 628, 1, 2 }, +{ 281, 630, 629, 1, 2 }, +{ 281, 282, 631, 1, 4 }, +{ 281, 631, 630, 1, 2 }, +{ 282, 632, 631, 1, 2 }, +{ 282, 283, 633, 1, 4 }, +{ 282, 633, 632, 1, 2 }, +{ 283, 284, 634, 1, 4 }, +{ 283, 634, 633, 1, 2 }, +{ 284, 285, 635, 1, 4 }, +{ 284, 635, 634, 1, 2 }, +{ 285, 286, 636, 1, 4 }, +{ 285, 636, 635, 1, 2 }, +{ 286, 287, 637, 1, 4 }, +{ 286, 637, 636, 1, 2 }, +{ 287, 288, 638, 1, 4 }, +{ 287, 638, 637, 1, 2 }, +{ 288, 277, 625, 1, 4 }, +{ 288, 625, 638, 1, 2 }, +{ 289, 290, 640, 1, 4 }, +{ 289, 640, 639, 1, 2 }, +{ 290, 291, 641, 1, 4 }, +{ 290, 641, 640, 1, 2 }, +{ 291, 292, 642, 1, 4 }, +{ 291, 642, 641, 1, 2 }, +{ 292, 293, 643, 1, 4 }, +{ 292, 643, 642, 1, 2 }, +{ 293, 294, 644, 1, 4 }, +{ 293, 644, 643, 1, 2 }, +{ 294, 295, 645, 1, 4 }, +{ 294, 645, 644, 1, 2 }, +{ 295, 296, 646, 1, 4 }, +{ 295, 646, 645, 1, 2 }, +{ 296, 297, 647, 1, 4 }, +{ 296, 647, 646, 1, 2 }, +{ 297, 298, 648, 1, 4 }, +{ 297, 648, 647, 1, 2 }, +{ 298, 299, 649, 1, 4 }, +{ 298, 649, 648, 1, 2 }, +{ 299, 300, 650, 1, 4 }, +{ 299, 650, 649, 1, 2 }, +{ 300, 301, 651, 1, 4 }, +{ 300, 651, 650, 1, 2 }, +{ 301, 302, 652, 1, 4 }, +{ 301, 652, 651, 1, 2 }, +{ 302, 303, 653, 1, 4 }, +{ 302, 653, 652, 1, 2 }, +{ 303, 304, 654, 1, 4 }, +{ 303, 654, 653, 1, 2 }, +{ 304, 305, 655, 1, 4 }, +{ 304, 655, 654, 1, 2 }, +{ 305, 306, 656, 1, 4 }, +{ 305, 656, 655, 1, 2 }, +{ 306, 307, 657, 1, 4 }, +{ 306, 657, 656, 1, 2 }, +{ 307, 308, 658, 1, 4 }, +{ 307, 658, 657, 1, 2 }, +{ 308, 309, 659, 1, 4 }, +{ 308, 659, 658, 1, 2 }, +{ 309, 310, 660, 1, 4 }, +{ 309, 660, 659, 1, 2 }, +{ 310, 289, 639, 1, 4 }, +{ 310, 639, 660, 1, 2 }, +{ 311, 312, 662, 1, 4 }, +{ 311, 662, 661, 1, 2 }, +{ 312, 313, 663, 1, 4 }, +{ 312, 663, 662, 1, 2 }, +{ 313, 314, 664, 1, 4 }, +{ 313, 664, 663, 1, 2 }, +{ 314, 315, 665, 1, 4 }, +{ 314, 665, 664, 1, 2 }, +{ 315, 316, 666, 1, 4 }, +{ 315, 666, 665, 1, 2 }, +{ 316, 317, 667, 1, 4 }, +{ 316, 667, 666, 1, 2 }, +{ 317, 318, 668, 1, 4 }, +{ 317, 668, 667, 1, 2 }, +{ 318, 319, 669, 1, 4 }, +{ 318, 669, 668, 1, 2 }, +{ 319, 320, 670, 1, 4 }, +{ 319, 670, 669, 1, 2 }, +{ 320, 321, 671, 1, 4 }, +{ 320, 671, 670, 1, 2 }, +{ 321, 322, 672, 1, 4 }, +{ 321, 672, 671, 1, 2 }, +{ 322, 323, 673, 1, 4 }, +{ 322, 673, 672, 1, 2 }, +{ 323, 324, 674, 1, 4 }, +{ 323, 674, 673, 1, 2 }, +{ 324, 325, 675, 1, 4 }, +{ 324, 675, 674, 1, 2 }, +{ 325, 326, 676, 1, 4 }, +{ 325, 676, 675, 1, 2 }, +{ 326, 327, 677, 1, 4 }, +{ 326, 677, 676, 1, 2 }, +{ 327, 328, 678, 1, 4 }, +{ 327, 678, 677, 1, 2 }, +{ 328, 329, 679, 1, 4 }, +{ 328, 679, 678, 1, 2 }, +{ 329, 330, 680, 1, 4 }, +{ 329, 680, 679, 1, 2 }, +{ 330, 331, 681, 1, 4 }, +{ 330, 681, 680, 1, 2 }, +{ 331, 332, 681, 1, 4 }, +{ 332, 682, 681, 1, 2 }, +{ 332, 333, 683, 1, 4 }, +{ 332, 683, 682, 1, 2 }, +{ 333, 334, 683, 1, 4 }, +{ 334, 335, 684, 1, 4 }, +{ 334, 684, 683, 1, 2 }, +{ 335, 311, 661, 1, 4 }, +{ 335, 661, 684, 1, 2 }, +{ 336, 337, 686, 1, 4 }, +{ 336, 686, 685, 1, 2 }, +{ 337, 338, 687, 1, 4 }, +{ 337, 687, 686, 1, 2 }, +{ 338, 339, 688, 1, 4 }, +{ 338, 688, 687, 1, 2 }, +{ 339, 336, 685, 1, 4 }, +{ 339, 685, 688, 1, 2 }, +{ 340, 341, 690, 1, 4 }, +{ 340, 690, 689, 1, 2 }, +{ 341, 342, 691, 1, 4 }, +{ 341, 691, 690, 1, 2 }, +{ 342, 343, 692, 1, 4 }, +{ 342, 692, 691, 1, 2 }, +{ 343, 344, 693, 1, 4 }, +{ 343, 693, 692, 1, 2 }, +{ 344, 345, 694, 1, 4 }, +{ 344, 694, 693, 1, 2 }, +{ 345, 346, 695, 1, 4 }, +{ 345, 695, 694, 1, 2 }, +{ 346, 347, 696, 1, 4 }, +{ 346, 696, 695, 1, 2 }, +{ 347, 340, 689, 1, 4 }, +{ 347, 689, 696, 1, 2 }, +{ 706, 698, 697, 1, 2 }, +{ 705, 706, 697, 1, 4 }, +{ 707, 699, 698, 1, 2 }, +{ 706, 707, 698, 1, 4 }, +{ 708, 700, 699, 1, 2 }, +{ 707, 708, 699, 1, 4 }, +{ 709, 701, 700, 1, 2 }, +{ 708, 709, 700, 1, 4 }, +{ 710, 702, 701, 1, 2 }, +{ 709, 710, 701, 1, 4 }, +{ 711, 703, 702, 1, 2 }, +{ 710, 711, 702, 1, 4 }, +{ 712, 704, 703, 1, 2 }, +{ 711, 712, 703, 1, 4 }, +{ 705, 697, 704, 1, 2 }, +{ 712, 705, 704, 1, 4 }, +{ 722, 714, 713, 1, 2 }, +{ 721, 722, 713, 1, 4 }, +{ 723, 715, 714, 1, 2 }, +{ 722, 723, 714, 1, 4 }, +{ 724, 716, 715, 1, 2 }, +{ 723, 724, 715, 1, 4 }, +{ 725, 717, 716, 1, 2 }, +{ 724, 725, 716, 1, 4 }, +{ 726, 718, 717, 1, 2 }, +{ 725, 726, 717, 1, 4 }, +{ 727, 719, 718, 1, 2 }, +{ 726, 727, 718, 1, 4 }, +{ 728, 720, 719, 1, 2 }, +{ 727, 728, 719, 1, 4 }, +{ 721, 713, 720, 1, 2 }, +{ 728, 721, 720, 1, 4 }, +{ 729, 730, 750, 1, 4 }, +{ 729, 750, 749, 1, 2 }, +{ 730, 731, 751, 1, 4 }, +{ 730, 751, 750, 1, 2 }, +{ 731, 732, 752, 1, 4 }, +{ 731, 752, 751, 1, 2 }, +{ 732, 733, 753, 1, 4 }, +{ 732, 753, 752, 1, 2 }, +{ 733, 734, 754, 1, 4 }, +{ 733, 754, 753, 1, 2 }, +{ 734, 735, 755, 1, 4 }, +{ 734, 755, 754, 1, 2 }, +{ 735, 736, 756, 1, 4 }, +{ 735, 756, 755, 1, 2 }, +{ 736, 737, 757, 1, 4 }, +{ 736, 757, 756, 1, 2 }, +{ 737, 738, 758, 1, 4 }, +{ 737, 758, 757, 1, 2 }, +{ 738, 739, 759, 1, 4 }, +{ 738, 759, 758, 1, 2 }, +{ 739, 740, 760, 1, 4 }, +{ 739, 760, 759, 1, 2 }, +{ 740, 741, 761, 1, 4 }, +{ 740, 761, 760, 1, 2 }, +{ 741, 742, 762, 1, 4 }, +{ 741, 762, 761, 1, 2 }, +{ 742, 743, 763, 1, 4 }, +{ 742, 763, 762, 1, 2 }, +{ 743, 744, 764, 1, 4 }, +{ 743, 764, 763, 1, 2 }, +{ 744, 745, 765, 1, 4 }, +{ 744, 765, 764, 1, 2 }, +{ 745, 746, 766, 1, 4 }, +{ 745, 766, 765, 1, 2 }, +{ 746, 747, 767, 1, 4 }, +{ 746, 767, 766, 1, 2 }, +{ 747, 748, 768, 1, 4 }, +{ 747, 768, 767, 1, 2 }, +{ 748, 729, 749, 1, 4 }, +{ 748, 749, 768, 1, 2 }, +{ 769, 770, 800, 1, 4 }, +{ 769, 800, 799, 1, 2 }, +{ 770, 771, 801, 1, 4 }, +{ 770, 801, 800, 1, 2 }, +{ 771, 772, 802, 1, 4 }, +{ 771, 802, 801, 1, 2 }, +{ 772, 773, 803, 1, 4 }, +{ 772, 803, 802, 1, 2 }, +{ 773, 774, 804, 1, 4 }, +{ 773, 804, 803, 1, 2 }, +{ 774, 775, 805, 1, 4 }, +{ 774, 805, 804, 1, 2 }, +{ 775, 776, 806, 1, 4 }, +{ 775, 806, 805, 1, 2 }, +{ 776, 777, 807, 1, 4 }, +{ 776, 807, 806, 1, 2 }, +{ 777, 778, 808, 1, 4 }, +{ 777, 808, 807, 1, 2 }, +{ 778, 779, 809, 1, 4 }, +{ 778, 809, 808, 1, 2 }, +{ 779, 780, 810, 1, 4 }, +{ 779, 810, 809, 1, 2 }, +{ 780, 781, 811, 1, 4 }, +{ 780, 811, 810, 1, 2 }, +{ 781, 782, 812, 1, 4 }, +{ 781, 812, 811, 1, 2 }, +{ 782, 783, 813, 1, 4 }, +{ 782, 813, 812, 1, 2 }, +{ 783, 784, 814, 1, 4 }, +{ 783, 814, 813, 1, 2 }, +{ 784, 785, 815, 1, 4 }, +{ 784, 815, 814, 1, 2 }, +{ 785, 786, 816, 1, 4 }, +{ 785, 816, 815, 1, 2 }, +{ 786, 787, 817, 1, 4 }, +{ 786, 817, 816, 1, 2 }, +{ 787, 788, 818, 1, 4 }, +{ 787, 818, 817, 1, 2 }, +{ 788, 789, 819, 1, 4 }, +{ 788, 819, 818, 1, 2 }, +{ 789, 790, 820, 1, 4 }, +{ 789, 820, 819, 1, 2 }, +{ 790, 791, 821, 1, 4 }, +{ 790, 821, 820, 1, 2 }, +{ 791, 769, 799, 1, 4 }, +{ 791, 799, 821, 1, 2 }, +{ 792, 793, 823, 1, 4 }, +{ 792, 823, 822, 1, 2 }, +{ 793, 794, 824, 1, 4 }, +{ 793, 824, 823, 1, 2 }, +{ 794, 795, 825, 1, 4 }, +{ 794, 825, 824, 1, 2 }, +{ 795, 796, 826, 1, 4 }, +{ 795, 826, 825, 1, 2 }, +{ 796, 797, 827, 1, 4 }, +{ 796, 827, 826, 1, 2 }, +{ 797, 798, 828, 1, 4 }, +{ 797, 828, 827, 1, 2 }, +{ 798, 792, 822, 1, 4 }, +{ 798, 822, 828, 1, 2 }, +{ 829, 830, 846, 0, 6 }, +{ 829, 846, 845, 0, 3 }, +{ 831, 832, 848, 0, 6 }, +{ 831, 848, 847, 0, 3 }, +{ 833, 834, 850, 0, 6 }, +{ 833, 850, 849, 0, 3 }, +{ 836, 835, 851, 0, 6 }, +{ 836, 851, 852, 0, 3 }, +{ 837, 838, 854, 1, 6 }, +{ 837, 854, 853, 1, 3 }, +{ 839, 840, 856, 1, 6 }, +{ 839, 856, 855, 1, 3 }, +{ 841, 842, 858, 1, 6 }, +{ 841, 858, 857, 1, 3 }, +{ 843, 844, 860, 1, 6 }, +{ 843, 860, 859, 1, 3 }, +{ 919, 918, 917, 0, 6 }, +{ 881, 880, 879, 0, 6 }, +{ 920, 919, 917, 0, 4 }, +{ 881, 879, 878, 0, 2 }, +{ 882, 881, 878, 0, 4 }, +{ 882, 878, 877, 0, 2 }, +{ 883, 882, 877, 0, 4 }, +{ 883, 877, 876, 0, 2 }, +{ 884, 883, 876, 0, 4 }, +{ 920, 917, 916, 0, 2 }, +{ 921, 920, 916, 0, 4 }, +{ 921, 916, 915, 0, 2 }, +{ 922, 921, 915, 0, 4 }, +{ 922, 915, 914, 0, 2 }, +{ 884, 876, 875, 0, 2 }, +{ 885, 884, 875, 0, 4 }, +{ 923, 922, 914, 0, 4 }, +{ 923, 914, 913, 0, 2 }, +{ 885, 875, 874, 0, 2 }, +{ 886, 885, 874, 0, 4 }, +{ 923, 913, 912, 0, 2 }, +{ 924, 923, 912, 0, 4 }, +{ 924, 912, 911, 0, 2 }, +{ 925, 924, 911, 0, 4 }, +{ 925, 911, 910, 0, 2 }, +{ 926, 925, 910, 0, 4 }, +{ 926, 910, 909, 0, 2 }, +{ 927, 926, 909, 0, 4 }, +{ 927, 909, 908, 0, 2 }, +{ 928, 927, 908, 0, 4 }, +{ 928, 908, 907, 0, 2 }, +{ 929, 928, 907, 0, 4 }, +{ 929, 907, 906, 0, 2 }, +{ 929, 906, 905, 0, 2 }, +{ 930, 929, 905, 0, 4 }, +{ 930, 905, 904, 0, 2 }, +{ 930, 904, 903, 0, 2 }, +{ 931, 930, 903, 0, 4 }, +{ 931, 903, 902, 0, 2 }, +{ 931, 902, 901, 0, 2 }, +{ 932, 931, 901, 0, 4 }, +{ 932, 901, 900, 0, 2 }, +{ 932, 900, 899, 0, 2 }, +{ 933, 932, 899, 0, 4 }, +{ 934, 933, 899, 0, 4 }, +{ 887, 886, 874, 0, 4 }, +{ 887, 874, 873, 0, 2 }, +{ 888, 887, 873, 0, 4 }, +{ 888, 873, 872, 0, 2 }, +{ 889, 888, 872, 0, 4 }, +{ 889, 872, 871, 0, 2 }, +{ 890, 889, 871, 0, 4 }, +{ 890, 871, 870, 0, 2 }, +{ 891, 890, 870, 0, 4 }, +{ 892, 891, 870, 0, 4 }, +{ 892, 870, 869, 0, 2 }, +{ 893, 892, 869, 0, 4 }, +{ 894, 893, 869, 0, 4 }, +{ 894, 869, 868, 0, 2 }, +{ 895, 894, 868, 0, 4 }, +{ 896, 895, 868, 0, 4 }, +{ 896, 868, 867, 0, 2 }, +{ 897, 896, 867, 0, 4 }, +{ 898, 897, 867, 0, 4 }, +{ 898, 867, 866, 0, 2 }, +{ 899, 898, 866, 0, 4 }, +{ 899, 866, 865, 0, 2 }, +{ 934, 899, 865, 0, 0 }, +{ 934, 865, 864, 0, 2 }, +{ 935, 934, 864, 0, 4 }, +{ 935, 864, 863, 0, 2 }, +{ 861, 935, 863, 0, 4 }, +{ 862, 861, 863, 0, 5 }, +{ 959, 943, 942, 0, 2 }, +{ 960, 959, 942, 0, 4 }, +{ 960, 942, 941, 0, 2 }, +{ 961, 960, 941, 0, 4 }, +{ 961, 941, 940, 0, 2 }, +{ 962, 961, 940, 0, 4 }, +{ 962, 940, 939, 0, 2 }, +{ 963, 962, 939, 0, 4 }, +{ 963, 939, 938, 0, 2 }, +{ 964, 963, 938, 0, 4 }, +{ 964, 938, 937, 0, 2 }, +{ 965, 964, 937, 0, 4 }, +{ 937, 936, 951, 0, 4 }, +{ 951, 965, 937, 0, 4 }, +{ 951, 936, 950, 0, 2 }, +{ 952, 951, 950, 0, 4 }, +{ 952, 950, 949, 0, 2 }, +{ 953, 952, 949, 0, 4 }, +{ 944, 943, 959, 0, 4 }, +{ 944, 959, 958, 0, 2 }, +{ 945, 944, 958, 0, 4 }, +{ 945, 958, 957, 0, 2 }, +{ 946, 945, 957, 0, 4 }, +{ 946, 957, 956, 0, 2 }, +{ 947, 946, 956, 0, 4 }, +{ 947, 956, 955, 0, 2 }, +{ 948, 947, 955, 0, 4 }, +{ 948, 955, 954, 0, 2 }, +{ 949, 948, 954, 0, 4 }, +{ 953, 949, 954, 0, 1 }, +{ 984, 983, 982, 1, 6 }, +{ 984, 982, 981, 1, 2 }, +{ 984, 981, 980, 1, 2 }, +{ 985, 984, 980, 1, 4 }, +{ 985, 980, 979, 1, 2 }, +{ 986, 985, 979, 1, 4 }, +{ 987, 986, 979, 1, 4 }, +{ 987, 979, 978, 1, 2 }, +{ 988, 987, 978, 1, 4 }, +{ 988, 978, 977, 1, 2 }, +{ 989, 988, 977, 1, 4 }, +{ 989, 977, 976, 1, 2 }, +{ 990, 989, 976, 1, 4 }, +{ 991, 990, 976, 1, 4 }, +{ 992, 991, 976, 1, 4 }, +{ 992, 976, 975, 1, 2 }, +{ 993, 992, 975, 1, 4 }, +{ 966, 1001, 1000, 1, 6 }, +{ 967, 966, 1000, 1, 4 }, +{ 1000, 999, 998, 1, 6 }, +{ 1000, 998, 997, 1, 2 }, +{ 967, 1000, 997, 1, 0 }, +{ 970, 969, 968, 1, 6 }, +{ 970, 968, 967, 1, 2 }, +{ 970, 967, 997, 1, 0 }, +{ 970, 997, 996, 1, 2 }, +{ 971, 970, 996, 1, 4 }, +{ 972, 971, 996, 1, 4 }, +{ 973, 972, 996, 1, 4 }, +{ 973, 996, 995, 1, 2 }, +{ 974, 973, 995, 1, 4 }, +{ 974, 995, 994, 1, 2 }, +{ 975, 974, 994, 1, 4 }, +{ 993, 975, 994, 1, 1 }, +{ 1003, 1002, 1013, 1, 6 }, +{ 1003, 1013, 1012, 1, 2 }, +{ 1011, 1010, 1009, 1, 6 }, +{ 1012, 1011, 1009, 1, 4 }, +{ 1009, 1008, 1007, 1, 6 }, +{ 1009, 1007, 1006, 1, 2 }, +{ 1005, 1004, 1003, 1, 6 }, +{ 1006, 1005, 1003, 1, 4 }, +{ 1006, 1003, 1012, 1, 0 }, +{ 1006, 1012, 1009, 1, 0 }, +{ 1014, 1021, 1020, 1, 6 }, +{ 1015, 1014, 1020, 1, 4 }, +{ 1020, 1019, 1018, 1, 6 }, +{ 1020, 1018, 1017, 1, 2 }, +{ 1015, 1020, 1017, 1, 0 }, +{ 1016, 1015, 1017, 1, 5 }, +{ 1022, 1031, 1030, 1, 6 }, +{ 1023, 1022, 1030, 1, 4 }, +{ 1024, 1023, 1030, 1, 4 }, +{ 1024, 1030, 1029, 1, 2 }, +{ 1024, 1029, 1028, 1, 2 }, +{ 1025, 1024, 1028, 1, 4 }, +{ 1026, 1025, 1028, 1, 4 }, +{ 1026, 1028, 1027, 1, 3 }, +{ 1032, 1035, 1034, 1, 6 }, +{ 1033, 1032, 1034, 1, 5 }, +{ 1036, 1054, 1053, 1, 6 }, +{ 1037, 1036, 1053, 1, 4 }, +{ 1053, 1052, 1039, 1, 4 }, +{ 1048, 1047, 1046, 1, 6 }, +{ 1048, 1046, 1045, 1, 2 }, +{ 1048, 1045, 1044, 1, 2 }, +{ 1049, 1048, 1044, 1, 4 }, +{ 1049, 1044, 1043, 1, 2 }, +{ 1050, 1049, 1043, 1, 4 }, +{ 1050, 1043, 1042, 1, 2 }, +{ 1050, 1042, 1041, 1, 2 }, +{ 1050, 1041, 1040, 1, 2 }, +{ 1051, 1050, 1040, 1, 4 }, +{ 1051, 1040, 1039, 1, 2 }, +{ 1039, 1038, 1037, 1, 6 }, +{ 1039, 1037, 1053, 1, 0 }, +{ 1051, 1039, 1052, 1, 1 }, +{ 1063, 1062, 1078, 1, 4 }, +{ 1064, 1063, 1078, 1, 4 }, +{ 1064, 1078, 1084, 1, 2 }, +{ 1056, 1055, 1077, 1, 6 }, +{ 1065, 1064, 1084, 1, 4 }, +{ 1065, 1084, 1083, 1, 2 }, +{ 1066, 1065, 1083, 1, 4 }, +{ 1066, 1083, 1082, 1, 2 }, +{ 1067, 1066, 1082, 1, 4 }, +{ 1068, 1067, 1082, 1, 4 }, +{ 1069, 1068, 1082, 1, 4 }, +{ 1069, 1082, 1081, 1, 2 }, +{ 1070, 1069, 1081, 1, 4 }, +{ 1070, 1081, 1080, 1, 2 }, +{ 1071, 1070, 1080, 1, 4 }, +{ 1071, 1080, 1079, 1, 2 }, +{ 1072, 1071, 1079, 1, 4 }, +{ 1073, 1072, 1079, 1, 4 }, +{ 1073, 1079, 1078, 1, 2 }, +{ 1073, 1078, 1062, 1, 0 }, +{ 1073, 1062, 1061, 1, 2 }, +{ 1073, 1061, 1060, 1, 2 }, +{ 1074, 1073, 1060, 1, 4 }, +{ 1074, 1060, 1059, 1, 2 }, +{ 1075, 1074, 1059, 1, 4 }, +{ 1075, 1059, 1058, 1, 2 }, +{ 1076, 1075, 1058, 1, 4 }, +{ 1076, 1058, 1057, 1, 2 }, +{ 1076, 1057, 1056, 1, 2 }, +{ 1077, 1076, 1056, 1, 4 }, +{ 1085, 1102, 1101, 1, 6 }, +{ 1086, 1085, 1101, 1, 4 }, +{ 1086, 1101, 1100, 1, 2 }, +{ 1100, 1099, 1088, 1, 4 }, +{ 1088, 1087, 1086, 1, 6 }, +{ 1088, 1086, 1100, 1, 0 }, +{ 1088, 1099, 1098, 1, 2 }, +{ 1089, 1088, 1098, 1, 4 }, +{ 1089, 1098, 1097, 1, 2 }, +{ 1090, 1089, 1097, 1, 4 }, +{ 1096, 1095, 1094, 1, 6 }, +{ 1090, 1097, 1096, 1, 2 }, +{ 1091, 1090, 1096, 1, 4 }, +{ 1096, 1094, 1093, 1, 2 }, +{ 1092, 1091, 1096, 1, 4 }, +{ 1093, 1092, 1096, 1, 4 }, +{ 1133, 1149, 1148, 1, 2 }, +{ 1107, 1106, 1133, 1, 4 }, +{ 1108, 1107, 1133, 1, 4 }, +{ 1109, 1108, 1133, 1, 4 }, +{ 1110, 1109, 1133, 1, 4 }, +{ 1148, 1110, 1133, 1, 0 }, +{ 1104, 1103, 1137, 1, 6 }, +{ 1104, 1137, 1136, 1, 2 }, +{ 1126, 1125, 1124, 1, 6 }, +{ 1127, 1126, 1124, 1, 4 }, +{ 1127, 1124, 1123, 1, 2 }, +{ 1128, 1127, 1123, 1, 4 }, +{ 1128, 1123, 1122, 1, 2 }, +{ 1129, 1128, 1122, 1, 4 }, +{ 1130, 1129, 1122, 1, 4 }, +{ 1130, 1122, 1121, 1, 2 }, +{ 1131, 1130, 1121, 1, 4 }, +{ 1132, 1131, 1121, 1, 4 }, +{ 1132, 1121, 1120, 1, 2 }, +{ 1132, 1120, 1119, 1, 2 }, +{ 1132, 1119, 1139, 1, 0 }, +{ 1104, 1136, 1135, 1, 2 }, +{ 1110, 1148, 1147, 1, 2 }, +{ 1111, 1110, 1147, 1, 4 }, +{ 1111, 1147, 1146, 1, 2 }, +{ 1105, 1104, 1135, 1, 4 }, +{ 1112, 1111, 1146, 1, 4 }, +{ 1112, 1146, 1145, 1, 2 }, +{ 1113, 1112, 1145, 1, 4 }, +{ 1113, 1145, 1144, 1, 2 }, +{ 1114, 1113, 1144, 1, 4 }, +{ 1115, 1114, 1144, 1, 4 }, +{ 1115, 1144, 1143, 1, 2 }, +{ 1116, 1115, 1143, 1, 4 }, +{ 1117, 1116, 1143, 1, 4 }, +{ 1117, 1143, 1142, 1, 2 }, +{ 1117, 1142, 1141, 1, 2 }, +{ 1118, 1117, 1141, 1, 4 }, +{ 1118, 1141, 1140, 1, 2 }, +{ 1119, 1118, 1140, 1, 4 }, +{ 1119, 1140, 1139, 1, 2 }, +{ 1132, 1139, 1138, 1, 2 }, +{ 1138, 1133, 1132, 1, 2 }, +{ 1133, 1138, 1149, 1, 2 }, +{ 1134, 1133, 1106, 1, 4 }, +{ 1135, 1134, 1106, 1, 4 }, +{ 1135, 1106, 1105, 1, 2 }, +{ 1163, 1165, 1164, 1, 3 }, +{ 1165, 1163, 1162, 1, 2 }, +{ 1151, 1150, 1171, 1, 6 }, +{ 1165, 1162, 1161, 1, 2 }, +{ 1166, 1165, 1161, 1, 4 }, +{ 1166, 1161, 1160, 1, 2 }, +{ 1167, 1166, 1160, 1, 4 }, +{ 1167, 1160, 1159, 1, 2 }, +{ 1168, 1167, 1159, 1, 4 }, +{ 1168, 1159, 1158, 1, 2 }, +{ 1169, 1168, 1158, 1, 4 }, +{ 1169, 1158, 1157, 1, 2 }, +{ 1170, 1169, 1157, 1, 4 }, +{ 1170, 1157, 1156, 1, 2 }, +{ 1170, 1156, 1155, 1, 2 }, +{ 1170, 1155, 1154, 1, 2 }, +{ 1170, 1154, 1153, 1, 2 }, +{ 1171, 1170, 1153, 1, 4 }, +{ 1171, 1153, 1152, 1, 2 }, +{ 1171, 1152, 1151, 1, 2 }, +{ 1191, 1190, 1189, 1, 6 }, +{ 1191, 1189, 1188, 1, 2 }, +{ 1188, 1187, 1186, 1, 6 }, +{ 1188, 1186, 1185, 1, 2 }, +{ 1184, 1183, 1182, 1, 6 }, +{ 1173, 1172, 1196, 1, 6 }, +{ 1174, 1173, 1196, 1, 4 }, +{ 1175, 1174, 1196, 1, 4 }, +{ 1175, 1196, 1195, 1, 2 }, +{ 1176, 1175, 1195, 1, 4 }, +{ 1176, 1195, 1194, 1, 2 }, +{ 1177, 1176, 1194, 1, 4 }, +{ 1178, 1177, 1194, 1, 4 }, +{ 1179, 1178, 1194, 1, 4 }, +{ 1179, 1194, 1193, 1, 2 }, +{ 1180, 1179, 1193, 1, 4 }, +{ 1181, 1180, 1193, 1, 4 }, +{ 1181, 1193, 1192, 1, 2 }, +{ 1182, 1181, 1192, 1, 4 }, +{ 1182, 1192, 1191, 1, 2 }, +{ 1182, 1191, 1188, 1, 0 }, +{ 1182, 1188, 1185, 1, 0 }, +{ 1182, 1185, 1184, 1, 2 }, +{ 1197, 1200, 1199, 1, 6 }, +{ 1198, 1197, 1199, 1, 5 }, +{ 1203, 1202, 1201, 1, 6 }, +{ 1204, 1203, 1201, 1, 4 }, +{ 1208, 1207, 1206, 1, 6 }, +{ 1208, 1206, 1205, 1, 2 }, +{ 1201, 1208, 1205, 1, 4 }, +{ 1204, 1201, 1205, 1, 1 }, +{ 1265, 1266, 1267, 0, 6 }, +{ 1227, 1228, 1229, 0, 6 }, +{ 1265, 1267, 1268, 0, 2 }, +{ 1226, 1227, 1229, 0, 4 }, +{ 1226, 1229, 1230, 0, 2 }, +{ 1225, 1226, 1230, 0, 4 }, +{ 1225, 1230, 1231, 0, 2 }, +{ 1224, 1225, 1231, 0, 4 }, +{ 1224, 1231, 1232, 0, 2 }, +{ 1264, 1265, 1268, 0, 4 }, +{ 1264, 1268, 1269, 0, 2 }, +{ 1263, 1264, 1269, 0, 4 }, +{ 1263, 1269, 1270, 0, 2 }, +{ 1262, 1263, 1270, 0, 4 }, +{ 1223, 1224, 1232, 0, 4 }, +{ 1223, 1232, 1233, 0, 2 }, +{ 1262, 1270, 1271, 0, 2 }, +{ 1261, 1262, 1271, 0, 4 }, +{ 1222, 1223, 1233, 0, 4 }, +{ 1222, 1233, 1234, 0, 2 }, +{ 1260, 1261, 1271, 0, 4 }, +{ 1260, 1271, 1272, 0, 2 }, +{ 1259, 1260, 1272, 0, 4 }, +{ 1259, 1272, 1273, 0, 2 }, +{ 1258, 1259, 1273, 0, 4 }, +{ 1258, 1273, 1274, 0, 2 }, +{ 1257, 1258, 1274, 0, 4 }, +{ 1257, 1274, 1275, 0, 2 }, +{ 1256, 1257, 1275, 0, 4 }, +{ 1256, 1275, 1276, 0, 2 }, +{ 1255, 1256, 1276, 0, 4 }, +{ 1255, 1276, 1277, 0, 2 }, +{ 1254, 1255, 1277, 0, 4 }, +{ 1253, 1254, 1277, 0, 4 }, +{ 1253, 1277, 1278, 0, 2 }, +{ 1252, 1253, 1278, 0, 4 }, +{ 1251, 1252, 1278, 0, 4 }, +{ 1251, 1278, 1279, 0, 2 }, +{ 1250, 1251, 1279, 0, 4 }, +{ 1249, 1250, 1279, 0, 4 }, +{ 1249, 1279, 1280, 0, 2 }, +{ 1248, 1249, 1280, 0, 4 }, +{ 1247, 1248, 1280, 0, 4 }, +{ 1247, 1280, 1281, 0, 2 }, +{ 1247, 1281, 1282, 0, 2 }, +{ 1222, 1234, 1235, 0, 2 }, +{ 1221, 1222, 1235, 0, 4 }, +{ 1221, 1235, 1236, 0, 2 }, +{ 1220, 1221, 1236, 0, 4 }, +{ 1220, 1236, 1237, 0, 2 }, +{ 1219, 1220, 1237, 0, 4 }, +{ 1219, 1237, 1238, 0, 2 }, +{ 1218, 1219, 1238, 0, 4 }, +{ 1218, 1238, 1239, 0, 2 }, +{ 1218, 1239, 1240, 0, 2 }, +{ 1217, 1218, 1240, 0, 4 }, +{ 1217, 1240, 1241, 0, 2 }, +{ 1217, 1241, 1242, 0, 2 }, +{ 1216, 1217, 1242, 0, 4 }, +{ 1216, 1242, 1243, 0, 2 }, +{ 1216, 1243, 1244, 0, 2 }, +{ 1215, 1216, 1244, 0, 4 }, +{ 1215, 1244, 1245, 0, 2 }, +{ 1215, 1245, 1246, 0, 2 }, +{ 1214, 1215, 1246, 0, 4 }, +{ 1214, 1246, 1247, 0, 2 }, +{ 1213, 1214, 1247, 0, 4 }, +{ 1213, 1247, 1282, 0, 0 }, +{ 1212, 1213, 1282, 0, 4 }, +{ 1212, 1282, 1283, 0, 2 }, +{ 1211, 1212, 1283, 0, 4 }, +{ 1211, 1283, 1209, 0, 2 }, +{ 1211, 1209, 1210, 0, 3 }, +{ 1290, 1291, 1307, 0, 4 }, +{ 1290, 1307, 1308, 0, 2 }, +{ 1289, 1290, 1308, 0, 4 }, +{ 1289, 1308, 1309, 0, 2 }, +{ 1288, 1289, 1309, 0, 4 }, +{ 1288, 1309, 1310, 0, 2 }, +{ 1287, 1288, 1310, 0, 4 }, +{ 1287, 1310, 1311, 0, 2 }, +{ 1286, 1287, 1311, 0, 4 }, +{ 1286, 1311, 1312, 0, 2 }, +{ 1285, 1286, 1312, 0, 4 }, +{ 1285, 1312, 1313, 0, 2 }, +{ 1284, 1285, 1313, 0, 4 }, +{ 1284, 1313, 1299, 0, 2 }, +{ 1298, 1284, 1299, 0, 4 }, +{ 1298, 1299, 1300, 0, 2 }, +{ 1297, 1298, 1300, 0, 4 }, +{ 1297, 1300, 1301, 0, 2 }, +{ 1307, 1291, 1292, 0, 2 }, +{ 1306, 1307, 1292, 0, 4 }, +{ 1306, 1292, 1293, 0, 2 }, +{ 1305, 1306, 1293, 0, 4 }, +{ 1305, 1293, 1294, 0, 2 }, +{ 1304, 1305, 1294, 0, 4 }, +{ 1304, 1294, 1295, 0, 2 }, +{ 1303, 1304, 1295, 0, 4 }, +{ 1303, 1295, 1296, 0, 2 }, +{ 1302, 1303, 1296, 0, 4 }, +{ 1302, 1296, 1297, 0, 2 }, +{ 1302, 1297, 1301, 0, 1 }, +{ 1330, 1331, 1332, 1, 6 }, +{ 1329, 1330, 1332, 1, 4 }, +{ 1328, 1329, 1332, 1, 4 }, +{ 1328, 1332, 1333, 1, 2 }, +{ 1327, 1328, 1333, 1, 4 }, +{ 1327, 1333, 1334, 1, 2 }, +{ 1327, 1334, 1335, 1, 2 }, +{ 1326, 1327, 1335, 1, 4 }, +{ 1326, 1335, 1336, 1, 2 }, +{ 1325, 1326, 1336, 1, 4 }, +{ 1325, 1336, 1337, 1, 2 }, +{ 1324, 1325, 1337, 1, 4 }, +{ 1324, 1337, 1338, 1, 2 }, +{ 1324, 1338, 1339, 1, 2 }, +{ 1324, 1339, 1340, 1, 2 }, +{ 1323, 1324, 1340, 1, 4 }, +{ 1323, 1340, 1341, 1, 2 }, +{ 1348, 1349, 1314, 1, 6 }, +{ 1348, 1314, 1315, 1, 2 }, +{ 1346, 1347, 1348, 1, 6 }, +{ 1345, 1346, 1348, 1, 4 }, +{ 1345, 1348, 1315, 1, 0 }, +{ 1316, 1317, 1318, 1, 6 }, +{ 1315, 1316, 1318, 1, 4 }, +{ 1345, 1315, 1318, 1, 0 }, +{ 1344, 1345, 1318, 1, 4 }, +{ 1344, 1318, 1319, 1, 2 }, +{ 1344, 1319, 1320, 1, 2 }, +{ 1344, 1320, 1321, 1, 2 }, +{ 1343, 1344, 1321, 1, 4 }, +{ 1343, 1321, 1322, 1, 2 }, +{ 1342, 1343, 1322, 1, 4 }, +{ 1342, 1322, 1323, 1, 2 }, +{ 1342, 1323, 1341, 1, 1 }, +{ 1361, 1350, 1351, 1, 6 }, +{ 1360, 1361, 1351, 1, 4 }, +{ 1357, 1358, 1359, 1, 6 }, +{ 1357, 1359, 1360, 1, 2 }, +{ 1355, 1356, 1357, 1, 6 }, +{ 1354, 1355, 1357, 1, 4 }, +{ 1351, 1352, 1353, 1, 6 }, +{ 1351, 1353, 1354, 1, 2 }, +{ 1360, 1351, 1354, 1, 0 }, +{ 1357, 1360, 1354, 1, 0 }, +{ 1368, 1369, 1362, 1, 6 }, +{ 1368, 1362, 1363, 1, 2 }, +{ 1366, 1367, 1368, 1, 6 }, +{ 1365, 1366, 1368, 1, 4 }, +{ 1365, 1368, 1363, 1, 0 }, +{ 1365, 1363, 1364, 1, 3 }, +{ 1378, 1379, 1370, 1, 6 }, +{ 1378, 1370, 1371, 1, 2 }, +{ 1378, 1371, 1372, 1, 2 }, +{ 1377, 1378, 1372, 1, 4 }, +{ 1376, 1377, 1372, 1, 4 }, +{ 1376, 1372, 1373, 1, 2 }, +{ 1376, 1373, 1374, 1, 2 }, +{ 1375, 1376, 1374, 1, 5 }, +{ 1382, 1383, 1380, 1, 6 }, +{ 1382, 1380, 1381, 1, 3 }, +{ 1401, 1402, 1384, 1, 6 }, +{ 1401, 1384, 1385, 1, 2 }, +{ 1400, 1401, 1385, 1, 4 }, +{ 1394, 1395, 1396, 1, 6 }, +{ 1393, 1394, 1396, 1, 4 }, +{ 1392, 1393, 1396, 1, 4 }, +{ 1392, 1396, 1397, 1, 2 }, +{ 1391, 1392, 1397, 1, 4 }, +{ 1391, 1397, 1398, 1, 2 }, +{ 1390, 1391, 1398, 1, 4 }, +{ 1389, 1390, 1398, 1, 4 }, +{ 1388, 1389, 1398, 1, 4 }, +{ 1388, 1398, 1399, 1, 2 }, +{ 1387, 1388, 1399, 1, 4 }, +{ 1385, 1386, 1387, 1, 6 }, +{ 1400, 1385, 1387, 1, 0 }, +{ 1400, 1387, 1399, 1, 1 }, +{ 1426, 1410, 1411, 1, 2 }, +{ 1426, 1411, 1412, 1, 2 }, +{ 1432, 1426, 1412, 1, 4 }, +{ 1425, 1403, 1404, 1, 6 }, +{ 1432, 1412, 1413, 1, 2 }, +{ 1431, 1432, 1413, 1, 4 }, +{ 1431, 1413, 1414, 1, 2 }, +{ 1430, 1431, 1414, 1, 4 }, +{ 1430, 1414, 1415, 1, 2 }, +{ 1430, 1415, 1416, 1, 2 }, +{ 1430, 1416, 1417, 1, 2 }, +{ 1429, 1430, 1417, 1, 4 }, +{ 1429, 1417, 1418, 1, 2 }, +{ 1428, 1429, 1418, 1, 4 }, +{ 1428, 1418, 1419, 1, 2 }, +{ 1427, 1428, 1419, 1, 4 }, +{ 1427, 1419, 1420, 1, 2 }, +{ 1427, 1420, 1421, 1, 2 }, +{ 1426, 1427, 1421, 1, 4 }, +{ 1410, 1426, 1421, 1, 0 }, +{ 1409, 1410, 1421, 1, 4 }, +{ 1408, 1409, 1421, 1, 4 }, +{ 1408, 1421, 1422, 1, 2 }, +{ 1407, 1408, 1422, 1, 4 }, +{ 1407, 1422, 1423, 1, 2 }, +{ 1406, 1407, 1423, 1, 4 }, +{ 1406, 1423, 1424, 1, 2 }, +{ 1405, 1406, 1424, 1, 4 }, +{ 1404, 1405, 1424, 1, 4 }, +{ 1404, 1424, 1425, 1, 2 }, +{ 1449, 1450, 1433, 1, 6 }, +{ 1449, 1433, 1434, 1, 2 }, +{ 1448, 1449, 1434, 1, 4 }, +{ 1447, 1448, 1434, 1, 4 }, +{ 1434, 1435, 1436, 1, 6 }, +{ 1447, 1434, 1436, 1, 0 }, +{ 1446, 1447, 1436, 1, 4 }, +{ 1446, 1436, 1437, 1, 2 }, +{ 1445, 1446, 1437, 1, 4 }, +{ 1445, 1437, 1438, 1, 2 }, +{ 1442, 1443, 1444, 1, 6 }, +{ 1444, 1445, 1438, 1, 4 }, +{ 1444, 1438, 1439, 1, 2 }, +{ 1441, 1442, 1444, 1, 4 }, +{ 1444, 1439, 1440, 1, 2 }, +{ 1444, 1440, 1441, 1, 2 }, +{ 1499, 1486, 1454, 1, 4 }, +{ 1499, 1454, 1455, 1, 2 }, +{ 1499, 1455, 1456, 1, 2 }, +{ 1499, 1456, 1457, 1, 2 }, +{ 1499, 1457, 1458, 1, 2 }, +{ 1498, 1499, 1458, 1, 4 }, +{ 1485, 1451, 1452, 1, 6 }, +{ 1472, 1473, 1474, 1, 6 }, +{ 1484, 1485, 1452, 1, 4 }, +{ 1472, 1474, 1475, 1, 2 }, +{ 1471, 1472, 1475, 1, 4 }, +{ 1471, 1475, 1476, 1, 2 }, +{ 1470, 1471, 1476, 1, 4 }, +{ 1470, 1476, 1477, 1, 2 }, +{ 1470, 1477, 1478, 1, 2 }, +{ 1469, 1470, 1478, 1, 4 }, +{ 1469, 1478, 1479, 1, 2 }, +{ 1469, 1479, 1480, 1, 2 }, +{ 1468, 1469, 1480, 1, 4 }, +{ 1468, 1480, 1481, 1, 2 }, +{ 1467, 1468, 1481, 1, 4 }, +{ 1483, 1484, 1452, 1, 4 }, +{ 1497, 1498, 1458, 1, 4 }, +{ 1497, 1458, 1459, 1, 2 }, +{ 1496, 1497, 1459, 1, 4 }, +{ 1483, 1452, 1453, 1, 2 }, +{ 1496, 1459, 1460, 1, 2 }, +{ 1495, 1496, 1460, 1, 4 }, +{ 1495, 1460, 1461, 1, 2 }, +{ 1494, 1495, 1461, 1, 4 }, +{ 1494, 1461, 1462, 1, 2 }, +{ 1494, 1462, 1463, 1, 2 }, +{ 1493, 1494, 1463, 1, 4 }, +{ 1493, 1463, 1464, 1, 2 }, +{ 1492, 1493, 1464, 1, 4 }, +{ 1492, 1464, 1465, 1, 2 }, +{ 1491, 1492, 1465, 1, 4 }, +{ 1490, 1491, 1465, 1, 4 }, +{ 1489, 1490, 1465, 1, 4 }, +{ 1489, 1465, 1466, 1, 2 }, +{ 1488, 1489, 1466, 1, 4 }, +{ 1488, 1466, 1467, 1, 2 }, +{ 1487, 1488, 1467, 1, 4 }, +{ 1487, 1467, 1481, 1, 0 }, +{ 1486, 1487, 1481, 1, 4 }, +{ 1454, 1486, 1481, 1, 0 }, +{ 1454, 1481, 1482, 1, 2 }, +{ 1454, 1482, 1483, 1, 2 }, +{ 1453, 1454, 1483, 1, 4 }, +{ 1513, 1514, 1515, 1, 6 }, +{ 1512, 1513, 1515, 1, 4 }, +{ 1521, 1500, 1501, 1, 6 }, +{ 1511, 1512, 1515, 1, 4 }, +{ 1511, 1515, 1516, 1, 2 }, +{ 1510, 1511, 1516, 1, 4 }, +{ 1510, 1516, 1517, 1, 2 }, +{ 1509, 1510, 1517, 1, 4 }, +{ 1509, 1517, 1518, 1, 2 }, +{ 1508, 1509, 1518, 1, 4 }, +{ 1508, 1518, 1519, 1, 2 }, +{ 1507, 1508, 1519, 1, 4 }, +{ 1507, 1519, 1520, 1, 2 }, +{ 1506, 1507, 1520, 1, 4 }, +{ 1505, 1506, 1520, 1, 4 }, +{ 1504, 1505, 1520, 1, 4 }, +{ 1503, 1504, 1520, 1, 4 }, +{ 1503, 1520, 1521, 1, 2 }, +{ 1502, 1503, 1521, 1, 4 }, +{ 1501, 1502, 1521, 1, 4 }, +{ 1539, 1540, 1541, 1, 6 }, +{ 1538, 1539, 1541, 1, 4 }, +{ 1536, 1537, 1538, 1, 6 }, +{ 1535, 1536, 1538, 1, 4 }, +{ 1532, 1533, 1534, 1, 6 }, +{ 1545, 1522, 1523, 1, 6 }, +{ 1545, 1523, 1524, 1, 2 }, +{ 1545, 1524, 1525, 1, 2 }, +{ 1544, 1545, 1525, 1, 4 }, +{ 1544, 1525, 1526, 1, 2 }, +{ 1544, 1526, 1527, 1, 2 }, +{ 1544, 1527, 1528, 1, 2 }, +{ 1544, 1528, 1529, 1, 2 }, +{ 1543, 1544, 1529, 1, 4 }, +{ 1543, 1529, 1530, 1, 2 }, +{ 1543, 1530, 1531, 1, 2 }, +{ 1542, 1543, 1531, 1, 4 }, +{ 1542, 1531, 1532, 1, 2 }, +{ 1541, 1542, 1532, 1, 4 }, +{ 1538, 1541, 1532, 1, 0 }, +{ 1535, 1538, 1532, 1, 0 }, +{ 1534, 1535, 1532, 1, 4 }, +{ 1548, 1549, 1546, 1, 6 }, +{ 1548, 1546, 1547, 1, 3 }, +{ 1550, 1551, 1552, 1, 6 }, +{ 1550, 1552, 1553, 1, 2 }, +{ 1555, 1556, 1557, 1, 6 }, +{ 1554, 1555, 1557, 1, 4 }, +{ 1554, 1557, 1550, 1, 2 }, +{ 1554, 1550, 1553, 1, 1 }, +{ 1575, 1558, 1559, 0, 2 }, +{ 1575, 1559, 1560, 0, 2 }, +{ 1575, 1560, 1561, 0, 2 }, +{ 1575, 1561, 1562, 0, 2 }, +{ 1575, 1562, 1563, 0, 2 }, +{ 1575, 1563, 1564, 0, 2 }, +{ 1575, 1564, 1565, 0, 2 }, +{ 1575, 1565, 1558, 0, 2 }, +{ 1574, 1567, 1566, 0, 2 }, +{ 1574, 1568, 1567, 0, 2 }, +{ 1574, 1569, 1568, 0, 2 }, +{ 1574, 1570, 1569, 0, 2 }, +{ 1574, 1571, 1570, 0, 2 }, +{ 1574, 1572, 1571, 0, 2 }, +{ 1574, 1573, 1572, 0, 2 }, +{ 1574, 1566, 1573, 0, 2 }, +{ 1593, 1576, 1577, 0, 2 }, +{ 1593, 1577, 1578, 0, 2 }, +{ 1593, 1578, 1579, 0, 2 }, +{ 1593, 1579, 1580, 0, 2 }, +{ 1593, 1580, 1581, 0, 2 }, +{ 1593, 1581, 1582, 0, 2 }, +{ 1593, 1582, 1583, 0, 2 }, +{ 1593, 1583, 1576, 0, 2 }, +{ 1592, 1585, 1584, 0, 2 }, +{ 1592, 1586, 1585, 0, 2 }, +{ 1592, 1587, 1586, 0, 2 }, +{ 1592, 1588, 1587, 0, 2 }, +{ 1592, 1589, 1588, 0, 2 }, +{ 1592, 1590, 1589, 0, 2 }, +{ 1592, 1591, 1590, 0, 2 }, +{ 1592, 1584, 1591, 0, 2 }, +{ 1610, 1609, 1608, 1, 6 }, +{ 1610, 1608, 1607, 1, 2 }, +{ 1607, 1606, 1605, 1, 6 }, +{ 1607, 1605, 1604, 1, 2 }, +{ 1603, 1602, 1601, 1, 6 }, +{ 1595, 1594, 1613, 1, 6 }, +{ 1596, 1595, 1613, 1, 4 }, +{ 1596, 1613, 1612, 1, 2 }, +{ 1597, 1596, 1612, 1, 4 }, +{ 1598, 1597, 1612, 1, 4 }, +{ 1599, 1598, 1612, 1, 4 }, +{ 1599, 1612, 1611, 1, 2 }, +{ 1600, 1599, 1611, 1, 4 }, +{ 1601, 1600, 1611, 1, 4 }, +{ 1601, 1611, 1610, 1, 2 }, +{ 1601, 1610, 1607, 1, 0 }, +{ 1601, 1607, 1604, 1, 0 }, +{ 1601, 1604, 1603, 1, 2 }, +{ 1628, 1629, 1630, 1, 6 }, +{ 1627, 1628, 1630, 1, 4 }, +{ 1625, 1626, 1627, 1, 6 }, +{ 1624, 1625, 1627, 1, 4 }, +{ 1621, 1622, 1623, 1, 6 }, +{ 1633, 1614, 1615, 1, 6 }, +{ 1633, 1615, 1616, 1, 2 }, +{ 1632, 1633, 1616, 1, 4 }, +{ 1632, 1616, 1617, 1, 2 }, +{ 1632, 1617, 1618, 1, 2 }, +{ 1632, 1618, 1619, 1, 2 }, +{ 1631, 1632, 1619, 1, 4 }, +{ 1631, 1619, 1620, 1, 2 }, +{ 1631, 1620, 1621, 1, 2 }, +{ 1630, 1631, 1621, 1, 4 }, +{ 1627, 1630, 1621, 1, 0 }, +{ 1624, 1627, 1621, 1, 0 }, +{ 1623, 1624, 1621, 1, 4 }, +{ 1642, 1641, 1657, 1, 4 }, +{ 1643, 1642, 1657, 1, 4 }, +{ 1643, 1657, 1663, 1, 2 }, +{ 1635, 1634, 1656, 1, 6 }, +{ 1644, 1643, 1663, 1, 4 }, +{ 1644, 1663, 1662, 1, 2 }, +{ 1645, 1644, 1662, 1, 4 }, +{ 1645, 1662, 1661, 1, 2 }, +{ 1646, 1645, 1661, 1, 4 }, +{ 1647, 1646, 1661, 1, 4 }, +{ 1648, 1647, 1661, 1, 4 }, +{ 1648, 1661, 1660, 1, 2 }, +{ 1649, 1648, 1660, 1, 4 }, +{ 1649, 1660, 1659, 1, 2 }, +{ 1650, 1649, 1659, 1, 4 }, +{ 1650, 1659, 1658, 1, 2 }, +{ 1651, 1650, 1658, 1, 4 }, +{ 1652, 1651, 1658, 1, 4 }, +{ 1652, 1658, 1657, 1, 2 }, +{ 1652, 1657, 1641, 1, 0 }, +{ 1652, 1641, 1640, 1, 2 }, +{ 1652, 1640, 1639, 1, 2 }, +{ 1653, 1652, 1639, 1, 4 }, +{ 1653, 1639, 1638, 1, 2 }, +{ 1654, 1653, 1638, 1, 4 }, +{ 1654, 1638, 1637, 1, 2 }, +{ 1655, 1654, 1637, 1, 4 }, +{ 1655, 1637, 1636, 1, 2 }, +{ 1655, 1636, 1635, 1, 2 }, +{ 1656, 1655, 1635, 1, 4 }, +{ 1687, 1671, 1672, 1, 2 }, +{ 1687, 1672, 1673, 1, 2 }, +{ 1693, 1687, 1673, 1, 4 }, +{ 1686, 1664, 1665, 1, 6 }, +{ 1693, 1673, 1674, 1, 2 }, +{ 1692, 1693, 1674, 1, 4 }, +{ 1692, 1674, 1675, 1, 2 }, +{ 1691, 1692, 1675, 1, 4 }, +{ 1691, 1675, 1676, 1, 2 }, +{ 1691, 1676, 1677, 1, 2 }, +{ 1691, 1677, 1678, 1, 2 }, +{ 1690, 1691, 1678, 1, 4 }, +{ 1690, 1678, 1679, 1, 2 }, +{ 1689, 1690, 1679, 1, 4 }, +{ 1689, 1679, 1680, 1, 2 }, +{ 1688, 1689, 1680, 1, 4 }, +{ 1688, 1680, 1681, 1, 2 }, +{ 1688, 1681, 1682, 1, 2 }, +{ 1687, 1688, 1682, 1, 4 }, +{ 1671, 1687, 1682, 1, 0 }, +{ 1670, 1671, 1682, 1, 4 }, +{ 1669, 1670, 1682, 1, 4 }, +{ 1669, 1682, 1683, 1, 2 }, +{ 1668, 1669, 1683, 1, 4 }, +{ 1668, 1683, 1684, 1, 2 }, +{ 1667, 1668, 1684, 1, 4 }, +{ 1667, 1684, 1685, 1, 2 }, +{ 1666, 1667, 1685, 1, 4 }, +{ 1665, 1666, 1685, 1, 4 }, +{ 1665, 1685, 1686, 1, 2 } +}; + +static Vert vert_2[] = { +{ 171.834137f, -24.549576f, 161.761139f, 0.000000f, -1.000000f, 0.000000f, 167.258984f, 73.910260f }, +{ 385.145508f, -24.549585f, 281.452515f, 0.000000f, -1.000000f, 0.000000f, 214.952915f, 32.905991f }, +{ 336.557922f, -24.549572f, 123.839111f, 0.000000f, -1.000000f, 0.000000f, 204.089298f, 86.901717f }, +{ 526.168030f, -24.549603f, 127.394318f, 0.000000f, -1.000000f, 0.000000f, 246.483912f, 85.683761f }, +{ 387.515625f, -24.549564f, 39.699638f, 0.000000f, -1.000000f, 0.000000f, 215.482850f, 115.726499f }, +{ 540.388733f, -24.549561f, -4.147684f, 0.000000f, -1.000000f, 0.000000f, 249.663506f, 130.747868f }, +{ 398.181213f, -24.549526f, -46.809975f, 0.000000f, -1.000000f, 0.000000f, 217.867557f, 145.363252f }, +{ 559.349792f, -24.549519f, -146.355286f, 0.000000f, -1.000000f, 0.000000f, 253.902968f, 179.465822f }, +{ 342.483246f, -24.549520f, -126.209206f, 0.000000f, -1.000000f, 0.000000f, 205.414135f, 172.564107f }, +{ 451.509033f, -24.549507f, -264.861603f, 0.000000f, -1.000000f, 0.000000f, 229.791028f, 220.064120f }, +{ 233.457428f, -24.549515f, -184.277298f, 0.000000f, -1.000000f, 0.000000f, 181.037242f, 192.457275f }, +{ 252.418427f, -24.549503f, -317.004364f, 0.000000f, -1.000000f, 0.000000f, 185.276690f, 237.927362f }, +{ 87.694656f, -24.549515f, -183.092224f, 0.000000f, -1.000000f, 0.000000f, 148.446376f, 192.051290f }, +{ 27.256439f, -24.549471f, -341.890686f, 0.000000f, -1.000000f, 0.000000f, 134.933100f, 246.453003f }, +{ -72.288864f, -24.549515f, -178.351990f, 0.000000f, -1.000000f, 0.000000f, 112.675931f, 190.427367f }, +{ -154.058212f, -24.549473f, -325.299805f, 0.000000f, -1.000000f, 0.000000f, 94.393258f, 240.769243f }, +{ -220.421753f, -24.549486f, -172.426666f, 0.000000f, -1.000000f, 0.000000f, 79.555146f, 188.397447f }, +{ -346.038452f, -24.549469f, -367.962097f, 0.000000f, -1.000000f, 0.000000f, 51.468713f, 255.384635f }, +{ -318.781982f, -24.549488f, -146.355286f, 0.000000f, -1.000000f, 0.000000f, 57.562944f, 179.465822f }, +{ -466.914886f, -24.549479f, -242.345398f, 0.000000f, -1.000000f, 0.000000f, 24.442152f, 212.350443f }, +{ -383.960480f, -24.549492f, -96.582626f, 0.000000f, -1.000000f, 0.000000f, 42.989791f, 162.414540f }, +{ -552.239441f, -24.549492f, -101.322876f, 0.000000f, -1.000000f, 0.000000f, 5.364584f, 164.038467f }, +{ -421.882477f, -24.549498f, -27.848965f, 0.000000f, -1.000000f, 0.000000f, 34.510873f, 138.867531f }, +{ -559.349792f, -24.549505f, 49.180138f, 0.000000f, -1.000000f, 0.000000f, 3.774793f, 112.478631f }, +{ -412.401978f, -24.549538f, 71.696342f, 0.000000f, -1.000000f, 0.000000f, 36.630604f, 104.764969f }, +{ -510.762207f, -24.549515f, 174.796814f, 0.000000f, -1.000000f, 0.000000f, 14.638404f, 69.444450f }, +{ -348.408569f, -24.549543f, 140.429993f, 0.000000f, -1.000000f, 0.000000f, 50.938782f, 81.217951f }, +{ -411.216919f, -24.549555f, 264.861633f, 0.000000f, -1.000000f, 0.000000f, 36.895568f, 38.589741f }, +{ -258.343781f, -24.549547f, 187.832520f, 0.000000f, -1.000000f, 0.000000f, 71.076220f, 64.978641f }, +{ -254.788574f, -24.549561f, 338.335541f, 0.000000f, -1.000000f, 0.000000f, 71.871129f, 13.418798f }, +{ -133.912140f, -24.549547f, 193.757843f, 0.000000f, -1.000000f, 0.000000f, 98.897688f, 62.948714f }, +{ -43.847347f, -24.549593f, 367.962097f, 0.000000f, -1.000000f, 0.000000f, 119.035126f, 3.269238f }, +{ 37.922009f, -24.549547f, 183.092255f, 0.000000f, -1.000000f, 0.000000f, 137.317792f, 66.602568f }, +{ 168.278946f, -24.549589f, 315.819336f, 0.000000f, -1.000000f, 0.000000f, 166.464082f, 21.132490f } +}; + +static Face face_2[] = { +{ 18, 17, 16, 2, 6 }, +{ 8, 7, 6, 2, 6 }, +{ 20, 19, 18, 2, 6 }, +{ 22, 21, 20, 2, 6 }, +{ 4, 3, 2, 2, 6 }, +{ 10, 9, 8, 2, 6 }, +{ 6, 5, 4, 2, 6 }, +{ 26, 25, 24, 2, 6 }, +{ 28, 27, 26, 2, 6 }, +{ 24, 23, 22, 2, 6 }, +{ 30, 29, 28, 2, 6 }, +{ 12, 11, 10, 2, 6 }, +{ 2, 1, 0, 2, 6 }, +{ 0, 33, 32, 2, 6 }, +{ 32, 31, 30, 2, 6 }, +{ 14, 13, 12, 2, 6 }, +{ 16, 15, 14, 2, 6 }, +{ 4, 2, 0, 2, 0 }, +{ 6, 4, 0, 2, 0 }, +{ 8, 6, 0, 2, 0 }, +{ 10, 8, 0, 2, 0 }, +{ 12, 10, 0, 2, 0 }, +{ 12, 0, 32, 2, 0 }, +{ 14, 12, 32, 2, 0 }, +{ 14, 32, 30, 2, 0 }, +{ 16, 14, 30, 2, 0 }, +{ 16, 30, 28, 2, 0 }, +{ 16, 28, 26, 2, 0 }, +{ 18, 16, 26, 2, 0 }, +{ 20, 18, 26, 2, 0 }, +{ 20, 26, 24, 2, 0 }, +{ 20, 24, 22, 2, 0 } +}; + + +static Vert *vert[] = { +vert_0, +vert_1, +vert_2 +}; + +static int num_verts[] = { +68, +1694, +34 +}; + +static Face *face[] = { +face_0, +face_1, +face_2 +}; + +static int num_faces[] = { +100, +1606, +32 +}; + +static int total_num_frames = 76; + +// jenz: changed array size to 76 (too many initialisers) +static Matrix mat[76][3] = { +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 22198.351563, 1.000000}, + {1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -32.104950, -4.568500, 21760.089844, 1.000000}, + {1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -36.722248, 9.404100, 22230.794922, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 21601.316406, 1.000000}, + {0.881000, 0.187100, 0.434500, 0.000000, + -0.178600, -0.718900, 0.671800, 0.000000, + -0.438000, 0.669500, 0.600000, 0.000000, + -40.679047, 57.105099, 21262.400391, 1.000000}, + {1.008900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.008900, 0.000000, + 0.000000, 1.008900, 0.000000, 0.000000, + -36.722248, 9.404100, 21633.759766, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 20863.496094, 1.000000}, + {0.759600, 0.187100, 0.622900, 0.000000, + -0.326300, -0.718900, 0.613800, 0.000000, + -0.562600, 0.669500, 0.485100, 0.000000, + -35.966850, 57.105099, 20524.212891, 1.000000}, + {1.017400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.017400, 0.000000, + 0.000000, 1.017400, 0.000000, 0.000000, + -36.722248, 9.404100, 20895.939453, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 20000.533203, 1.000000}, + {0.598200, 0.187100, 0.779200, 0.000000, + -0.457200, -0.718900, 0.523600, 0.000000, + -0.658100, 0.669500, 0.344500, 0.000000, + -31.281849, 57.105099, 19661.962891, 1.000000}, + {1.025100, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.025100, 0.000000, + 0.000000, 1.025100, 0.000000, 0.000000, + -36.722248, 9.404100, 20032.976563, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 19028.070313, 1.000000}, + {0.406500, 0.187100, 0.894300, 0.000000, + -0.563800, -0.718900, 0.406600, 0.000000, + -0.719000, 0.669500, 0.186800, 0.000000, + -26.903849, 57.105099, 18691.248047, 1.000000}, + {1.031600, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.031600, 0.000000, + 0.000000, 1.031600, 0.000000, 0.000000, + -36.722248, 9.404100, 19060.513672, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 17961.750000, 1.000000}, + {0.196700, 0.187100, 0.962400, 0.000000, + -0.640300, -0.718900, 0.270600, 0.000000, + -0.742500, 0.669500, 0.021700, 0.000000, + -23.081848, 57.105099, 17627.578125, 1.000000}, + {1.036500, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.036500, 0.000000, + 0.000000, 1.036500, 0.000000, 0.000000, + -36.722248, 9.404100, 17994.193359, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 16817.216797, 1.000000}, + {-0.018200, 0.187100, 0.982200, 0.000000, + -0.683900, -0.718900, 0.124300, 0.000000, + -0.729300, 0.669500, -0.141000, 0.000000, + -20.007050, 57.105099, 16486.400391, 1.000000}, + {1.039500, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.039500, 0.000000, + 0.000000, 1.039500, 0.000000, 0.000000, + -36.722248, 9.404100, 16849.660156, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 15610.111328, 1.000000}, + {-0.225800, 0.187100, 0.956000, 0.000000, + -0.694700, -0.718900, -0.023400, 0.000000, + -0.682900, 0.669500, -0.292300, 0.000000, + -17.795149, 57.105099, 15283.111328, 1.000000}, + {1.040000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.040000, 0.000000, + 0.000000, 1.040000, 0.000000, 0.000000, + -36.722248, 9.404100, 15642.555664, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 14356.078125, 1.000000}, + {-0.414200, 0.187100, 0.890800, 0.000000, + -0.675700, -0.718900, -0.163200, 0.000000, + -0.609900, 0.669500, -0.424100, 0.000000, + -16.485548, 57.105099, 14033.073242, 1.000000}, + {1.037200, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.037200, 0.000000, + 0.000000, 1.037200, 0.000000, 0.000000, + -36.722248, 9.404100, 14388.522461, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 13070.758789, 1.000000}, + {-0.577800, 0.187100, 0.794500, 0.000000, + -0.631700, -0.718900, -0.290100, 0.000000, + -0.516900, 0.669500, -0.533500, 0.000000, + -16.012848, 57.105099, 12751.730469, 1.000000}, + {1.031000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.031000, 0.000000, + 0.000000, 1.031000, 0.000000, 0.000000, + -36.722248, 9.404100, 13103.203125, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 11769.795898, 1.000000}, + {-0.715900, 0.187100, 0.672600, 0.000000, + -0.566400, -0.718900, -0.402900, 0.000000, + -0.408200, 0.669500, -0.620600, 0.000000, + -16.293648, 57.105099, 11454.640625, 1.000000}, + {1.022700, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.022700, 0.000000, + 0.000000, 1.022700, 0.000000, 0.000000, + -36.722248, 9.404100, 11802.240234, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 10468.833984, 1.000000}, + {-0.827900, 0.187100, 0.528800, 0.000000, + -0.482200, -0.718900, -0.500600, 0.000000, + -0.286500, 0.669500, -0.685400, 0.000000, + -17.278248, 57.105099, 10157.392578, 1.000000}, + {1.013400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.013400, 0.000000, + 0.000000, 1.013400, 0.000000, 0.000000, + -36.722248, 9.404100, 10501.278320, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 9183.513672, 1.000000}, + {-0.912000, 0.187100, 0.365100, 0.000000, + -0.380400, -0.718900, -0.581800, 0.000000, + -0.153600, 0.669500, -0.726800, 0.000000, + -18.951847, 57.105099, 8875.574219, 1.000000}, + {1.004100, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004100, 0.000000, + 0.000000, 1.004100, 0.000000, 0.000000, + -36.722248, 9.404100, 9215.958008, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 7929.480957, 1.000000}, + {-0.965100, 0.187100, 0.183100, 0.000000, + -0.261500, -0.718900, -0.644000, 0.000000, + -0.011100, 0.669500, -0.742800, 0.000000, + -21.328348, 57.105099, 7624.758301, 1.000000}, + {0.996000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.996000, 0.000000, + 0.000000, 0.996000, 0.000000, 0.000000, + -36.722248, 9.404100, 7961.925293, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 6722.375488, 1.000000}, + {-0.982200, 0.187100, -0.015200, 0.000000, + -0.126300, -0.718900, -0.683500, 0.000000, + 0.138800, 0.669500, -0.729800, 0.000000, + -24.438049, 57.105099, 6420.471191, 1.000000}, + {0.990300, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.990300, 0.000000, + 0.000000, 0.990300, 0.000000, 0.000000, + -36.722248, 9.404100, 6754.819824, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 5577.841309, 1.000000}, + {-0.956000, 0.187100, -0.225800, 0.000000, + 0.023400, -0.718900, -0.694700, 0.000000, + 0.292300, 0.669500, -0.682900, 0.000000, + -28.305548, 57.105099, 5278.185547, 1.000000}, + {0.988000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.988000, 0.000000, + 0.000000, 0.988000, 0.000000, 0.000000, + -36.722248, 9.404100, 5610.285645, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 4511.521484, 1.000000}, + {-0.878200, 0.187100, -0.440200, 0.000000, + 0.183000, -0.718900, -0.670600, 0.000000, + 0.441900, 0.669500, -0.597100, 0.000000, + -32.898449, 57.105099, 4213.296387, 1.000000}, + {0.991400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.991400, 0.000000, + 0.000000, 0.991400, 0.000000, 0.000000, + -36.722248, 9.404100, 4543.965332, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 3539.058594, 1.000000}, + {-0.743400, 0.187100, -0.642200, 0.000000, + 0.341900, -0.718900, -0.605200, 0.000000, + 0.574900, 0.669500, -0.470500, 0.000000, + -38.008450, 57.105099, 3241.149658, 1.000000}, + {1.000100, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000100, 0.000000, + 0.000000, 1.000100, 0.000000, 0.000000, + -36.722248, 9.404100, 3571.502441, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 2676.096436, 1.000000}, + {-0.553100, 0.187100, -0.811800, 0.000000, + 0.486100, -0.718900, -0.496800, 0.000000, + 0.676600, 0.669500, -0.306700, 0.000000, + -43.285347, 57.105099, 2377.160400, 1.000000}, + {1.011600, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.011600, 0.000000, + 0.000000, 1.011600, 0.000000, 0.000000, + -36.722248, 9.404100, 2708.540283, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1938.275757, 1.000000}, + {-0.316400, 0.187100, -0.930000, 0.000000, + 0.601100, -0.718900, -0.349100, 0.000000, + 0.733900, 0.669500, -0.115000, 0.000000, + -48.290947, 57.105099, 1636.875488, 1.000000}, + {1.023400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.023400, 0.000000, + 0.000000, 1.023400, 0.000000, 0.000000, + -36.722248, 9.404100, 1970.719727, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.049500, 0.187100, -0.981100, 0.000000, + 0.673700, -0.718900, -0.171100, 0.000000, + 0.737300, 0.669500, 0.090500, 0.000000, + -52.555748, 57.105099, 1036.013794, 1.000000}, + {1.032800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.032800, 0.000000, + 0.000000, 1.032800, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.225800, 0.187100, -0.956000, 0.000000, + 0.694700, -0.718900, 0.023400, 0.000000, + 0.682900, 0.669500, 0.292300, 0.000000, + -55.649448, 57.105099, 1031.074585, 1.000000}, + {1.037400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.037400, 0.000000, + 0.000000, 1.037400, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.491100, 0.187100, -0.850800, 0.000000, + 0.658600, -0.718900, 0.222200, 0.000000, + 0.570100, 0.669500, 0.476300, 0.000000, + -57.270248, 57.105099, 1025.276733, 1.000000}, + {1.037900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.037900, 0.000000, + 0.000000, 1.037900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.723400, 0.187100, -0.664600, 0.000000, + 0.561800, -0.718900, 0.409300, 0.000000, + 0.401200, 0.669500, 0.625200, 0.000000, + -57.111149, 57.105099, 1019.001221, 1.000000}, + {1.036800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.036800, 0.000000, + 0.000000, 1.036800, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.892600, 0.187100, -0.410300, 0.000000, + 0.409000, -0.718900, 0.562000, 0.000000, + 0.189800, 0.669500, 0.718200, 0.000000, + -55.002949, 57.105099, 1012.916504, 1.000000}, + {1.034500, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.034500, 0.000000, + 0.000000, 1.034500, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.975800, 0.187100, -0.113200, 0.000000, + 0.214500, -0.718900, 0.661200, 0.000000, + -0.042300, 0.669500, 0.741600, 0.000000, + -51.079346, 57.105099, 1007.726318, 1.000000}, + {1.031200, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.031200, 0.000000, + 0.000000, 1.031200, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.963000, 0.187100, 0.193800, 0.000000, + -0.000200, -0.718900, 0.695100, 0.000000, + -0.269300, 0.669500, 0.692300, 0.000000, + -45.765148, 57.105099, 1004.021790, 1.000000}, + {1.027000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.027000, 0.000000, + 0.000000, 1.027000, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.859000, 0.187100, 0.476600, 0.000000, + -0.210900, -0.718900, 0.662300, 0.000000, + -0.466500, 0.669500, 0.578100, 0.000000, + -39.690350, 57.105099, 1002.157410, 1.000000}, + {1.022400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.022400, 0.000000, + 0.000000, 1.022400, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.681700, 0.187100, 0.707300, 0.000000, + -0.395700, -0.718900, 0.571500, 0.000000, + -0.615400, 0.669500, 0.416100, 0.000000, + -33.554749, 57.105099, 1002.187256, 1.000000}, + {1.017400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.017400, 0.000000, + 0.000000, 1.017400, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.458000, 0.187100, 0.869100, 0.000000, + -0.539100, -0.718900, 0.438800, 0.000000, + -0.706900, 0.669500, 0.228400, 0.000000, + -27.984049, 57.105099, 1003.876953, 1.000000}, + {1.012300, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.012300, 0.000000, + 0.000000, 1.012300, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.217300, 0.187100, 0.958000, 0.000000, + -0.634300, -0.718900, 0.284200, 0.000000, + -0.741900, 0.669500, 0.037500, 0.000000, + -23.418049, 57.105099, 1006.781006, 1.000000}, + {1.007400, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.007400, 0.000000, + 0.000000, 1.007400, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.011500, 0.187100, 0.982300, 0.000000, + -0.683000, -0.718900, 0.128900, 0.000000, + -0.730300, 0.669500, -0.136000, 0.000000, + -20.090649, 57.105099, 1010.310059, 1.000000}, + {1.001600, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.001600, 0.000000, + 0.000000, 1.001600, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.214400, 0.187100, 0.958700, 0.000000, + -0.694900, -0.718900, -0.015100, 0.000000, + -0.686400, 0.669500, -0.284100, 0.000000, + -17.896347, 57.105099, 1014.017090, 1.000000}, + {0.994300, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.994300, 0.000000, + 0.000000, 0.994300, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.391300, 0.187100, 0.901000, 0.000000, + -0.679600, -0.718900, -0.145900, 0.000000, + -0.620500, 0.669500, -0.408500, 0.000000, + -16.604847, 57.105099, 1017.721558, 1.000000}, + {0.986100, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.986100, 0.000000, + 0.000000, 0.986100, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.545300, 0.187100, 0.817100, 0.000000, + -0.642900, -0.718900, -0.264400, 0.000000, + -0.538000, 0.669500, -0.512300, 0.000000, + -16.047749, 57.105099, 1021.376709, 1.000000}, + {0.977700, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.977700, 0.000000, + 0.000000, 0.977700, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.679500, 0.187100, 0.709400, 0.000000, + -0.586800, -0.718900, -0.372600, 0.000000, + -0.440300, 0.669500, -0.598300, 0.000000, + -16.141548, 57.105099, 1025.005493, 1.000000}, + {0.969900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.969900, 0.000000, + 0.000000, 0.969900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.795500, 0.187100, 0.576300, 0.000000, + -0.510700, -0.718900, -0.471600, 0.000000, + -0.326100, 0.669500, -0.667400, 0.000000, + -16.893848, 57.105099, 1028.650513, 1.000000}, + {0.963300, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.963300, 0.000000, + 0.000000, 0.963300, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.890900, 0.187100, 0.413900, 0.000000, + -0.411300, -0.718900, -0.560400, 0.000000, + -0.192700, 0.669500, -0.717400, 0.000000, + -18.402348, 57.105099, 1032.325195, 1.000000}, + {0.958800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.958800, 0.000000, + 0.000000, 0.958800, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.958000, 0.187100, 0.217300, 0.000000, + -0.284200, -0.718900, -0.634300, 0.000000, + -0.037500, 0.669500, -0.741900, 0.000000, + -20.845448, 57.105099, 1035.962158, 1.000000}, + {0.957000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.957000, 0.000000, + 0.000000, 0.957000, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.982300, 0.187100, -0.013000, 0.000000, + -0.127900, -0.718900, -0.683200, 0.000000, + 0.137100, 0.669500, -0.730100, 0.000000, + -24.399748, 57.105099, 1039.308228, 1.000000}, + {0.958800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.958800, 0.000000, + 0.000000, 0.958800, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.947100, 0.187100, -0.260700, 0.000000, + 0.048800, -0.718900, -0.693400, 0.000000, + 0.317100, 0.669500, -0.671800, 0.000000, + -29.005148, 57.105099, 1041.880859, 1.000000}, + {0.963900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.963900, 0.000000, + 0.000000, 0.963900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.844400, 0.187100, -0.502000, 0.000000, + 0.230600, -0.718900, -0.655700, 0.000000, + 0.483600, 0.669500, -0.563900, 0.000000, + -34.367550, 57.105099, 1043.237793, 1.000000}, + {0.971800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.971800, 0.000000, + 0.000000, 0.971800, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.677300, 0.187100, -0.711500, 0.000000, + 0.399200, -0.718900, -0.569000, 0.000000, + 0.618000, 0.669500, -0.412200, 0.000000, + -40.015949, 57.105099, 1043.108643, 1.000000}, + {0.981700, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.981700, 0.000000, + 0.000000, 0.981700, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.460700, 0.187100, -0.867600, 0.000000, + 0.537700, -0.718900, -0.440500, 0.000000, + 0.706200, 0.669500, -0.230600, 0.000000, + -45.402149, 57.105099, 1041.465820, 1.000000}, + {0.993000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.993000, 0.000000, + 0.000000, 0.993000, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {-0.217300, 0.187100, -0.958000, 0.000000, + 0.634300, -0.718900, -0.284200, 0.000000, + 0.741900, 0.669500, -0.037500, 0.000000, + -50.026550, 57.105099, 1038.534790, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.034900, 0.187100, -0.981700, 0.000000, + 0.685900, -0.718900, -0.112600, 0.000000, + 0.726800, 0.669500, 0.153400, 0.000000, + -53.643948, 57.105099, 1034.605103, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.284000, 0.187100, -0.940400, 0.000000, + 0.692000, -0.718900, 0.066000, 0.000000, + 0.663700, 0.669500, 0.333600, 0.000000, + -56.130249, 57.105099, 1029.897339, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.513800, 0.187100, -0.837300, 0.000000, + 0.652400, -0.718900, 0.239800, 0.000000, + 0.557100, 0.669500, 0.491400, 0.000000, + -57.333046, 57.105099, 1024.724487, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.709500, 0.187100, -0.679400, 0.000000, + 0.570200, -0.718900, 0.397500, 0.000000, + 0.414100, 0.669500, 0.616700, 0.000000, + -57.182648, 57.105099, 1019.425110, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.858600, 0.187100, -0.477300, 0.000000, + 0.450800, -0.718900, 0.529100, 0.000000, + 0.244200, 0.669500, 0.701600, 0.000000, + -55.694046, 57.105099, 1014.342407, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.951600, 0.187100, -0.244000, 0.000000, + 0.301900, -0.718900, 0.626100, 0.000000, + 0.058300, 0.669500, 0.740600, 0.000000, + -52.966049, 57.105099, 1009.804321, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.982300, 0.187100, 0.005300, 0.000000, + 0.133200, -0.718900, 0.682200, 0.000000, + -0.131400, 0.669500, 0.731100, 0.000000, + -49.174549, 57.105099, 1006.104492, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +}, +{{1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -41.462547, 14.736900, 1341.240845, 1.000000}, + {0.948800, 0.187100, 0.254600, 0.000000, + -0.044400, -0.718900, 0.693700, 0.000000, + -0.312800, 0.669500, 0.673800, 0.000000, + -44.562447, 57.105099, 1003.484802, 1.000000}, + {1.004900, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.004900, 0.000000, + 0.000000, 1.004900, 0.000000, 0.000000, + -36.722248, 9.404100, 1373.684814, 1.000000} +} +}; +#define RAW_NAME text_3dfinfo_raw +#define IMAGE_NAME text_3dfinfo_image +unsigned char RAW_NAME[] = { +0x40, +0x0, +0x0, +0x0, +0x40, +0x0, +0x0, +0x0, +0x8, +0x0, +0x0, +0x0, +0x2, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x22, +0x22, +0x2b, +0x3c, +0x44, +0x44, +0x66, +0x77, +0x88, +0x99, +0xaa, +0xbb, +0xcc, +0xdd, +0xee, +0xff, +0xcf, +0x1, +0x27, +0x0, +0x23, +0x0, +0x1, +0x0, +0x0, +0x0, +0xef, +0x1, +0xe2, +0x1, +0xe, +0x0, +0x12, +0x0, +0xf4, +0x1, +0xff, +0x1, +0xfc, +0x1, +0xee, +0x1, +0x19, +0x0, +0x10, +0x0, +0xe5, +0x1, +0x11, +0x0, +0x6, +0x0, +0xe8, +0x1, +0x9, +0x0, +0x8, +0x0, +0xeb, +0x1, +0x1, +0x0, +0x4, +0x0, +0x22, +0x22, +0x2b, +0x3c, +0x44, +0x44, +0x66, +0x77, +0x88, +0x99, +0xaa, +0xbb, +0xcc, +0xdd, +0xee, +0xff, +0x23, +0x4e, +0x3c, +0x7, +0xef, +0x1, +0x4, +0x0, +0x12, +0x1c, +0x88, +0x7, +0xfc, +0xff, +0xd3, +0x7, +0x10, +0x32, +0xb8, +0x7, +0x6, +0x22, +0x94, +0x7, +0x8, +0x12, +0xa0, +0x7, +0x4, +0x2, +0xac, +0x7, +0x19, +0x0, +0x0, +0x0, +0x1c, +0x0, +0x0, +0x0, +0x1f, +0x0, +0x0, +0x0, +0x21, +0x0, +0x0, +0x0, +0x24, +0x0, +0x0, +0x0, +0x26, +0x0, +0x0, +0x0, +0x28, +0x0, +0x0, +0x0, +0x2a, +0x0, +0x0, +0x0, +0x2c, +0x0, +0x0, +0x0, +0x2e, +0x0, +0x0, +0x0, +0x30, +0x0, +0x0, +0x0, +0x32, +0x0, +0x0, +0x0, +0x34, +0x0, +0x0, +0x0, +0x36, +0x0, +0x0, +0x0, +0x37, +0x0, +0x0, +0x0, +0x39, +0x0, +0x0, +0x0, +0x3b, +0x0, +0x0, +0x0, +0x3c, +0x0, +0x0, +0x0, +0x3e, +0x0, +0x0, +0x0, +0x40, +0x0, +0x0, +0x0, +0x41, +0x0, +0x0, +0x0, +0x43, +0x0, +0x0, +0x0, +0x44, +0x0, +0x0, +0x0, +0x46, +0x0, +0x0, +0x0, +0x47, +0x0, +0x0, +0x0, +0x48, +0x0, +0x0, +0x0, +0x4a, +0x0, +0x0, +0x0, +0x4b, +0x0, +0x0, +0x0, +0x4d, +0x0, +0x0, +0x0, +0x4e, +0x0, +0x0, +0x0, +0x4f, +0x0, +0x0, +0x0, +0x51, +0x0, +0x0, +0x0, +0x52, +0x0, +0x0, +0x0, +0x53, +0x0, +0x0, +0x0, +0x54, +0x0, +0x0, +0x0, +0x56, +0x0, +0x0, +0x0, +0x57, +0x0, +0x0, +0x0, +0x58, +0x0, +0x0, +0x0, +0x59, +0x0, +0x0, +0x0, +0x5b, +0x0, +0x0, +0x0, +0x5c, +0x0, +0x0, +0x0, +0x5d, +0x0, +0x0, +0x0, +0x5e, +0x0, +0x0, +0x0, +0x5f, +0x0, +0x0, +0x0, +0x61, +0x0, +0x0, +0x0, +0x62, +0x0, +0x0, +0x0, +0x63, +0x0, +0x0, +0x0, +0x64, +0x0, +0x0, +0x0, +0x65, +0x0, +0x0, +0x0, +0x66, +0x0, +0x0, +0x0, +0x67, +0x0, +0x0, +0x0, +0x69, +0x0, +0x0, +0x0, +0x6a, +0x0, +0x0, +0x0, +0x6b, +0x0, +0x0, +0x0, +0x6c, +0x0, +0x0, +0x0, +0x6d, +0x0, +0x0, +0x0, +0x6e, +0x0, +0x0, +0x0, +0x6f, +0x0, +0x0, +0x0, +0x70, +0x0, +0x0, +0x0, +0x71, +0x0, +0x0, +0x0, +0x72, +0x0, +0x0, +0x0, +0x73, +0x0, +0x0, +0x0, +0x74, +0x0, +0x0, +0x0, +0x75, +0x0, +0x0, +0x0, +0x76, +0x0, +0x0, +0x0, +0x77, +0x0, +0x0, +0x0, +0x78, +0x0, +0x0, +0x0, +0x79, +0x0, +0x0, +0x0, +0x7a, +0x0, +0x0, +0x0, +0x7b, +0x0, +0x0, +0x0, +0x7c, +0x0, +0x0, +0x0, +0x7d, +0x0, +0x0, +0x0, +0x7e, +0x0, +0x0, +0x0, +0x7f, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0x81, +0x0, +0x0, +0x0, +0x82, +0x0, +0x0, +0x0, +0x83, +0x0, +0x0, +0x0, +0x84, +0x0, +0x0, +0x0, +0x85, +0x0, +0x0, +0x0, +0x86, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x88, +0x0, +0x0, +0x0, +0x89, +0x0, +0x0, +0x0, +0x8a, +0x0, +0x0, +0x0, +0x8b, +0x0, +0x0, +0x0, +0x8c, +0x0, +0x0, +0x0, +0x8d, +0x0, +0x0, +0x0, +0x8e, +0x0, +0x0, +0x0, +0x8f, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x91, +0x0, +0x0, +0x0, +0x92, +0x0, +0x0, +0x0, +0x93, +0x0, +0x0, +0x0, +0x94, +0x0, +0x0, +0x0, +0x95, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x97, +0x0, +0x0, +0x0, +0x98, +0x0, +0x0, +0x0, +0x99, +0x0, +0x0, +0x0, +0x9a, +0x0, +0x0, +0x0, +0x9b, +0x0, +0x0, +0x0, +0x9c, +0x0, +0x0, +0x0, +0x9c, +0x0, +0x0, +0x0, +0x9d, +0x0, +0x0, +0x0, +0x9e, +0x0, +0x0, +0x0, +0x9f, +0x0, +0x0, +0x0, +0xa0, +0x0, +0x0, +0x0, +0xa0, +0x0, +0x0, +0x0, +0xa1, +0x0, +0x0, +0x0, +0xa2, +0x0, +0x0, +0x0, +0xa3, +0x0, +0x0, +0x0, +0xa4, +0x0, +0x0, +0x0, +0xa4, +0x0, +0x0, +0x0, +0xa5, +0x0, +0x0, +0x0, +0xa6, +0x0, +0x0, +0x0, +0xa7, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa9, +0x0, +0x0, +0x0, +0xaa, +0x0, +0x0, +0x0, +0xab, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xad, +0x0, +0x0, +0x0, +0xae, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xb0, +0x0, +0x0, +0x0, +0xb1, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb3, +0x0, +0x0, +0x0, +0xb4, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb6, +0x0, +0x0, +0x0, +0xb7, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb9, +0x0, +0x0, +0x0, +0xba, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbc, +0x0, +0x0, +0x0, +0xbd, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbf, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc1, +0x0, +0x0, +0x0, +0xc2, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc4, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc6, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc8, +0x0, +0x0, +0x0, +0xc9, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xcb, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcd, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xcf, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd1, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xe2, +0x13, +0xf7, +0xbf, +0x37, +0x1, +0x0, +0x0, +0xac, +0xf7, +0xf9, +0xbf, +0x0, +0x0, +0x0, +0x0, +0x80, +0x1, +0x7a, +0x0, +0x1, +0x0, +0x0, +0x0, +0xcc, +0xfa, +0x76, +0x0, +0x42, +0x52, +0x64, +0x81, +0x18, +0x52, +0x64, +0x81, +0x2, +0x0, +0x0, +0x0, +0xda, +0x0, +0x0, +0x0, +0x4, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0x66, +0xc, +0xfa, +0xbf, +0x18, +0x52, +0x64, +0x81, +0x7a, +0xc, +0xfa, +0xbf, +0x42, +0x52, +0x64, +0x81, +0x80, +0x1, +0x7a, +0x0, +0x4, +0x0, +0x0, +0x0, +0xf8, +0xfa, +0x76, +0x0, +0xef, +0x5b, +0xf7, +0xbf, +0xf8, +0xfa, +0x76, +0x0, +0xe8, +0x5d, +0xf7, +0xbf, +0x0, +0x0, +0x0, +0x0, +0x80, +0x1, +0x7a, +0x0, +0x4, +0x0, +0x0, +0x0, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0xf7, +0xbf, +0x18, +0x52, +0x64, +0x81, +0x0, +0x0, +0x0, +0x0, +0x80, +0x1, +0x7a, +0x0, +0x8d, +0xea, +0x40, +0x0, +0x4, +0x0, +0x0, +0x0, +0x80, +0x1, +0x7a, +0x0, +0x1, +0x0, +0x0, +0x0, +0xab, +0xea, +0x40, +0x0, +0x2, +0x0, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x38, +0x44, +0x41, +0x0, +0x28, +0xba, +0x40, +0x0, +0x2, +0x0, +0x0, +0x0, +0xb3, +0xba, +0x40, +0x0, +0x2, +0x0, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0xa, +0x31, +0x0, +0x0, +0x1, +0x0, +0x0, +0x0, +0x74, +0x1e, +0xa7, +0x0, +0x58, +0x15, +0x0, +0x0 +}; + +unsigned char IMAGE_NAME[] = { +0xc, +0xe, +0xe, +0xe, +0xc, +0x8, +0x3, +0x29, +0x9, +0x9, +0xa, +0xc, +0xb, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0x9, +0x8, +0x3, +0x9, +0x2e, +0xf, +0xe, +0xc, +0xa, +0x9, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x39, +0x0, +0x33, +0x32, +0x31, +0x30, +0x30, +0x40, +0x40, +0x40, +0x30, +0x30, +0x42, +0x32, +0x32, +0x21, +0x0, +0x22, +0x39, +0x22, +0x39, +0x39, +0x2, +0x2, +0x9, +0x9, +0xc, +0x2e, +0xe, +0xe, +0x2e, +0x9, +0x3, +0x29, +0x9, +0xa, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0x9, +0x29, +0x3, +0x9, +0xd, +0xf, +0xe, +0x2e, +0xa, +0x9, +0x8, +0x3, +0x2, +0x2, +0x1, +0x22, +0x39, +0x22, +0x22, +0x22, +0x0, +0x21, +0x33, +0x32, +0x32, +0x31, +0x42, +0x42, +0x41, +0x42, +0x42, +0x31, +0x32, +0x31, +0x20, +0x20, +0x33, +0x21, +0x33, +0x21, +0x33, +0x0, +0x22, +0x1, +0x8, +0x29, +0x9, +0xc, +0xe, +0xe, +0xf, +0x2e, +0x8, +0x3, +0x8, +0x2d, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xc, +0x9, +0x8, +0x3, +0x9, +0xe, +0xf, +0xd, +0xb, +0xa, +0x9, +0x29, +0x2, +0x39, +0x22, +0x0, +0x21, +0x33, +0x21, +0x33, +0x21, +0x33, +0x33, +0x20, +0x20, +0x32, +0x20, +0x20, +0x20, +0x20, +0x32, +0x20, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x32, +0x31, +0x20, +0x33, +0x0, +0x2, +0x8, +0x9, +0x2e, +0xe, +0xe, +0xe, +0x9, +0x8, +0x3, +0x29, +0x9, +0xc, +0x2e, +0xd, +0xe, +0xe, +0xd, +0x2e, +0xc, +0x2b, +0x8, +0x29, +0x2a, +0x2e, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x8, +0x2, +0x2, +0x39, +0x22, +0x0, +0x33, +0x21, +0x33, +0x0, +0x33, +0x0, +0x0, +0x33, +0x0, +0x0, +0x0, +0x0, +0x0, +0x22, +0x0, +0x0, +0x33, +0x20, +0x20, +0x32, +0x31, +0x32, +0x31, +0x42, +0x31, +0x32, +0x20, +0x0, +0x23, +0x9, +0x2e, +0xe, +0xe, +0x9, +0x29, +0x3, +0x29, +0x29, +0x9, +0x2a, +0x9, +0x9, +0x2a, +0x8, +0x9, +0x8, +0x29, +0x29, +0x8, +0x9, +0x2e, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x8, +0x3, +0x23, +0x1, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x21, +0x33, +0x0, +0x22, +0x39, +0x1, +0x2, +0x2, +0x3, +0x2, +0x29, +0x3, +0x2, +0x2, +0x39, +0x0, +0x33, +0x20, +0x31, +0x42, +0x41, +0x42, +0x42, +0x31, +0x20, +0x0, +0x2, +0xc, +0xe, +0xe, +0xa, +0x2, +0x29, +0x8, +0x9, +0x9, +0x9, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x29, +0x9, +0xc, +0xe, +0xf, +0xe, +0x2e, +0xc, +0x9, +0x29, +0x2, +0x2, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x0, +0x0, +0x33, +0x0, +0x22, +0x39, +0x2, +0x2, +0x29, +0x8, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x29, +0x2, +0x1, +0x0, +0x20, +0x32, +0x41, +0x42, +0x30, +0x42, +0x31, +0x20, +0x22, +0x2, +0x2e, +0xe, +0xe, +0xa, +0x8, +0x29, +0x29, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x3, +0x29, +0x2, +0x2, +0x29, +0x3, +0x8, +0x9, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x8, +0x3, +0x2, +0x39, +0x22, +0x0, +0x0, +0x33, +0x21, +0x33, +0x0, +0x0, +0x22, +0x23, +0x2, +0x29, +0x29, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x29, +0x2, +0x2, +0x39, +0x0, +0x33, +0x20, +0x20, +0x20, +0x33, +0x21, +0x22, +0x2, +0x29, +0x2e, +0xe, +0xe, +0xa, +0x29, +0x3, +0x29, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x29, +0x8, +0x2a, +0x8, +0x8, +0x29, +0x8, +0x3, +0x29, +0x29, +0x2d, +0x2e, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x2, +0x1, +0x0, +0x33, +0x20, +0x32, +0x20, +0x20, +0x33, +0x0, +0x22, +0x23, +0x2, +0x29, +0x29, +0x8, +0x9, +0x2a, +0x29, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x39, +0x23, +0x1, +0x2, +0x2, +0x3, +0x8, +0xc, +0x2e, +0xe, +0xf, +0xc, +0x9, +0x2, +0x29, +0x8, +0x9, +0x9, +0x9, +0x9, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x8, +0x3, +0x2, +0x8, +0xc, +0xe, +0xe, +0xe, +0xa, +0x9, +0x3, +0x1, +0x0, +0x33, +0x20, +0x32, +0x32, +0x20, +0x33, +0x0, +0x22, +0x39, +0x2, +0x2, +0x29, +0x29, +0x8, +0x8, +0x29, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x29, +0x8, +0xc, +0xc, +0x2e, +0xe, +0xe, +0xe, +0x9, +0x29, +0x3, +0x29, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0xd, +0x2e, +0xe, +0x2e, +0xa, +0x9, +0x8, +0x29, +0x29, +0xa, +0xd, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x3, +0x23, +0x0, +0x0, +0x32, +0x32, +0x31, +0x32, +0x32, +0x32, +0x20, +0x21, +0x0, +0x22, +0x22, +0x1, +0x23, +0x1, +0x23, +0x1, +0x23, +0x1, +0x1, +0x23, +0x1, +0x22, +0x1, +0x22, +0x1, +0x22, +0x2, +0x2, +0x3, +0x9, +0x9, +0xa, +0x2e, +0xe, +0xe, +0xe, +0xc, +0x8, +0x3, +0x9, +0xa, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0x9, +0x2a, +0x8, +0x9, +0xe, +0xe, +0x2e, +0xc, +0x2b, +0x8, +0x29, +0x1, +0x22, +0x21, +0x20, +0x32, +0x31, +0x32, +0x31, +0x31, +0x32, +0x32, +0x20, +0x20, +0x33, +0x21, +0x33, +0x21, +0x21, +0x33, +0x21, +0x0, +0x33, +0x0, +0x0, +0x0, +0x0, +0x0, +0x22, +0x0, +0x22, +0x22, +0x39, +0x2, +0x29, +0x8, +0x9, +0xc, +0x2e, +0xe, +0xf, +0xd, +0x9, +0x3, +0x29, +0x9, +0xc, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xe, +0xc, +0x9, +0x3, +0x8, +0x2e, +0xf, +0xe, +0x2e, +0xa, +0x9, +0x29, +0x2, +0x1, +0x0, +0x33, +0x20, +0x32, +0x31, +0x42, +0x31, +0x42, +0x31, +0x20, +0x20, +0x33, +0x21, +0x0, +0x0, +0x22, +0x22, +0x0, +0x22, +0x0, +0x0, +0x0, +0x33, +0x0, +0x33, +0x21, +0x20, +0x33, +0x20, +0x33, +0x0, +0x22, +0x2, +0x2, +0x29, +0x9, +0x2e, +0x2e, +0xe, +0xf, +0x2e, +0x9, +0x29, +0x3, +0x29, +0x9, +0x9, +0xa, +0xc, +0xa, +0x9, +0x29, +0x8, +0x29, +0xc, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x8, +0x3, +0x1, +0x22, +0x21, +0x32, +0x31, +0x42, +0x42, +0x30, +0x30, +0x42, +0x31, +0x32, +0x33, +0x0, +0x39, +0x2, +0x2, +0x29, +0x3, +0x8, +0x2, +0x2, +0x39, +0x0, +0x33, +0x20, +0x31, +0x42, +0x42, +0x30, +0x42, +0x42, +0x31, +0x20, +0x22, +0x1, +0x3, +0x8, +0xc, +0xb, +0xe, +0xe, +0xf, +0x2e, +0x9, +0x8, +0x2, +0x29, +0x29, +0x29, +0x8, +0x8, +0x29, +0x2, +0x8, +0xc, +0xe, +0xf, +0xe, +0x2e, +0xa, +0x9, +0x29, +0x2, +0x1, +0x22, +0x33, +0x20, +0x31, +0x42, +0x30, +0x30, +0x30, +0x42, +0x31, +0x20, +0x0, +0x22, +0x2, +0x8, +0x29, +0x9, +0x9, +0x9, +0x8, +0x3, +0x1, +0x22, +0x33, +0x31, +0x42, +0x30, +0x30, +0x30, +0x30, +0x30, +0x42, +0x32, +0x21, +0x1, +0x2, +0x8, +0x9, +0xa, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0x9, +0x3, +0x2, +0x29, +0x29, +0x29, +0x8, +0x3, +0x2, +0x9, +0xc, +0xe, +0xf, +0xd, +0x2e, +0xa, +0x9, +0x29, +0x2, +0x2, +0x39, +0x22, +0x21, +0x33, +0x33, +0x20, +0x20, +0x20, +0x33, +0x0, +0x22, +0x1, +0x2, +0x29, +0x2a, +0x9, +0x9, +0xa, +0x9, +0x9, +0x29, +0x2, +0x2, +0x22, +0x21, +0x32, +0x32, +0x31, +0x32, +0x31, +0x20, +0x20, +0x33, +0x0, +0x2, +0x2, +0x2, +0x29, +0x9, +0x9, +0xb, +0xd, +0xe, +0xe, +0x2e, +0x9, +0x3, +0x2, +0x29, +0x8, +0x3, +0x2, +0x29, +0x9, +0x2e, +0xf, +0xe, +0xe, +0xc, +0x2b, +0x9, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x8, +0x8, +0x29, +0x8, +0x9, +0x9, +0x9, +0xa, +0x2d, +0xa, +0xc, +0x9, +0x9, +0x8, +0x29, +0x2, +0x2, +0x1, +0x22, +0x22, +0x22, +0x39, +0x39, +0x39, +0x39, +0x39, +0x2, +0x2, +0x2, +0x29, +0x9, +0x9, +0x2e, +0xd, +0xe, +0xe, +0x2e, +0x9, +0x3, +0x2, +0x29, +0x29, +0x8, +0x2, +0x29, +0x9, +0x2e, +0xf, +0xe, +0xd, +0x2e, +0xa, +0x9, +0x8, +0x29, +0x3, +0x3, +0x2, +0x8, +0x8, +0x29, +0x29, +0x29, +0x29, +0x8, +0x29, +0x9, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x3, +0x2, +0x2, +0x23, +0x1, +0x39, +0x1, +0x22, +0x23, +0x39, +0x23, +0x3, +0x29, +0x9, +0xa, +0x2e, +0xd, +0xe, +0xe, +0x2e, +0x9, +0x8, +0x3, +0x29, +0x8, +0x9, +0x8, +0x2a, +0x29, +0x3, +0x8, +0x9, +0x2e, +0xf, +0xe, +0x2e, +0xc, +0x2b, +0x9, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x23, +0x23, +0x1, +0x2, +0x1, +0x23, +0x1, +0x39, +0x1, +0x22, +0x22, +0x39, +0x22, +0x22, +0x22, +0x0, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x33, +0x0, +0x0, +0x39, +0x23, +0x29, +0x9, +0x2e, +0xe, +0xe, +0xf, +0x2e, +0x9, +0x8, +0x2, +0x29, +0x29, +0x9, +0x9, +0x9, +0xa, +0x9, +0x9, +0x8, +0x2, +0x8, +0xa, +0xe, +0xf, +0xe, +0x2e, +0xc, +0x2b, +0x9, +0x29, +0x2, +0x2, +0x1, +0x22, +0x22, +0x0, +0x0, +0x0, +0x0, +0x33, +0x21, +0x20, +0x20, +0x32, +0x32, +0x31, +0x31, +0x42, +0x42, +0x31, +0x42, +0x31, +0x31, +0x43, +0x31, +0x32, +0x31, +0x32, +0x32, +0x32, +0x20, +0x33, +0x39, +0x2, +0x9, +0xc, +0x2e, +0xe, +0xf, +0x2e, +0x9, +0x8, +0x2, +0x3, +0x29, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x29, +0x3, +0x2, +0x9, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xa, +0x9, +0x29, +0x2, +0x2, +0x39, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x21, +0x33, +0x20, +0x20, +0x32, +0x32, +0x32, +0x31, +0x31, +0x43, +0x31, +0x32, +0x32, +0x20, +0x20, +0x20, +0x33, +0x20, +0x33, +0x0, +0x0, +0x22, +0x2, +0x2, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0x9, +0x8, +0x2, +0x2, +0x29, +0x3, +0x3, +0x3, +0x2, +0x29, +0x2, +0x29, +0x2, +0x8, +0x2, +0x2, +0x2, +0x29, +0x8, +0x9, +0x2e, +0xe, +0xe, +0xe, +0xb, +0x2d, +0x2a, +0x29, +0x2, +0x1, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x0, +0x22, +0x0, +0x22, +0x22, +0x39, +0x39, +0x1, +0x23, +0x2, +0x2, +0x2, +0x8, +0x2, +0x29, +0x29, +0x9, +0x9, +0xe, +0xe, +0xf, +0x2e, +0x9, +0x29, +0x2, +0x3, +0x2, +0x8, +0x2, +0x2, +0x2, +0x3, +0x29, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x3, +0x2, +0x3, +0x8, +0xc, +0xe, +0xe, +0xe, +0x2e, +0xa, +0x8, +0x8, +0x2, +0x1, +0x22, +0x39, +0x39, +0x1, +0x23, +0x1, +0x23, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x29, +0x29, +0x29, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0xc, +0x2e, +0xe, +0xe, +0xf, +0x2e, +0xa, +0x29, +0x2, +0x2, +0x2, +0x2, +0x29, +0x29, +0x29, +0x9, +0x9, +0xa, +0x9, +0x9, +0xa, +0x9, +0xc, +0x2b, +0xc, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0xc, +0xa, +0x9, +0x8, +0x29, +0x29, +0x2, +0x2, +0x3, +0x2, +0x29, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x29, +0x29, +0x8, +0x9, +0x9, +0x9, +0xa, +0xa, +0x2d, +0xa, +0xc, +0x2e, +0x2e, +0xe, +0xe, +0xf, +0xe, +0x2e, +0x9, +0x8, +0x29, +0x29, +0x8, +0x9, +0xa, +0x2e, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0xf, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xa, +0x9, +0x9, +0x29, +0x29, +0x29, +0x8, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x29, +0x29, +0x2a, +0x9, +0xa, +0xc, +0xc, +0x2e, +0x2e, +0xb, +0x2e, +0x2e, +0x2e, +0xd, +0xd, +0xe, +0xe, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xf, +0xf, +0xe, +0xe, +0xd, +0xb, +0xc, +0xa, +0x9, +0x29, +0x29, +0x3, +0x3, +0x29, +0x29, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x3, +0x29, +0x8, +0x9, +0x9, +0xa, +0x2d, +0xa, +0xc, +0xa, +0xa, +0x2d, +0xa, +0xd, +0x8, +0x9, +0x9, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xe, +0x2e, +0xc, +0x2b, +0x9, +0x29, +0x29, +0x2a, +0x29, +0x9, +0x9, +0xa, +0xd, +0xe, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0x2d, +0x9, +0x9, +0x2a, +0x29, +0x29, +0x3, +0x3, +0x2, +0x2, +0x3, +0x2, +0x2, +0x3, +0x2, +0x2, +0x2, +0x2, +0x23, +0x23, +0x1, +0x22, +0x1, +0x22, +0x1, +0x22, +0x1, +0x39, +0x1, +0x23, +0x1, +0x23, +0x1, +0x39, +0x1, +0x23, +0x29, +0x22, +0x1, +0x2, +0x3, +0x8, +0x9, +0xc, +0x2e, +0xe, +0xf, +0xc, +0x9, +0x2, +0x29, +0x29, +0x2a, +0x29, +0x8, +0x29, +0x2, +0x3, +0x8, +0x9, +0x2e, +0xe, +0xf, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x8, +0x3, +0x2, +0x39, +0x22, +0x0, +0x22, +0x0, +0x22, +0x22, +0x22, +0x22, +0x39, +0x39, +0x39, +0x39, +0x22, +0x0, +0x0, +0x0, +0x33, +0x20, +0x32, +0x32, +0x31, +0x31, +0x42, +0x31, +0x42, +0x31, +0x31, +0x32, +0x0, +0x22, +0x1, +0x2, +0x8, +0x8, +0x9, +0xa, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0x9, +0x8, +0x8, +0x8, +0x8, +0x29, +0x29, +0x8, +0x2a, +0x9, +0xc, +0xb, +0xd, +0xf, +0xf, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x9, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x23, +0x1, +0x39, +0x22, +0x0, +0x33, +0x20, +0x32, +0x31, +0x42, +0x42, +0x42, +0x42, +0x31, +0x32, +0x32, +0x20, +0x2, +0x2, +0x29, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0x2e, +0xe, +0x2e, +0xe, +0xf, +0xf, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0x2e, +0xc, +0xc, +0xa, +0xc, +0xa, +0xc, +0xa, +0xc, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x2, +0x39, +0x0, +0x33, +0x20, +0x32, +0x31, +0x42, +0x31, +0x32, +0x20, +0x33, +0x0, +0x2, +0x29, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0xf, +0xe, +0xf, +0xe, +0xe, +0xf, +0xf, +0xe, +0xf, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0x2e, +0xd, +0xb, +0x2e, +0x2e, +0xc, +0xc, +0xa, +0x9, +0x29, +0x2, +0x39, +0x0, +0x33, +0x20, +0x32, +0x31, +0x32, +0x32, +0x33, +0x21, +0x22, +0x2, +0x29, +0x9, +0xa, +0xc, +0xc, +0xb, +0x2e, +0xd, +0x2e, +0xe, +0x2e, +0xd, +0x2e, +0xe, +0x2e, +0xd, +0x2e, +0xe, +0xe, +0xd, +0xe, +0xe, +0xe, +0xd, +0xe, +0x2e, +0x2e, +0xd, +0x2e, +0xd, +0x2e, +0xe, +0xe, +0xe, +0xd, +0xe, +0xe, +0xe, +0x2e, +0xd, +0xb, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x9, +0x8, +0x3, +0x2, +0x1, +0x22, +0x0, +0x33, +0x32, +0x20, +0x32, +0x32, +0x20, +0x33, +0x0, +0x1, +0x3, +0x29, +0x9, +0xa, +0xc, +0xc, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xf, +0xf, +0xe, +0xe, +0xe, +0xf, +0xe, +0xf, +0xe, +0xd, +0xb, +0xc, +0x9, +0x9, +0x2a, +0x9, +0x2a, +0x9, +0x9, +0x9, +0xa, +0xc, +0xc, +0xb, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0x2b, +0x9, +0x8, +0x3, +0x2, +0x2, +0x1, +0x23, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x20, +0x32, +0x32, +0x20, +0x20, +0x33, +0x21, +0x22, +0x1, +0x2, +0x29, +0x8, +0x9, +0x9, +0xa, +0xc, +0xc, +0xb, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xd, +0x2e, +0xa, +0x9, +0x9, +0x29, +0x29, +0x8, +0x29, +0x8, +0x29, +0x9, +0x9, +0xa, +0xc, +0xc, +0xa, +0x2e, +0xc, +0xc, +0xa, +0x9, +0x9, +0x8, +0x8, +0x2, +0x2, +0x1, +0x22, +0x39, +0x22, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x33, +0x21, +0x33, +0x0, +0x0, +0x0, +0x22, +0x2, +0x1, +0x23, +0x1, +0x1, +0x23, +0x2, +0x2, +0x2, +0x29, +0x29, +0x8, +0x8, +0x9, +0x8, +0x9, +0x9, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0xa, +0x9, +0x2d, +0xa, +0xc, +0xa, +0x2d, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x9, +0x8, +0x9, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x8, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x23, +0x0, +0x0, +0x20, +0x20, +0x32, +0x20, +0x20, +0x20, +0x20, +0x33, +0x20, +0x33, +0x21, +0x33, +0x0, +0x33, +0x0, +0x0, +0x39, +0x2, +0x29, +0x9, +0x9, +0x2e, +0x2e, +0xd, +0xe, +0x2e, +0x2e, +0xb, +0xc, +0x9, +0x9, +0x29, +0x2, +0x2, +0x2, +0x2, +0x2, +0x3, +0x29, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0x2e, +0xd, +0xb, +0x2e, +0xc, +0xa, +0x2d, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x9, +0x2a, +0x29, +0x29, +0x2, +0x1, +0x22, +0x33, +0x20, +0x32, +0x32, +0x31, +0x32, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x33, +0x0, +0x22, +0x23, +0x2, +0x8, +0x9, +0x9, +0xc, +0x2e, +0xc, +0xa, +0xc, +0xa, +0x9, +0x9, +0x2a, +0x29, +0x29, +0x29, +0x29, +0x29, +0x9, +0x9, +0x9, +0xc, +0x2e, +0xb, +0xd, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0xc, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x29, +0x3, +0x1, +0x1, +0x22, +0x0, +0x0, +0x33, +0x20, +0x33, +0x20, +0x33, +0x20, +0x20, +0x20, +0x20, +0x32, +0x32, +0x20, +0x32, +0x20, +0x33, +0x21, +0x33, +0x0, +0x22, +0x22, +0x39, +0x23, +0x2, +0x2, +0x29, +0x8, +0x9, +0x9, +0xc, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xd, +0x2e, +0x2e, +0x2e, +0xc, +0xc, +0xa, +0x2d, +0x2b, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x29, +0x8, +0x2, +0x2, +0x39, +0x39, +0x0, +0x0, +0x0, +0x33, +0x21, +0x21, +0x33, +0x33, +0x20, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x20, +0x21, +0x0, +0x1, +0x2, +0x8, +0xc, +0x2e, +0xd, +0xe, +0xf, +0xf, +0xf, +0xf, +0xf, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0x2b, +0x9, +0x2a, +0x29, +0x8, +0x8, +0x8, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x8, +0x29, +0x3, +0x2, +0x2, +0x1, +0x1, +0x22, +0x22, +0x22, +0x0, +0x33, +0x21, +0x32, +0x32, +0x20, +0x32, +0x31, +0x32, +0x32, +0x32, +0x20, +0x20, +0x20, +0x33, +0x0, +0x0, +0x22, +0x39, +0x2, +0x2, +0x29, +0x9, +0x9, +0xa, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0xc, +0x9, +0x9, +0x9, +0x29, +0x29, +0x29, +0x8, +0x2a, +0x9, +0x9, +0x9, +0x9, +0xa, +0x9, +0xa, +0x9, +0x9, +0x9, +0x29, +0x9, +0x29, +0x8, +0x29, +0x8, +0x2, +0x2, +0x2, +0x39, +0x22, +0x21, +0x33, +0x32, +0x32, +0x31, +0x31, +0x32, +0x31, +0x20, +0x33, +0x0, +0x22, +0x1, +0x2, +0x3, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x29, +0x29, +0x29, +0x29, +0x8, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0xa, +0xa, +0x9, +0xa, +0xa, +0x9, +0xa, +0x9, +0x8, +0x8, +0x29, +0x3, +0x3, +0x2, +0x2, +0x1, +0x22, +0x0, +0x33, +0x32, +0x31, +0x32, +0x42, +0x42, +0x31, +0x31, +0x32, +0x33, +0x0, +0x39, +0x2, +0x3, +0x8, +0x9, +0xa, +0xc, +0xa, +0xc, +0x2b, +0x9, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x8, +0x29, +0x29, +0x9, +0x9, +0x9, +0xa, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x2a, +0x8, +0x8, +0x9, +0x0, +0x0, +0x33, +0x33, +0x20, +0x20, +0x32, +0x32, +0x31, +0x42, +0x30, +0x30, +0x30, +0x30, +0x40, +0x30, +0x30, +0x30, +0x42, +0x32, +0x33, +0x39, +0x2, +0x29, +0x9, +0x9, +0xc, +0xc, +0x2e, +0xc, +0xa, +0xc, +0x9, +0x9, +0x2a, +0x8, +0x8, +0x29, +0x8, +0x9, +0x9, +0x9, +0xc, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x8, +0x29, +0x2, +0x1, +0x22, +0x22, +0x22, +0x22, +0x21, +0x33, +0x0, +0x33, +0x1, +0x30, +0x30, +0x30, +0x30, +0x40, +0x30, +0x40, +0x40, +0x40, +0x40, +0x63, +0x40, +0x40, +0x40, +0x63, +0x40, +0x40, +0x40, +0x30, +0x42, +0x20, +0x0, +0x2, +0x29, +0x9, +0xa, +0xc, +0xb, +0x2e, +0x2e, +0xb, +0xc, +0xc, +0xa, +0xa, +0x9, +0x9, +0x9, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0x9, +0x29, +0x2, +0x22, +0x33, +0x20, +0x31, +0x42, +0x31, +0x42, +0x42, +0x42, +0x41, +0x31, +0x32, +0x31, +0x42, +0x42, +0x41, +0x30, +0x30, +0x30, +0x30, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x30, +0x30, +0x30, +0x32, +0x20, +0x0, +0x23, +0x29, +0x8, +0x9, +0xc, +0xc, +0x2e, +0x2e, +0xc, +0xc, +0xa, +0x2d, +0xa, +0x9, +0x9, +0xa, +0x9, +0xc, +0xc, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0xa, +0x8, +0x29, +0x23, +0x22, +0x21, +0x33, +0x33, +0x20, +0x33, +0x0, +0x33, +0x21, +0x32, +0x2, +0x2, +0x1, +0x22, +0x22, +0x22, +0x0, +0x0, +0x33, +0x20, +0x20, +0x32, +0x32, +0x31, +0x31, +0x42, +0x31, +0x32, +0x32, +0x20, +0x21, +0x0, +0x22, +0x2, +0x2, +0x29, +0x29, +0x9, +0x9, +0x9, +0x9, +0x9, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0xa, +0xc, +0xc, +0x2e, +0xb, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x2a, +0x8, +0x9, +0x8, +0x29, +0x2a, +0x9, +0x8, +0x8, +0x29, +0x9, +0x2a, +0x8, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x33, +0x0, +0x33, +0x21, +0x0, +0x0, +0x22, +0x39, +0x39, +0x2, +0x2, +0x3, +0x29, +0x8, +0x2a, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0xa, +0xc, +0xc, +0xc, +0xc, +0x2e, +0xc, +0xc, +0xa, +0x2d, +0xa, +0xa, +0x2d, +0xa, +0xc, +0xc, +0xa, +0xc, +0xc, +0xc, +0xa, +0xc, +0xa, +0x9, +0x3, +0x3, +0x2, +0x2, +0x2, +0x2, +0x23, +0x1, +0x39, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x33, +0x21, +0x33, +0x0, +0x22, +0x39, +0x1, +0x2, +0x2, +0x29, +0x8, +0x9, +0x9, +0x9, +0xa, +0x2d, +0xa, +0xa, +0x2d, +0xa, +0x9, +0xa, +0x9, +0xa, +0xa, +0x9, +0xa, +0xc, +0x9, +0x9, +0x9, +0x9, +0x9, +0x29, +0x8, +0x29, +0x8, +0x8, +0x29, +0x8, +0x8, +0x8, +0x29, +0x29, +0x3, +0x29, +0x8, +0x29, +0x8, +0x22, +0x0, +0x22, +0x22, +0x0, +0x0, +0x0, +0x0, +0x33, +0x0, +0x33, +0x0, +0x33, +0x33, +0x21, +0x20, +0x33, +0x0, +0x0, +0x22, +0x2, +0x2, +0x29, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xc, +0xc, +0xc, +0xa, +0xa, +0x9, +0x9, +0x29, +0x3, +0x2, +0x2, +0x23, +0x1, +0x22, +0x22, +0x22, +0x22, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x33, +0x0, +0x0, +0x0, +0x22, +0x33, +0x21, +0x33, +0x0, +0x33, +0x0, +0x33, +0x0, +0x21, +0x33, +0x21, +0x33, +0x0, +0x0, +0x33, +0x21, +0x0, +0x0, +0x22, +0x2, +0x3, +0x29, +0x9, +0xc, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0x2e, +0xd, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xc, +0xc, +0xa, +0xa, +0x9, +0x9, +0x29, +0x3, +0x2, +0x2, +0x39, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x33, +0x20, +0x20, +0x20, +0x32, +0x32, +0x32, +0x32, +0x20, +0x20, +0x33, +0x31, +0x32, +0x31, +0x32, +0x32, +0x32, +0x20, +0x20, +0x33, +0x0, +0x0, +0x0, +0x22, +0x22, +0x39, +0x39, +0x1, +0x23, +0x2, +0x29, +0x8, +0x9, +0xc, +0xb, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0xa, +0x2d, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x8, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x1, +0x22, +0x0, +0x0, +0x20, +0x32, +0x32, +0x31, +0x42, +0x31, +0x42, +0x42, +0x31, +0x42, +0x32, +0x30, +0x42, +0x41, +0x42, +0x31, +0x42, +0x31, +0x32, +0x20, +0x21, +0x0, +0x22, +0x23, +0x2, +0x2, +0x2, +0x8, +0x8, +0x29, +0x9, +0xa, +0xc, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xa, +0x9, +0x9, +0x29, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x8, +0x29, +0x2, +0x2, +0x22, +0x21, +0x32, +0x32, +0x42, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x42, +0x42, +0x31, +0x42, +0x31, +0x32, +0x20, +0x21, +0x22, +0x1, +0x2, +0x3, +0x29, +0x8, +0x9, +0x2a, +0x9, +0x9, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x2a, +0x29, +0x9, +0x8, +0x8, +0x8, +0x8, +0x8, +0x29, +0x8, +0x8, +0x8, +0x29, +0x3, +0x2, +0x23, +0x22, +0x21, +0x20, +0x32, +0x42, +0x41, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x42, +0x42, +0x31, +0x42, +0x31, +0x32, +0x31, +0x33, +0x21, +0x22, +0x2, +0x2, +0x8, +0x9, +0xa, +0xc, +0xa, +0xc, +0xa, +0xa, +0x9, +0x9, +0x9, +0x8, +0x8, +0x29, +0x8, +0x8, +0x29, +0x29, +0x29, +0x29, +0x9, +0x9, +0x9, +0xa, +0xc, +0xa, +0xc, +0xa, +0x2d, +0x9, +0x9, +0x9, +0x8, +0x29, +0x29, +0x3, +0x2, +0x2, +0x2, +0x39, +0x22, +0x0, +0x33, +0x32, +0x32, +0x31, +0x42, +0x42, +0x31, +0x42, +0x31, +0x42, +0x42, +0x32, +0x31, +0x32, +0x31, +0x20, +0x20, +0x0, +0x22, +0x2, +0x2, +0x8, +0xc, +0xa, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x29, +0x2, +0x2, +0x39, +0x22, +0x0, +0x22, +0x39, +0x23, +0x2, +0x29, +0x2a, +0x9, +0xc, +0xc, +0xb, +0x2e, +0xc, +0xc, +0xa, +0x9, +0x9, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x23, +0x1, +0x22, +0x0, +0x33, +0x20, +0x20, +0x32, +0x31, +0x32, +0x31, +0x32, +0x31, +0x32, +0x31, +0x33, +0x21, +0x33, +0x0, +0x22, +0x39, +0x2, +0x2, +0x29, +0x9, +0x9, +0xc, +0xc, +0xb, +0xd, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x29, +0x3, +0x2, +0x1, +0x22, +0x39, +0x39, +0x39, +0x2, +0x2, +0x3, +0x29, +0x8, +0x9, +0x2a, +0x9, +0x8, +0x9, +0x9, +0x2a, +0x8, +0x8, +0x2a, +0x8, +0x8, +0x8, +0x29, +0x3, +0x2, +0x2, +0x1, +0x22, +0x0, +0x0, +0x33, +0x33, +0x20, +0x33, +0x21, +0x33, +0x33, +0x20, +0x23, +0x2, +0x2, +0x3, +0x29, +0x29, +0x9, +0x9, +0xa, +0x2d, +0xa, +0xc, +0xc, +0xc, +0x2e, +0xc, +0xc, +0xc, +0xc, +0xa, +0xa, +0x9, +0x9, +0x8, +0x8, +0x3, +0x2, +0x2, +0x23, +0x1, +0x22, +0x39, +0x39, +0x39, +0x1, +0x22, +0x39, +0x39, +0x1, +0x2, +0x2, +0x29, +0x8, +0x9, +0x9, +0xa, +0x2d, +0xa, +0x2d, +0x9, +0x9, +0x8, +0x29, +0x3, +0x2, +0x23, +0x1, +0x22, +0x22, +0x39, +0x1, +0x22, +0x1, +0x22, +0x3b, +0x3, +0x8, +0x29, +0x9, +0x9, +0xc, +0xc, +0xb, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0xa, +0x9, +0x9, +0x29, +0x3, +0x2, +0x2, +0x1, +0x22, +0x22, +0x22, +0x0, +0x0, +0x0, +0x0, +0x22, +0x39, +0x2, +0x2, +0x29, +0x9, +0x9, +0xa, +0xc, +0xc, +0xa, +0xa, +0x9, +0x9, +0x8, +0x3, +0x2, +0x2, +0x1, +0x22, +0x22, +0x22, +0x22, +0x39, +0x39, +0x2, +0x1, +0x2, +0x2, +0x29, +0x9, +0x9, +0xc, +0xb, +0xd, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xf, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xd, +0x2e, +0x2e, +0x2d, +0x9, +0x9, +0x29, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x3, +0x3, +0x3, +0x8, +0x8, +0x2a, +0x2a, +0x9, +0x2a, +0x9, +0x8, +0x8, +0x29, +0x2, +0x2, +0x22, +0x0, +0x0, +0x0, +0x33, +0x20, +0x20, +0x20, +0x20, +0x33, +0x39, +0x22, +0x1, +0x2, +0x29, +0x9, +0x9, +0xc, +0x2e, +0xe, +0xe, +0xf, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xd, +0xe, +0xe, +0xf, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x8, +0x29, +0x29, +0x29, +0x3, +0x3, +0x2, +0x2, +0x3, +0x2, +0x23, +0x39, +0x0, +0x33, +0x32, +0x31, +0x42, +0x42, +0x42, +0x41, +0x42, +0x31, +0x32, +0x33, +0x1, +0x2, +0x8, +0x9, +0xc, +0xb, +0xd, +0xe, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0xc, +0xa, +0x9, +0xa, +0xc, +0x2e, +0x2e, +0xe, +0xe, +0xf, +0xe, +0xe, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x29, +0x2a, +0x29, +0x8, +0x8, +0x9, +0x29, +0x29, +0x8, +0x3, +0x2, +0x2, +0x2, +0x2, +0x1, +0x1, +0x23, +0x39, +0x22, +0x0, +0x33, +0x20, +0x32, +0x31, +0x42, +0x42, +0x30, +0x42, +0x31, +0x32, +0x20, +0x33, +0x8, +0x9, +0x2e, +0xe, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x9, +0x9, +0xc, +0x25, +0x4, +0x4, +0x2b, +0x9, +0xc, +0x2e, +0xe, +0xf, +0xe, +0xe, +0x2e, +0xc, +0x9, +0x29, +0x3, +0x2, +0x2, +0x23, +0x1, +0x1, +0x23, +0x1, +0x1, +0x23, +0x1, +0x23, +0x1, +0x22, +0x22, +0x22, +0x0, +0x0, +0x0, +0x33, +0x0, +0x0, +0x33, +0x21, +0x20, +0x20, +0x32, +0x32, +0x32, +0x31, +0x32, +0x31, +0x32, +0x32, +0x21, +0x0, +0x39, +0x9, +0x2e, +0xe, +0xf, +0xc, +0x9, +0x8, +0x2, +0x2, +0x2, +0x3, +0x2, +0x29, +0x8, +0x9, +0x9, +0x9, +0xc, +0x2e, +0xe, +0xf, +0xe, +0xb, +0xc, +0x9, +0x3, +0x2, +0x39, +0x22, +0x0, +0x0, +0x33, +0x0, +0x0, +0x0, +0x22, +0x0, +0x22, +0x0, +0x0, +0x0, +0x33, +0x21, +0x32, +0x20, +0x32, +0x32, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x32, +0x32, +0x20, +0x20, +0x33, +0x0, +0x1, +0x3, +0xc, +0x2e, +0xe, +0xe, +0xa, +0x8, +0x2, +0x29, +0x29, +0x29, +0x29, +0x29, +0x29, +0x29, +0x29, +0x29, +0x3, +0x29, +0x8, +0xa, +0xd, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x2, +0x2, +0x1, +0x22, +0x22, +0x22, +0x22, +0x22, +0x22, +0x39, +0x22, +0x39, +0x39, +0x22, +0x0, +0x33, +0x20, +0x32, +0x31, +0x42, +0x42, +0x42, +0x42, +0x42, +0x31, +0x32, +0x31, +0x20, +0x20, +0x20, +0x33, +0x0, +0x33, +0x0, +0x0, +0x39, +0x2, +0x8, +0xc, +0xe, +0xe, +0xe, +0xa, +0x29, +0x2, +0x8, +0x9, +0x9, +0x9, +0xa, +0xc, +0xa, +0xc, +0xa, +0xc, +0x9, +0x8, +0x8, +0x29, +0xc, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x2, +0x39, +0x0, +0x33, +0x32, +0x31, +0x30, +0x30, +0x40, +0x40, +0x30, +0x30, +0x30, +0x42, +0x32, +0x32, +0x0, +0x0, +0x22, +0x22, +0x39, +0x39, +0x23, +0x2, +0x29, +0x9, +0xc, +0xe, +0xc, +0x8, +0x9, +0xc, +0x2e, +0xe, +0x2e, +0x9, +0x29, +0x2e, +0xe, +0x9, +0x8, +0x2, +0x2, +0x2, +0x1, +0x22, +0x21, +0x32, +0x30, +0x30, +0x30, +0x42, +0x32, +0x33, +0x0, +0x0, +0x22, +0x8, +0x9, +0x2e, +0xe, +0x9, +0x29, +0xa, +0xe, +0xe, +0xe, +0xc, +0x8, +0x9, +0xe, +0x2e, +0x9, +0x2, +0x39, +0x0, +0x33, +0x0, +0x33, +0x21, +0x33, +0x33, +0x20, +0x33, +0x20, +0x32, +0x31, +0x32, +0x20, +0x22, +0x2e, +0x2e, +0x8, +0x29, +0x9, +0x29, +0x8, +0x29, +0x29, +0x9, +0x2e, +0xe, +0xc, +0x8, +0x2, +0x22, +0x0, +0x0, +0x33, +0x0, +0x39, +0x2, +0x29, +0x8, +0x29, +0x2, +0x0, +0x32, +0x41, +0x42, +0x32, +0x1, +0xd, +0x2e, +0x3, +0x8, +0x9, +0x9, +0x29, +0x29, +0x29, +0x29, +0x9, +0xa, +0xd, +0xb, +0x9, +0x2, +0x22, +0x20, +0x20, +0x0, +0x22, +0x2, +0x29, +0x9, +0x2a, +0x29, +0x2, +0x22, +0x0, +0x0, +0x1, +0x8, +0x2e, +0xe, +0x9, +0x29, +0x9, +0xa, +0xc, +0xc, +0xa, +0x9, +0x8, +0x8, +0x2e, +0xe, +0xc, +0x3, +0x0, +0x20, +0x32, +0x32, +0x21, +0x22, +0x2, +0x2, +0x3, +0x2, +0x2, +0x2, +0x2, +0x23, +0x2, +0x9, +0x9, +0x2e, +0xe, +0xa, +0x29, +0xc, +0xe, +0xe, +0xe, +0xc, +0x8, +0xd, +0x2e, +0xa, +0x29, +0x22, +0x20, +0x32, +0x31, +0x31, +0x32, +0x33, +0x0, +0x0, +0x0, +0x0, +0x33, +0x0, +0x0, +0x33, +0x0, +0x2, +0x2, +0xa, +0xd, +0xe, +0x9, +0x29, +0x2a, +0x9, +0x2a, +0x29, +0xc, +0xe, +0x2e, +0x9, +0x23, +0x0, +0x32, +0x30, +0x30, +0x42, +0x33, +0x1, +0x3, +0x29, +0x29, +0x2, +0x21, +0x43, +0x30, +0x30, +0x42, +0x21, +0x2, +0x8, +0xa, +0xe, +0xe, +0x9, +0x3, +0x29, +0x3, +0x29, +0xe, +0xe, +0xa, +0x9, +0x2, +0x23, +0x39, +0x22, +0x22, +0x1, +0x2, +0x8, +0x9, +0xa, +0x9, +0x29, +0x2, +0x22, +0x20, +0x33, +0x0, +0x22, +0x2, +0x9, +0xc, +0xe, +0x2e, +0x9, +0x3, +0x29, +0x29, +0x8, +0x2e, +0xe, +0xc, +0x9, +0x3, +0x3, +0x2, +0x2, +0x8, +0x2, +0x29, +0x3, +0x8, +0x8, +0x2, +0x2, +0x23, +0x1, +0x22, +0x22, +0x22, +0x1, +0x9, +0xd, +0xe, +0x9, +0x3, +0x29, +0x9, +0x9, +0x9, +0x29, +0x2a, +0xe, +0xe, +0xc, +0x2a, +0x8, +0x1, +0x22, +0x0, +0x0, +0x33, +0x20, +0x32, +0x31, +0x31, +0x31, +0x32, +0x32, +0x20, +0x20, +0x0, +0x23, +0xe, +0xe, +0x9, +0x2, +0x8, +0x2, +0x3, +0x29, +0x2, +0x2, +0x2, +0x29, +0x9, +0xe, +0xd, +0xa, +0x8, +0x1, +0x22, +0x22, +0x39, +0x39, +0x1, +0x1, +0x23, +0x1, +0x2, +0x3, +0x29, +0x8, +0x9, +0x9, +0xe, +0xe, +0x9, +0x3, +0x3, +0x2a, +0x2d, +0xb, +0xd, +0xb, +0xd, +0xb, +0x2e, +0xc, +0xa, +0x9, +0x29, +0x8, +0x29, +0x8, +0x29, +0x3, +0x2, +0x2, +0x2, +0x29, +0x9, +0x9, +0xc, +0xa, +0x2e, +0x2e, +0xc, +0x2e, +0xd, +0xb, +0x2e, +0xc, +0xa, +0xc, +0x2e, +0x2e, +0xe, +0x2e, +0xc, +0x9, +0x8, +0x8, +0x29, +0x8, +0x8, +0x29, +0x8, +0x3, +0x2, +0x2, +0x2, +0x2, +0x2, +0x29, +0x8, +0x29, +0x29, +0x9, +0x22, +0x2, +0x9, +0x2e, +0xe, +0x2e, +0x29, +0x8, +0x8, +0x29, +0x29, +0xc, +0xe, +0xe, +0x2e, +0x9, +0x8, +0x1, +0x22, +0x1, +0x22, +0x23, +0x1, +0x22, +0x22, +0x0, +0x20, +0x32, +0x42, +0x31, +0x42, +0x20, +0x2, +0x9, +0xc, +0xb, +0xd, +0xe, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xe, +0xf, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0x2e, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x29, +0x39, +0x33, +0x32, +0x31, +0x20, +0x0, +0x29, +0x9, +0x2e, +0x2e, +0xe, +0xe, +0xe, +0xe, +0xe, +0xe, +0xd, +0xb, +0xc, +0xa, +0xc, +0x2e, +0x2e, +0x2e, +0xd, +0x2e, +0xc, +0x2b, +0x8, +0x29, +0x2, +0x1, +0x22, +0x33, +0x20, +0x32, +0x33, +0x1, +0x2, +0x3, +0x29, +0x2a, +0x9, +0xc, +0xa, +0xc, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0x3, +0x3, +0x2, +0x2, +0x39, +0x22, +0x22, +0x39, +0x39, +0x1, +0x0, +0x32, +0x32, +0x20, +0x20, +0x20, +0x20, +0x20, +0x33, +0x39, +0x29, +0x9, +0x2e, +0x2e, +0x2e, +0xa, +0x8, +0x29, +0x2, +0x29, +0x9, +0xc, +0xb, +0xd, +0x2e, +0xa, +0xa, +0x9, +0x9, +0x9, +0x8, +0x2, +0x1, +0x0, +0x33, +0x21, +0x33, +0x20, +0x20, +0x32, +0x20, +0x20, +0x20, +0x33, +0x0, +0x39, +0x2, +0x9, +0x2e, +0xe, +0xe, +0xe, +0xd, +0xb, +0xc, +0x9, +0x9, +0x29, +0x9, +0x9, +0x9, +0x9, +0x9, +0x3, +0x29, +0x2, +0x2, +0x1, +0x0, +0x33, +0x32, +0x31, +0x32, +0x20, +0x33, +0x39, +0x2, +0x8, +0x29, +0x9, +0x9, +0xa, +0x9, +0x9, +0xa, +0x2d, +0x2b, +0x9, +0x2a, +0x2a, +0x9, +0x9, +0xa, +0x9, +0xa, +0x9, +0x2, +0x39, +0x22, +0x0, +0x20, +0x31, +0x42, +0x30, +0x30, +0x32, +0x0, +0x2, +0x9, +0xc, +0xa, +0x2d, +0x2a, +0x29, +0x3, +0x29, +0x2a, +0x2d, +0xa, +0xc, +0xa, +0x9, +0x29, +0x3, +0x2, +0x2, +0x2, +0x2, +0x42, +0x30, +0x30, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x42, +0x21, +0x2, +0x9, +0x2e, +0x2e, +0x2e, +0xa, +0xa, +0x9, +0xa, +0xc, +0x2e, +0xe, +0xd, +0xb, +0x9, +0x2, +0x33, +0x20, +0x32, +0x32, +0x32, +0x3, +0x2, +0x2, +0x39, +0x0, +0x33, +0x20, +0x32, +0x20, +0x33, +0x0, +0x39, +0x2, +0x8, +0x9, +0x9, +0x9, +0x9, +0x9, +0x9, +0xc, +0x2e, +0x2e, +0x2e, +0xa, +0x2d, +0x9, +0x9, +0x9, +0x9, +0x9, +0x2a, +0x23, +0x1, +0x22, +0x22, +0x0, +0x0, +0x33, +0x20, +0x0, +0x0, +0x2, +0x29, +0x9, +0xa, +0xc, +0xc, +0xa, +0xc, +0xa, +0xc, +0xa, +0x9, +0x8, +0x29, +0x2, +0x2, +0x2, +0x2, +0x23, +0x1, +0x23, +0x2, +0x20, +0x20, +0x20, +0x20, +0x33, +0x21, +0x0, +0x22, +0x22, +0x2, +0x8, +0xc, +0x2e, +0xe, +0xd, +0x2e, +0x2e, +0xc, +0xa, +0x9, +0x9, +0x29, +0x2, +0x23, +0x22, +0x0, +0x33, +0x20, +0x32, +0x31, +0x32, +0x32, +0x30, +0x42, +0x31, +0x32, +0x0, +0x22, +0x2, +0x29, +0x8, +0x9, +0xc, +0x2e, +0xe, +0xe, +0x2e, +0x2e, +0x9, +0x9, +0x29, +0x29, +0x8, +0x8, +0x8, +0x8, +0x2, +0x1, +0x33, +0x31, +0x30, +0x30, +0x30, +0x30, +0x31, +0x32, +0x32, +0x21, +0x23, +0x29, +0xc, +0x2e, +0xc, +0xa, +0x9, +0x3, +0x2, +0x23, +0x2, +0x29, +0x9, +0xc, +0xa, +0xc, +0x9, +0x2a, +0x29, +0x2, +0x2, +0x39, +0x33, +0x20, +0x31, +0x43, +0x31, +0x42, +0x22, +0x39, +0x2, +0x29, +0x9, +0xa, +0x2e, +0x2e, +0x2e, +0xc, +0x9, +0x8, +0x2, +0x23, +0x1, +0x23, +0x2, +0x2, +0x3, +0x8, +0x29, +0x8, +0x9, +0x9, +0x9, +0x3, +0x2, +0x22, +0x0, +0x0, +0x0, +0x0, +0x2, +0x29, +0x9, +0xc, +0x2e, +0xe, +0xd, +0xe, +0xe, +0xe, +0x2e, +0x2e, +0xa, +0x9, +0x29, +0x2, +0x23, +0x1, +0x22, +0x2, +0x3, +0x8, +0x9, +0x9, +0x9, +0x8, +0x2, +0x1, +0x0, +0x0, +0x0, +0x22, +0x1, +0x29, +0xa, +0xd, +0xe, +0xe, +0x2e, +0x2e, +0xc, +0xb, +0xd, +0xe, +0xe, +0x2e, +0xa, +0x9, +0x9, +0x9, +0x8, +0x9, +0x29, +0x3, +0x2, +0x2, +0x2, +0x22, +0x33, +0x32, +0x41, +0x42, +0x31, +0x20, +0x9, +0xe, +0x2e, +0x9, +0x8, +0x8, +0x2c, +0x9, +0x2d, +0xe, +0xe, +0x2e, +0x9, +0x2, +0x1, +0x22, +0x22, +0x22, +0x22, +0x22, +0x0, +0x0, +0x33, +0x20, +0x20, +0x20, +0x32, +0x20, +0x32, +0x32, +0x33, +0x1, +0x2e, +0xe, +0x9, +0x3, +0x29, +0x9, +0x9, +0x2a, +0x9, +0x8, +0x2e, +0xe, +0xa, +0x29, +0x2, +0x39, +0x1, +0x1, +0x23, +0x22, +0x21, +0x32, +0x30, +0x30, +0x30, +0x42, +0x32, +0x21, +0x0, +0x0, +0x1, +0x3, +0x2e, +0xa, +0x9, +0xe, +0xc, +0x9, +0x2e, +0x29, +0x39, +0x0, +0x33, +0x31, +0x32, +0x20, +0x33, +0x39, +0x2e, +0x8, +0x9, +0x8, +0x8, +0x2e, +0xc, +0x2, +0x0, +0x33, +0x23, +0x8, +0x29, +0x0, +0x20, +0x22, +0x2e, +0xa, +0x9, +0xd, +0xc, +0x2a, +0x2e, +0x29, +0x20, +0x32, +0x21, +0x22, +0x39, +0x22, +0x22, +0x2, +0x29, +0x2e, +0x9, +0x8, +0x8, +0xd, +0x2b, +0x1, +0x33, +0x20, +0x1, +0x2a, +0x29, +0x0, +0x32, +0x20, +0x9, +0x2e, +0x9, +0x8, +0x8, +0x2e, +0xc, +0x3, +0x2, +0x39, +0x39, +0x0, +0x0, +0x0, +0x33, +0x39, +0xe, +0x8, +0x29, +0x9, +0x9, +0x9, +0xc, +0xa, +0x29, +0x2, +0x2, +0x2, +0x2, +0x8, +0x9, +0xa, +0x2a, +0xc, +0x2e, +0x9, +0x9, +0x2e, +0x2e, +0x9, +0x29, +0x2, +0x2, +0x23, +0x1, +0x22, +0x0, +0x39, +0x8, +0x2e, +0xe, +0xd, +0xe, +0xe, +0x2e, +0x2e, +0xd, +0xb, +0xc, +0x9, +0x29, +0x0, +0x32, +0x21, +0x22, +0x39, +0x2, +0x2, +0x29, +0x9, +0xa, +0x9, +0x9, +0x8, +0x9, +0x9, +0x2a, +0x29, +0x2, +0x2, +0x2, +0x22, +0x33, +0x32, +0x20, +0x0, +0x1, +0x2a, +0xc, +0x2e, +0xc, +0xa, +0x8, +0x9, +0x9, +0x2a, +0x33, +0x31, +0x42, +0x30, +0x42, +0x39, +0xa, +0xc, +0x9, +0x9, +0xa, +0x2e, +0x9, +0x2, +0x0, +0x0, +0x2, +0x39, +0x0, +0x20, +0x33, +0x1, +0x2a, +0xc, +0x2b, +0x2d, +0xa, +0x9, +0x8, +0x8, +0x29, +0x8, +0x31, +0x32, +0x0, +0x23, +0x29, +0xc, +0xe, +0x2e, +0xa, +0x9, +0x8, +0x8, +0x39, +0x20, +0x42, +0x42, +0x33, +0x1, +0x8, +0x2e, +0xc, +0x8, +0x2, +0x2, +0x29, +0x9, +0x9, +0x8, +0x2, +0x22, +0x20, +0x20, +0x2, +0xc, +0xe, +0x2e, +0x2e, +0xd, +0xa, +0x9, +0x2, +0x29, +0x8, +0x29, +0x2, +0x0, +0x20, +0x33, +0x2e, +0x9, +0x2a, +0x9, +0x9, +0xe, +0x29, +0x1, +0x22, +0x39, +0x33, +0x31, +0x32, +0x20, +0x33, +0x39, +0xa, +0x9, +0xc, +0x9, +0x0, +0x22, +0x0, +0x21, +0xa, +0x9, +0x2d, +0x2a, +0x20, +0x1, +0x1, +0x0, +0xc, +0x2a, +0x9, +0x9, +0x2, +0x39, +0x23, +0x2, +0x9, +0x2e, +0x2e, +0x2e, +0x9, +0x8, +0x39, +0x0, +0x39, +0x22, +0x1, +0x2a, +0x9, +0x9, +0x9, +0x29, +0x0, +0x32, +0x21, +0x2b, +0x9, +0xc, +0x8, +0x23, +0x20, +0x3, +0x9, +0x9, +0x9, +0x8, +0x22, +0x32, +0x9, +0xc, +0xb, +0x8, +0x2, +0x39, +0x0, +0x33, +0xa, +0x9, +0x0, +0x0, +0xa, +0xc, +0x3, +0x1, +0x0, +0x2, +0xa, +0x29, +0x29, +0x9, +0x3, +0x33, +0x9, +0x1, +0x2, +0x3, +0x3, +0x0, +0x0, +0x0 +}; + +#undef RAW_NAME +#undef IMAGE_NAME +#define RAW_NAME hilite_3dfinfo_raw +#define IMAGE_NAME hilite_3dfinfo_image +unsigned char RAW_NAME[] = { +0x20, +0x0, +0x0, +0x0, +0x20, +0x0, +0x0, +0x0, +0x8, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0xff, +0x1, +0xfc, +0x1, +0xee, +0x1, +0x19, +0x0, +0x10, +0x0, +0xe5, +0x1, +0x11, +0x0, +0x6, +0x0, +0xe8, +0x1, +0x9, +0x0, +0x8, +0x0, +0xeb, +0x1, +0x1, +0x0, +0x4, +0x0, +0x22, +0x22, +0x2b, +0x3c, +0x44, +0x44, +0x66, +0x77, +0x88, +0x99, +0xaa, +0xbb, +0xcc, +0xdd, +0xee, +0xff, +0x23, +0x4e, +0x3c, +0x7, +0xef, +0x1, +0x4, +0x0, +0x12, +0x1c, +0x88, +0x7, +0xfc, +0xff, +0xd3, +0x7, +0x10, +0x32, +0xb8, +0x7, +0x6, +0x22, +0x94, +0x7, +0x8, +0x12, +0xa0, +0x7, +0x4, +0x2, +0xac, +0x7, +0x62, +0x0, +0x0, +0x0, +0x63, +0x0, +0x0, +0x0, +0x64, +0x0, +0x0, +0x0, +0x65, +0x0, +0x0, +0x0, +0x66, +0x0, +0x0, +0x0, +0x67, +0x0, +0x0, +0x0, +0x69, +0x0, +0x0, +0x0, +0x6a, +0x0, +0x0, +0x0, +0x6b, +0x0, +0x0, +0x0, +0x6c, +0x0, +0x0, +0x0, +0x6d, +0x0, +0x0, +0x0, +0x6e, +0x0, +0x0, +0x0, +0x6f, +0x0, +0x0, +0x0, +0x70, +0x0, +0x0, +0x0, +0x71, +0x0, +0x0, +0x0, +0x72, +0x0, +0x0, +0x0, +0x73, +0x0, +0x0, +0x0, +0x74, +0x0, +0x0, +0x0, +0x75, +0x0, +0x0, +0x0, +0x76, +0x0, +0x0, +0x0, +0x77, +0x0, +0x0, +0x0, +0x78, +0x0, +0x0, +0x0, +0x79, +0x0, +0x0, +0x0, +0x7a, +0x0, +0x0, +0x0, +0x7b, +0x0, +0x0, +0x0, +0x7c, +0x0, +0x0, +0x0, +0x7d, +0x0, +0x0, +0x0, +0x7e, +0x0, +0x0, +0x0, +0x7f, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0x81, +0x0, +0x0, +0x0, +0x82, +0x0, +0x0, +0x0, +0x83, +0x0, +0x0, +0x0, +0x84, +0x0, +0x0, +0x0, +0x85, +0x0, +0x0, +0x0, +0x86, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x88, +0x0, +0x0, +0x0, +0x89, +0x0, +0x0, +0x0, +0x8a, +0x0, +0x0, +0x0, +0x8b, +0x0, +0x0, +0x0, +0x8c, +0x0, +0x0, +0x0, +0x8d, +0x0, +0x0, +0x0, +0x8e, +0x0, +0x0, +0x0, +0x8f, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x91, +0x0, +0x0, +0x0, +0x92, +0x0, +0x0, +0x0, +0x93, +0x0, +0x0, +0x0, +0x94, +0x0, +0x0, +0x0, +0x95, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x97, +0x0, +0x0, +0x0, +0xeb, +0xa5, +0x40, +0x0, +0x41, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xb8, +0xfc, +0x7b, +0x0, +0xd4, +0xfc, +0x7b, +0x0, +0xc, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x0, +0x0, +0x0, +0x0, +0x94, +0xa4, +0x40, +0x0, +0x12, +0x9f, +0x40, +0x0, +0x12, +0x9f, +0x40, +0x0, +0xa, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xbc, +0xfc, +0x7b, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1, +0x0, +0x0, +0x0, +0x68, +0x82, +0xe2, +0x0, +0xa6, +0x0, +0x0, +0x0, +0xa7, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa9, +0x0, +0x0, +0x0, +0xaa, +0x0, +0x0, +0x0, +0xab, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xad, +0x0, +0x0, +0x0, +0xae, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xb0, +0x0, +0x0, +0x0, +0xb1, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb3, +0x0, +0x0, +0x0, +0xb4, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb6, +0x0, +0x0, +0x0, +0xb7, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb9, +0x0, +0x0, +0x0, +0xba, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbc, +0x0, +0x0, +0x0, +0xbd, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbf, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc1, +0x0, +0x0, +0x0, +0xc2, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc4, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc6, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc8, +0x0, +0x0, +0x0, +0xc9, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xcb, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcd, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xcf, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd1, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xd3, +0x0, +0x0, +0x0, +0xd4, +0x0, +0x0, +0x0, +0xd4, +0x0, +0x0, +0x0, +0xd5, +0x0, +0x0, +0x0, +0xd6, +0x0, +0x0, +0x0, +0xd6, +0x0, +0x0, +0x0, +0xd7, +0x0, +0x0, +0x0, +0xd8, +0x0, +0x0, +0x0, +0xd8, +0x0, +0x0, +0x0, +0xd9, +0x0, +0x0, +0x0, +0xda, +0x0, +0x0, +0x0, +0xda, +0x0, +0x0, +0x0, +0xdb, +0x0, +0x0, +0x0, +0xdc, +0x0, +0x0, +0x0, +0xdc, +0x0, +0x0, +0x0, +0xdd, +0x0, +0x0, +0x0, +0xde, +0x0, +0x0, +0x0, +0xde, +0x0, +0x0, +0x0, +0xdf, +0x0, +0x0, +0x0, +0xe0, +0x0, +0x0, +0x0, +0xe0, +0x0, +0x0, +0x0, +0xe1, +0x0, +0x0, +0x0, +0xe2, +0x0, +0x0, +0x0, +0xe2, +0x0, +0x0, +0x0, +0xe3, +0x0, +0x0, +0x0, +0xe3, +0x0, +0x0, +0x0, +0xe4, +0x0, +0x0, +0x0, +0xe5, +0x0, +0x0, +0x0, +0xe5, +0x0, +0x0, +0x0, +0xe6, +0x0, +0x0, +0x0, +0xe7, +0x0, +0x0, +0x0, +0xe7, +0x0, +0x0, +0x0, +0xe8, +0x0, +0x0, +0x0, +0xe9, +0x0, +0x0, +0x0, +0xe9, +0x0, +0x0, +0x0, +0xea, +0x0, +0x0, +0x0, +0xea, +0x0, +0x0, +0x0, +0xeb, +0x0, +0x0, +0x0, +0xec, +0x0, +0x0, +0x0, +0xec, +0x0, +0x0, +0x0, +0xed, +0x0, +0x0, +0x0, +0xee, +0x0, +0x0, +0x0, +0xee, +0x0, +0x0, +0x0, +0xef, +0x0, +0x0, +0x0, +0xef, +0x0, +0x0, +0x0, +0xf0, +0x0, +0x0, +0x0, +0xf1, +0x0, +0x0, +0x0, +0xf1, +0x0, +0x0, +0x0, +0xf2, +0x0, +0x0, +0x0, +0xf2, +0x0, +0x0, +0x0, +0xf3, +0x0, +0x0, +0x0, +0xf4, +0x0, +0x0, +0x0, +0xf4, +0x0, +0x0, +0x0, +0xf5, +0x0, +0x0, +0x0, +0xf5, +0x0, +0x0, +0x0, +0xf6, +0x0, +0x0, +0x0, +0xf7, +0x0, +0x0, +0x0, +0xf7, +0x0, +0x0, +0x0, +0xf8, +0x0, +0x0, +0x0, +0xf8, +0x0, +0x0, +0x0, +0xf9, +0x0, +0x0, +0x0, +0xfa, +0x0, +0x0, +0x0, +0xfa, +0x0, +0x0, +0x0, +0xfb, +0x0, +0x0, +0x0, +0xfb, +0x0, +0x0, +0x0, +0xfc, +0x0, +0x0, +0x0, +0xfd, +0x0, +0x0, +0x0, +0xfd, +0x0, +0x0, +0x0, +0xfe, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1b, +0x0, +0x0, +0x0, +0x1b, +0x0, +0x0, +0x0, +0x0, +0x0, +0x41, +0x0, +0x41, +0x95, +0x40, +0x0, +0x2, +0x0, +0x0, +0x0, +0x40, +0x69, +0xa0, +0x0, +0x1a, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1a, +0x0, +0x0, +0x0, +0xd8, +0x9c, +0x40, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1, +0x0, +0x0, +0x0, +0xfd, +0x90, +0x40, +0x0, +0x1, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x3c, +0x83, +0xe2, +0x0, +0x48, +0x8, +0x0, +0x0, +0x68, +0x82, +0xe2, +0x0, +0xf, +0x21, +0x40, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xec, +0x41, +0x55, +0x0, +0x38, +0xfe, +0x7b, +0x0, +0x74, +0xe4, +0x61, +0x81, +0x94, +0xdf, +0x61, +0x81, +0x0, +0x0, +0x6b, +0x0, +0xe0, +0xae, +0xa0, +0x0, +0x58, +0x5, +0x0, +0x0 +}; + +unsigned char IMAGE_NAME[] = { +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x3, +0x2, +0x2, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x2, +0x5, +0x7, +0xc, +0xb, +0xb, +0x7, +0x5, +0x2, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x7, +0xb, +0xe, +0x11, +0x16, +0x16, +0x15, +0x11, +0xe, +0xa, +0x6, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0x8, +0x10, +0x14, +0x17, +0x1a, +0x20, +0x21, +0x1e, +0x1a, +0x17, +0x14, +0xe, +0x8, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x8, +0x10, +0x16, +0x20, +0x22, +0x26, +0x2d, +0x2f, +0x2b, +0x26, +0x21, +0x1b, +0x16, +0x10, +0x8, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x7, +0xf, +0x16, +0x1f, +0x28, +0x30, +0x35, +0x3d, +0x40, +0x3d, +0x36, +0x2d, +0x26, +0x1f, +0x16, +0xf, +0x7, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x4, +0xc, +0x15, +0x1c, +0x28, +0x31, +0x41, +0x46, +0x4f, +0x54, +0x50, +0x47, +0x3f, +0x31, +0x28, +0x1c, +0x15, +0xc, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x7, +0x11, +0x1a, +0x25, +0x31, +0x3e, +0x4d, +0x60, +0x66, +0x79, +0x64, +0x5e, +0x4d, +0x3e, +0x31, +0x25, +0x1a, +0x11, +0x7, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0xb, +0x14, +0x1f, +0x2a, +0x39, +0x4a, +0x63, +0x76, +0x94, +0xa4, +0x8c, +0x76, +0x5a, +0x4a, +0x39, +0x2a, +0x1f, +0x14, +0xb, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x4, +0xe, +0x16, +0x21, +0x2f, +0x40, +0x54, +0x6a, +0x91, +0xcf, +0xd9, +0xc5, +0x95, +0x76, +0x54, +0x40, +0x2f, +0x21, +0x16, +0xe, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x6, +0x10, +0x1b, +0x27, +0x35, +0x47, +0x60, +0x81, +0xc1, +0xeb, +0xff, +0xe8, +0xb8, +0x73, +0x5d, +0x44, +0x31, +0x23, +0x17, +0xe, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x4, +0xe, +0x17, +0x27, +0x38, +0x4e, +0x69, +0x95, +0xc7, +0xec, +0xff, +0xe6, +0xbe, +0x81, +0x5c, +0x45, +0x31, +0x23, +0x17, +0xe, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0xb, +0x16, +0x1c, +0x2a, +0x3a, +0x4e, +0x5b, +0x73, +0x9a, +0xd1, +0xf9, +0xc0, +0x9d, +0x70, +0x5d, +0x4b, +0x32, +0x22, +0x16, +0xe, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x6, +0x13, +0x1c, +0x21, +0x2a, +0x43, +0x53, +0x64, +0x7c, +0xa7, +0x97, +0x94, +0x7a, +0x64, +0x52, +0x3c, +0x2e, +0x1f, +0x14, +0xb, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x7, +0x11, +0x1e, +0x2c, +0x33, +0x46, +0x55, +0x69, +0x72, +0x6d, +0x6c, +0x62, +0x54, +0x46, +0x33, +0x25, +0x1a, +0x11, +0x7, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x4, +0x11, +0x15, +0x1c, +0x28, +0x34, +0x47, +0x56, +0x55, +0x55, +0x54, +0x4b, +0x47, +0x34, +0x28, +0x1c, +0x15, +0xc, +0x4, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x7, +0xf, +0x16, +0x1f, +0x2a, +0x34, +0x42, +0x3f, +0x3f, +0x3f, +0x3d, +0x30, +0x29, +0x1f, +0x16, +0xf, +0x7, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x8, +0x10, +0x16, +0x1e, +0x25, +0x2e, +0x2c, +0x2c, +0x2c, +0x28, +0x21, +0x1b, +0x16, +0x10, +0x8, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0x8, +0xe, +0x14, +0x19, +0x1c, +0x1c, +0x1c, +0x1c, +0x1a, +0x17, +0x14, +0xe, +0x8, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x6, +0xa, +0x11, +0x11, +0x13, +0x13, +0x13, +0x11, +0xe, +0xa, +0x6, +0x2, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x2, +0xa, +0x7, +0x8, +0x8, +0x8, +0x7, +0x5, +0x2, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x1, +0x1, +0x1, +0x1, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x59, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x2, +0x5, +0x6, +0x4, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x9, +0x11, +0x19, +0x1b, +0x14, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x8, +0x17, +0x27, +0x31, +0x35, +0x2b, +0x1e, +0xf, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0x13, +0x26, +0x3f, +0x57, +0x60, +0x4c, +0x32, +0x1c, +0xa, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x8, +0x1a, +0x35, +0x5b, +0x9b, +0xb4, +0x77, +0x46, +0x26, +0x11, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0xa, +0x20, +0x41, +0x78, +0xd8, +0xf3, +0x9a, +0x51, +0x2a, +0x13, +0x2, +0x0, +0x0, +0x0, +0x0, +0x1, +0xe, +0x20, +0x3d, +0x62, +0xa4, +0xb9, +0x7b, +0x4e, +0x28, +0x11, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0x15, +0x29, +0x46, +0x62, +0x60, +0x52, +0x35, +0x1c, +0xa, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x8, +0x17, +0x28, +0x37, +0x35, +0x2e, +0x1e, +0xf, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1, +0x8, +0x12, +0x17, +0x18, +0x14, +0xc, +0x3, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0x4, +0x5, +0x4, +0x1, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x16, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x3, +0xd, +0xf, +0x4, +0x0, +0x0, +0x0, +0x1, +0x16, +0x3c, +0x44, +0x1f, +0x3, +0x0, +0x0, +0x4, +0x2c, +0x92, +0xae, +0x3a, +0xa, +0x0, +0x0, +0x4, +0x27, +0x6c, +0x7a, +0x32, +0x7, +0x0, +0x0, +0x0, +0xa, +0x22, +0x24, +0xf, +0x1, +0x0, +0x0, +0x0, +0x0, +0x2, +0x2, +0x0, +0x0, +0x0, +0x5, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x4, +0x5, +0x0, +0x1, +0x44, +0x53, +0x3, +0x1, +0x30, +0x38, +0x2, +0x1, +0x0, +0x0, +0x0, +0x12, +0x17, +0xd, +0xf, +0x11, +0x0, +0x0, +0x0 +}; + +#undef RAW_NAME +#undef IMAGE_NAME +#define RAW_NAME shadow_3dfinfo_raw +#define IMAGE_NAME shadow_3dfinfo_image +unsigned char RAW_NAME[] = { +0x40, +0x0, +0x0, +0x0, +0x20, +0x0, +0x0, +0x0, +0x8, +0x0, +0x0, +0x0, +0x2, +0x0, +0x0, +0x0, +0x2, +0x0, +0x0, +0x0, +0x3, +0x0, +0x0, +0x0, +0xff, +0x1, +0xfc, +0x1, +0xee, +0x1, +0x19, +0x0, +0x10, +0x0, +0xe5, +0x1, +0x11, +0x0, +0x6, +0x0, +0xe8, +0x1, +0x9, +0x0, +0x8, +0x0, +0xeb, +0x1, +0x1, +0x0, +0x4, +0x0, +0x22, +0x22, +0x2b, +0x3c, +0x44, +0x44, +0x66, +0x77, +0x88, +0x99, +0xaa, +0xbb, +0xcc, +0xdd, +0xee, +0xff, +0x23, +0x4e, +0x3c, +0x7, +0xef, +0x1, +0x4, +0x0, +0x12, +0x1c, +0x88, +0x7, +0xfc, +0xff, +0xd3, +0x7, +0x10, +0x32, +0xb8, +0x7, +0x6, +0x22, +0x94, +0x7, +0x8, +0x12, +0xa0, +0x7, +0x4, +0x2, +0xac, +0x7, +0x62, +0x0, +0x0, +0x0, +0x63, +0x0, +0x0, +0x0, +0x64, +0x0, +0x0, +0x0, +0x65, +0x0, +0x0, +0x0, +0x66, +0x0, +0x0, +0x0, +0x67, +0x0, +0x0, +0x0, +0x69, +0x0, +0x0, +0x0, +0x6a, +0x0, +0x0, +0x0, +0x6b, +0x0, +0x0, +0x0, +0x6c, +0x0, +0x0, +0x0, +0x6d, +0x0, +0x0, +0x0, +0x6e, +0x0, +0x0, +0x0, +0x6f, +0x0, +0x0, +0x0, +0x70, +0x0, +0x0, +0x0, +0x71, +0x0, +0x0, +0x0, +0x72, +0x0, +0x0, +0x0, +0x73, +0x0, +0x0, +0x0, +0x74, +0x0, +0x0, +0x0, +0x75, +0x0, +0x0, +0x0, +0x76, +0x0, +0x0, +0x0, +0x77, +0x0, +0x0, +0x0, +0x78, +0x0, +0x0, +0x0, +0x79, +0x0, +0x0, +0x0, +0x7a, +0x0, +0x0, +0x0, +0x7b, +0x0, +0x0, +0x0, +0x7c, +0x0, +0x0, +0x0, +0x7d, +0x0, +0x0, +0x0, +0x7e, +0x0, +0x0, +0x0, +0x7f, +0x0, +0x0, +0x0, +0x80, +0x0, +0x0, +0x0, +0x81, +0x0, +0x0, +0x0, +0x82, +0x0, +0x0, +0x0, +0x83, +0x0, +0x0, +0x0, +0x84, +0x0, +0x0, +0x0, +0x85, +0x0, +0x0, +0x0, +0x86, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x87, +0x0, +0x0, +0x0, +0x88, +0x0, +0x0, +0x0, +0x89, +0x0, +0x0, +0x0, +0x8a, +0x0, +0x0, +0x0, +0x8b, +0x0, +0x0, +0x0, +0x8c, +0x0, +0x0, +0x0, +0x8d, +0x0, +0x0, +0x0, +0x8e, +0x0, +0x0, +0x0, +0x8f, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x90, +0x0, +0x0, +0x0, +0x91, +0x0, +0x0, +0x0, +0x92, +0x0, +0x0, +0x0, +0x93, +0x0, +0x0, +0x0, +0x94, +0x0, +0x0, +0x0, +0x95, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x96, +0x0, +0x0, +0x0, +0x97, +0x0, +0x0, +0x0, +0xeb, +0xa5, +0x40, +0x0, +0x41, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xb8, +0xfc, +0x7b, +0x0, +0xd4, +0xfc, +0x7b, +0x0, +0xc, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x0, +0x0, +0x0, +0x0, +0x94, +0xa4, +0x40, +0x0, +0x12, +0x9f, +0x40, +0x0, +0x12, +0x9f, +0x40, +0x0, +0xa, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xbc, +0xfc, +0x7b, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1, +0x0, +0x0, +0x0, +0x68, +0x82, +0xe2, +0x0, +0xa6, +0x0, +0x0, +0x0, +0xa7, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa8, +0x0, +0x0, +0x0, +0xa9, +0x0, +0x0, +0x0, +0xaa, +0x0, +0x0, +0x0, +0xab, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xac, +0x0, +0x0, +0x0, +0xad, +0x0, +0x0, +0x0, +0xae, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xaf, +0x0, +0x0, +0x0, +0xb0, +0x0, +0x0, +0x0, +0xb1, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb2, +0x0, +0x0, +0x0, +0xb3, +0x0, +0x0, +0x0, +0xb4, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb5, +0x0, +0x0, +0x0, +0xb6, +0x0, +0x0, +0x0, +0xb7, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb8, +0x0, +0x0, +0x0, +0xb9, +0x0, +0x0, +0x0, +0xba, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbb, +0x0, +0x0, +0x0, +0xbc, +0x0, +0x0, +0x0, +0xbd, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbe, +0x0, +0x0, +0x0, +0xbf, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc0, +0x0, +0x0, +0x0, +0xc1, +0x0, +0x0, +0x0, +0xc2, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc3, +0x0, +0x0, +0x0, +0xc4, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc5, +0x0, +0x0, +0x0, +0xc6, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc7, +0x0, +0x0, +0x0, +0xc8, +0x0, +0x0, +0x0, +0xc9, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xca, +0x0, +0x0, +0x0, +0xcb, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcc, +0x0, +0x0, +0x0, +0xcd, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xce, +0x0, +0x0, +0x0, +0xcf, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd0, +0x0, +0x0, +0x0, +0xd1, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xd2, +0x0, +0x0, +0x0, +0xd3, +0x0, +0x0, +0x0, +0xd4, +0x0, +0x0, +0x0, +0xd4, +0x0, +0x0, +0x0, +0xd5, +0x0, +0x0, +0x0, +0xd6, +0x0, +0x0, +0x0, +0xd6, +0x0, +0x0, +0x0, +0xd7, +0x0, +0x0, +0x0, +0xd8, +0x0, +0x0, +0x0, +0xd8, +0x0, +0x0, +0x0, +0xd9, +0x0, +0x0, +0x0, +0xda, +0x0, +0x0, +0x0, +0xda, +0x0, +0x0, +0x0, +0xdb, +0x0, +0x0, +0x0, +0xdc, +0x0, +0x0, +0x0, +0xdc, +0x0, +0x0, +0x0, +0xdd, +0x0, +0x0, +0x0, +0xde, +0x0, +0x0, +0x0, +0xde, +0x0, +0x0, +0x0, +0xdf, +0x0, +0x0, +0x0, +0xe0, +0x0, +0x0, +0x0, +0xe0, +0x0, +0x0, +0x0, +0xe1, +0x0, +0x0, +0x0, +0xe2, +0x0, +0x0, +0x0, +0xe2, +0x0, +0x0, +0x0, +0xe3, +0x0, +0x0, +0x0, +0xe3, +0x0, +0x0, +0x0, +0xe4, +0x0, +0x0, +0x0, +0xe5, +0x0, +0x0, +0x0, +0xe5, +0x0, +0x0, +0x0, +0xe6, +0x0, +0x0, +0x0, +0xe7, +0x0, +0x0, +0x0, +0xe7, +0x0, +0x0, +0x0, +0xe8, +0x0, +0x0, +0x0, +0xe9, +0x0, +0x0, +0x0, +0xe9, +0x0, +0x0, +0x0, +0xea, +0x0, +0x0, +0x0, +0xea, +0x0, +0x0, +0x0, +0xeb, +0x0, +0x0, +0x0, +0xec, +0x0, +0x0, +0x0, +0xec, +0x0, +0x0, +0x0, +0xed, +0x0, +0x0, +0x0, +0xee, +0x0, +0x0, +0x0, +0xee, +0x0, +0x0, +0x0, +0xef, +0x0, +0x0, +0x0, +0xef, +0x0, +0x0, +0x0, +0xf0, +0x0, +0x0, +0x0, +0xf1, +0x0, +0x0, +0x0, +0xf1, +0x0, +0x0, +0x0, +0xf2, +0x0, +0x0, +0x0, +0xf2, +0x0, +0x0, +0x0, +0xf3, +0x0, +0x0, +0x0, +0xf4, +0x0, +0x0, +0x0, +0xf4, +0x0, +0x0, +0x0, +0xf5, +0x0, +0x0, +0x0, +0xf5, +0x0, +0x0, +0x0, +0xf6, +0x0, +0x0, +0x0, +0xf7, +0x0, +0x0, +0x0, +0xf7, +0x0, +0x0, +0x0, +0xf8, +0x0, +0x0, +0x0, +0xf8, +0x0, +0x0, +0x0, +0xf9, +0x0, +0x0, +0x0, +0xfa, +0x0, +0x0, +0x0, +0xfa, +0x0, +0x0, +0x0, +0xfb, +0x0, +0x0, +0x0, +0xfb, +0x0, +0x0, +0x0, +0xfc, +0x0, +0x0, +0x0, +0xfd, +0x0, +0x0, +0x0, +0xfd, +0x0, +0x0, +0x0, +0xfe, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x0, +0x1b, +0x0, +0x0, +0x0, +0x1b, +0x0, +0x0, +0x0, +0x0, +0x0, +0x41, +0x0, +0x41, +0x95, +0x40, +0x0, +0x2, +0x0, +0x0, +0x0, +0x40, +0x69, +0xa0, +0x0, +0x1a, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1a, +0x0, +0x0, +0x0, +0xd8, +0x9c, +0x40, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x1, +0x0, +0x0, +0x0, +0xfd, +0x90, +0x40, +0x0, +0x1, +0x0, +0x0, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0x3c, +0x83, +0xe2, +0x0, +0x48, +0x8, +0x0, +0x0, +0x68, +0x82, +0xe2, +0x0, +0xf, +0x21, +0x40, +0x0, +0xc0, +0x4f, +0x55, +0x0, +0xec, +0x41, +0x55, +0x0, +0x38, +0xfe, +0x7b, +0x0, +0x74, +0xe4, +0x61, +0x81, +0x94, +0xdf, +0x61, +0x81, +0x0, +0x0, +0x6b, +0x0, +0x40, +0xc4, +0xa0, +0x0, +0xb0, +0xa, +0x0, +0x0 +}; + +unsigned char IMAGE_NAME[] = { +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xfb, +0xfa, +0xfa, +0xfb, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xf4, +0xe4, +0xd7, +0xd0, +0xcf, +0xd6, +0xe2, +0xf2, +0xfc, +0xff, +0xff, +0xfb, +0xe8, +0xdf, +0xdf, +0xdf, +0xdf, +0xde, +0xdf, +0xe0, +0xe2, +0xe7, +0xee, +0xf5, +0xfa, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf1, +0xc0, +0x94, +0x80, +0x79, +0x78, +0x7f, +0x91, +0xb1, +0xda, +0xf8, +0xfd, +0xe7, +0xab, +0x8c, +0x89, +0x89, +0x89, +0x89, +0x89, +0x8b, +0x8e, +0x96, +0xa1, +0xb4, +0xcf, +0xe8, +0xf9, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xe3, +0x93, +0x60, +0x58, +0x58, +0x57, +0x55, +0x59, +0x6b, +0x96, +0xd4, +0xf7, +0xdc, +0x88, +0x5d, +0x59, +0x59, +0x5a, +0x5a, +0x5b, +0x5b, +0x5b, +0x5d, +0x60, +0x6a, +0x7e, +0xa0, +0xcc, +0xf0, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xe2, +0x96, +0x72, +0x7a, +0x7e, +0x74, +0x60, +0x53, +0x53, +0x66, +0xa3, +0xe8, +0xdb, +0x84, +0x57, +0x52, +0x54, +0x5d, +0x67, +0x69, +0x68, +0x65, +0x5f, +0x59, +0x56, +0x58, +0x64, +0x86, +0xbc, +0xed, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xfa, +0xf7, +0xf4, +0xf3, +0xf6, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xef, +0xc8, +0xc1, +0xd1, +0xd6, +0xc4, +0x95, +0x62, +0x52, +0x57, +0x84, +0xd7, +0xd9, +0x84, +0x57, +0x52, +0x5b, +0x82, +0xac, +0xb6, +0xb4, +0xac, +0x9c, +0x83, +0x68, +0x58, +0x55, +0x5d, +0x7f, +0xc0, +0xf3, +0xff, +0xff, +0xff, +0xff, +0xf9, +0xe5, +0xcc, +0xba, +0xb0, +0xaf, +0xc4, +0xeb, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xf7, +0xf8, +0xfb, +0xfc, +0xf5, +0xc9, +0x79, +0x55, +0x54, +0x7c, +0xd0, +0xd8, +0x85, +0x58, +0x52, +0x61, +0xa1, +0xe7, +0xf6, +0xf6, +0xf3, +0xe9, +0xd1, +0xa5, +0x72, +0x58, +0x54, +0x5f, +0x8d, +0xd6, +0xfb, +0xff, +0xff, +0xf8, +0xd2, +0x9f, +0x7e, +0x77, +0x7b, +0x81, +0xa8, +0xe5, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf9, +0xd0, +0x7d, +0x55, +0x57, +0x88, +0xda, +0xd9, +0x85, +0x58, +0x53, +0x61, +0xa7, +0xf2, +0xff, +0xff, +0xff, +0xfe, +0xf9, +0xe2, +0xa7, +0x6a, +0x55, +0x56, +0x6c, +0xb2, +0xf2, +0xff, +0xfd, +0xe2, +0x9a, +0x69, +0x6c, +0x95, +0xb3, +0xbd, +0xd0, +0xed, +0xf5, +0xf8, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xf7, +0xf6, +0xf9, +0xfe, +0xfe, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf6, +0xda, +0xa6, +0x69, +0x55, +0x69, +0xaa, +0xeb, +0xdc, +0x85, +0x58, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xd4, +0x87, +0x5b, +0x55, +0x5d, +0x93, +0xe3, +0xfd, +0xfa, +0xcc, +0x7a, +0x5e, +0x85, +0xd1, +0xf3, +0xf0, +0xd8, +0xbf, +0xb7, +0xc4, +0xe5, +0xfc, +0xff, +0xff, +0xf4, +0xd2, +0xbb, +0xbc, +0xd6, +0xf1, +0xf2, +0xf0, +0xf8, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xd1, +0x94, +0x6b, +0x57, +0x64, +0x97, +0xd9, +0xf8, +0xdc, +0x84, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xec, +0xa1, +0x62, +0x54, +0x58, +0x80, +0xd4, +0xf8, +0xef, +0xbb, +0x70, +0x5f, +0x8e, +0xda, +0xf4, +0xf2, +0xd5, +0x9d, +0x77, +0x7a, +0xaa, +0xe4, +0xfc, +0xf4, +0xc8, +0x8c, +0x76, +0x93, +0xcc, +0xf2, +0xf2, +0xed, +0xf6, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf6, +0xb8, +0x6b, +0x53, +0x56, +0x75, +0xb9, +0xf1, +0xfc, +0xdb, +0x84, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf5, +0xb0, +0x67, +0x55, +0x57, +0x77, +0xc7, +0xde, +0xba, +0x90, +0x65, +0x5b, +0x77, +0xa3, +0xb5, +0xcb, +0xe5, +0xc8, +0x8e, +0x68, +0x75, +0xaf, +0xdd, +0xcc, +0x8e, +0x6c, +0x85, +0xbe, +0xed, +0xfe, +0xfd, +0xfc, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf7, +0xba, +0x6e, +0x54, +0x53, +0x64, +0x93, +0xd0, +0xf5, +0xdc, +0x84, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf6, +0xb4, +0x69, +0x56, +0x56, +0x74, +0xc0, +0xc7, +0x8f, +0x6e, +0x5b, +0x58, +0x64, +0x76, +0x80, +0xa6, +0xe7, +0xf2, +0xcc, +0x90, +0x6a, +0x77, +0x98, +0x8a, +0x70, +0x88, +0xc2, +0xef, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xd8, +0xa0, +0x76, +0x59, +0x53, +0x63, +0x96, +0xdc, +0xd9, +0x84, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf2, +0xab, +0x65, +0x55, +0x57, +0x79, +0xca, +0xdf, +0xbd, +0x91, +0x65, +0x5b, +0x78, +0xa6, +0xb8, +0xce, +0xf3, +0xff, +0xf5, +0xcd, +0x8d, +0x65, +0x64, +0x66, +0x83, +0xc4, +0xf2, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xe5, +0xb9, +0x77, +0x55, +0x53, +0x70, +0xbb, +0xd2, +0x85, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xe3, +0x95, +0x5e, +0x54, +0x59, +0x85, +0xd8, +0xf9, +0xf0, +0xba, +0x6f, +0x5f, +0x90, +0xdd, +0xf4, +0xf9, +0xff, +0xff, +0xfe, +0xe7, +0xa4, +0x6a, +0x5c, +0x63, +0x91, +0xd9, +0xfb, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xe5, +0x96, +0x5c, +0x51, +0x62, +0xa5, +0xca, +0x84, +0x57, +0x52, +0x61, +0xa7, +0xf1, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf3, +0xc0, +0x77, +0x58, +0x54, +0x61, +0x9c, +0xe8, +0xfe, +0xf8, +0xc2, +0x71, +0x60, +0x95, +0xe7, +0xfe, +0xff, +0xff, +0xfe, +0xed, +0xbf, +0x84, +0x6a, +0x70, +0x68, +0x74, +0xab, +0xe1, +0xfa, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xf8, +0xfd, +0xff, +0xff, +0xfe, +0xe8, +0x99, +0x5d, +0x52, +0x60, +0xa1, +0xc9, +0x84, +0x57, +0x52, +0x61, +0xa6, +0xef, +0xfd, +0xfd, +0xfc, +0xf9, +0xee, +0xc9, +0x8b, +0x5f, +0x54, +0x57, +0x74, +0xbd, +0xf5, +0xff, +0xf8, +0xc2, +0x71, +0x60, +0x95, +0xe7, +0xfe, +0xff, +0xfc, +0xe8, +0xb8, +0x81, +0x6f, +0x91, +0xb2, +0x96, +0x6e, +0x73, +0xa4, +0xdb, +0xf9, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xe0, +0xca, +0xdd, +0xef, +0xf5, +0xeb, +0xc3, +0x7d, +0x56, +0x52, +0x66, +0xad, +0xcd, +0x85, +0x57, +0x52, +0x5f, +0x97, +0xd3, +0xe1, +0xdf, +0xd9, +0xca, +0xad, +0x83, +0x61, +0x55, +0x55, +0x66, +0x9d, +0xe1, +0xfd, +0xff, +0xf8, +0xc2, +0x71, +0x60, +0x95, +0xe7, +0xfe, +0xfd, +0xe6, +0xb3, +0x7d, +0x6d, +0x93, +0xd0, +0xef, +0xd6, +0x98, +0x6c, +0x71, +0xa0, +0xd9, +0xf9, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf8, +0xc2, +0x85, +0x8c, +0xa4, +0xad, +0xa0, +0x7e, +0x5c, +0x51, +0x56, +0x7d, +0xc9, +0xd5, +0x84, +0x57, +0x52, +0x58, +0x6e, +0x87, +0x8c, +0x8a, +0x83, +0x77, +0x68, +0x5a, +0x54, +0x58, +0x68, +0x94, +0xd3, +0xf9, +0xff, +0xff, +0xf8, +0xc2, +0x71, +0x60, +0x95, +0xe7, +0xfd, +0xf5, +0xcd, +0x9b, +0x86, +0x9d, +0xd1, +0xf6, +0xff, +0xf8, +0xd4, +0x9e, +0x84, +0x91, +0xbd, +0xed, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf7, +0xbe, +0x6f, +0x5a, +0x5f, +0x63, +0x5f, +0x56, +0x53, +0x58, +0x71, +0xac, +0xe9, +0xdb, +0x84, +0x57, +0x53, +0x54, +0x57, +0x5b, +0x5b, +0x5b, +0x5a, +0x58, +0x57, +0x5a, +0x63, +0x79, +0xa3, +0xd5, +0xf7, +0xff, +0xff, +0xff, +0xf8, +0xc2, +0x71, +0x60, +0x95, +0xe7, +0xfd, +0xfa, +0xe6, +0xd6, +0xd5, +0xe4, +0xf8, +0xff, +0xff, +0xff, +0xf9, +0xe4, +0xd5, +0xd4, +0xe0, +0xf6, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xd2, +0x8f, +0x6d, +0x61, +0x5e, +0x5d, +0x61, +0x6c, +0x85, +0xb2, +0xe3, +0xf9, +0xdf, +0x92, +0x6a, +0x66, +0x67, +0x67, +0x67, +0x67, +0x69, +0x6c, +0x70, +0x78, +0x89, +0xa4, +0xc5, +0xe6, +0xfa, +0xff, +0xff, +0xff, +0xff, +0xf8, +0xc1, +0x71, +0x60, +0x95, +0xe7, +0xfe, +0xff, +0xfc, +0xfb, +0xfb, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xfb, +0xfb, +0xfc, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf4, +0xd8, +0xbe, +0xaa, +0xa0, +0xa0, +0xa9, +0xbb, +0xd5, +0xef, +0xfd, +0xfe, +0xf0, +0xc8, +0xb4, +0xb2, +0xb2, +0xb3, +0xb3, +0xb3, +0xb6, +0xbb, +0xc3, +0xcd, +0xdc, +0xec, +0xf8, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf9, +0xc9, +0x83, +0x73, +0xa2, +0xea, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfc, +0xf7, +0xf2, +0xee, +0xee, +0xf1, +0xf7, +0xfb, +0xff, +0xff, +0xff, +0xfe, +0xf8, +0xf5, +0xf5, +0xf5, +0xf5, +0xf5, +0xf5, +0xf6, +0xf7, +0xf8, +0xfa, +0xfc, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xe7, +0xc5, +0xbd, +0xd4, +0xf6, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xf6, +0xf6, +0xf9, +0xfd, +0xfe, +0xff, +0xff, +0xff, +0xfe, +0xfe, +0xff, +0xff, +0xfe, +0xfd, +0xfc, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xf4, +0xf1, +0xf2, +0xf3, +0xee, +0xf0, +0xf4, +0xf6, +0xf5, +0xf4, +0xf3, +0xf7, +0xf6, +0xf1, +0xea, +0xea, +0xf0, +0xf6, +0xf7, +0xf5, +0xfa, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfc, +0xe7, +0xd4, +0xce, +0xd0, +0xcb, +0xcd, +0xcd, +0xd3, +0xd4, +0xd9, +0xd3, +0xd7, +0xd8, +0xd6, +0xcc, +0xd0, +0xd4, +0xd5, +0xd3, +0xd0, +0xe7, +0xfc, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xde, +0xc5, +0xc0, +0xc4, +0xc2, +0xc1, +0xbc, +0xc5, +0xcb, +0xd5, +0xc3, +0xbf, +0xcb, +0xd7, +0xcb, +0xca, +0xc7, +0xbf, +0xbf, +0xbe, +0xe0, +0xfb, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xe3, +0xcf, +0xce, +0xd0, +0xcc, +0xc9, +0xc9, +0xd5, +0xda, +0xd9, +0xc2, +0xc2, +0xcd, +0xd8, +0xd0, +0xd2, +0xd7, +0xd2, +0xd3, +0xcf, +0xe9, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf6, +0xee, +0xee, +0xef, +0xeb, +0xe8, +0xe8, +0xef, +0xf2, +0xef, +0xe3, +0xe6, +0xe9, +0xeb, +0xe8, +0xec, +0xf4, +0xf4, +0xf3, +0xeb, +0xf6, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xfe, +0xfe, +0xfd, +0xfd, +0xfd, +0xfe, +0xfe, +0xfe, +0xfc, +0xfd, +0xfd, +0xfd, +0xfd, +0xfd, +0xff, +0xff, +0xff, +0xfd, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xfd, +0xff, +0xff, +0xff, +0xfe, +0xfe, +0xfe, +0xfe, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xcb, +0xa8, +0xa7, +0xc6, +0xf3, +0xf8, +0xc0, +0xb4, +0xb4, +0xb5, +0xbb, +0xce, +0xec, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf0, +0x7f, +0x6a, +0x60, +0x5b, +0x9d, +0xe6, +0x70, +0x56, +0x5e, +0x62, +0x5f, +0x5e, +0x77, +0xc0, +0xfa, +0xff, +0xff, +0xff, +0xfc, +0xf9, +0xfc, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfb, +0xde, +0xe8, +0xc6, +0x61, +0x6b, +0xd6, +0x6e, +0x58, +0xae, +0xd6, +0xc9, +0x98, +0x5e, +0x64, +0xc6, +0xfe, +0xfd, +0xd4, +0x9f, +0x97, +0xcf, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xd2, +0x64, +0x7d, +0xdf, +0x6f, +0x5a, +0xcc, +0xff, +0xff, +0xf5, +0x9b, +0x57, +0x84, +0xf4, +0xe9, +0x77, +0x96, +0xd5, +0xd5, +0xda, +0xf7, +0xff, +0xf0, +0xd9, +0xf0, +0xf7, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xde, +0x6f, +0x62, +0xc7, +0xeb, +0x6e, +0x5a, +0xcc, +0xff, +0xff, +0xff, +0xcd, +0x5d, +0x6a, +0xdc, +0xbd, +0x64, +0xa1, +0xda, +0xc8, +0x7a, +0xad, +0xe6, +0x94, +0x93, +0xea, +0xf6, +0xfc, +0xff, +0xff, +0xff, +0xff, +0xe1, +0x76, +0x59, +0x97, +0xe2, +0x6e, +0x5a, +0xcc, +0xff, +0xff, +0xff, +0xd2, +0x5e, +0x67, +0xcc, +0x93, +0x5d, +0x7e, +0xab, +0xf3, +0xc8, +0x75, +0x7b, +0x90, +0xe9, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xe0, +0x70, +0x5e, +0xbf, +0x6e, +0x5a, +0xcc, +0xff, +0xff, +0xfc, +0xac, +0x58, +0x77, +0xee, +0xd9, +0x68, +0xba, +0xfb, +0xff, +0xe4, +0x7f, +0x66, +0xa2, +0xf5, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf5, +0xe7, +0xf9, +0xe5, +0x72, +0x5b, +0xb9, +0x6e, +0x59, +0xc0, +0xef, +0xe6, +0xba, +0x68, +0x5a, +0xac, +0xfc, +0xdd, +0x69, +0xbe, +0xfe, +0xdf, +0x89, +0x99, +0xc3, +0x79, +0xa4, +0xf3, +0xff, +0xff, +0xff, +0xff, +0xdc, +0x77, +0x85, +0x75, +0x56, +0x7c, +0xd9, +0x6e, +0x54, +0x6a, +0x73, +0x6b, +0x5d, +0x62, +0x9d, +0xf1, +0xff, +0xdd, +0x69, +0xbe, +0xfa, +0xc9, +0xb7, +0xf0, +0xfd, +0xd4, +0xb0, +0xe0, +0xff, +0xff, +0xff, +0xff, +0xf0, +0xa5, +0x82, +0x82, +0xa0, +0xe0, +0xf2, +0x9e, +0x8c, +0x8d, +0x8e, +0x97, +0xab, +0xd3, +0xf7, +0xff, +0xff, +0xdf, +0x72, +0xc2, +0xff, +0xfd, +0xfe, +0xff, +0xff, +0xff, +0xfd, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfc, +0xf8, +0xf7, +0xfc, +0xff, +0xff, +0xfb, +0xfa, +0xfa, +0xfa, +0xfb, +0xfd, +0xff, +0xff, +0xff, +0xff, +0xf7, +0xdc, +0xf0, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf5, +0xe1, +0xdf, +0xe0, +0xe5, +0xe5, +0xe7, +0xdf, +0xe0, +0xe5, +0xea, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xee, +0xc9, +0xc9, +0xc4, +0xd0, +0xcd, +0xc6, +0xd3, +0xcf, +0xc9, +0xd6, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfd, +0xf6, +0xf5, +0xf3, +0xf7, +0xf3, +0xf2, +0xf3, +0xf7, +0xf9, +0xf7, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfe, +0xdc, +0xda, +0xfa, +0xdc, +0xd9, +0xe2, +0xfa, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfa, +0xac, +0x79, +0xb1, +0x63, +0x91, +0x88, +0x7e, +0xef, +0xf4, +0xcb, +0xf2, +0xff, +0xff, +0xff, +0xff, +0xff, +0xf6, +0x82, +0xc4, +0x64, +0xe6, +0xfd, +0x87, +0xb0, +0xa0, +0xba, +0xbc, +0xe2, +0xbc, +0xf2, +0xfe, +0xff, +0xf7, +0x88, +0xa6, +0x64, +0xe6, +0xfe, +0x8d, +0xa6, +0x8c, +0xb8, +0xe8, +0x75, +0xc4, +0xff, +0xff, +0xf4, +0xb7, +0x89, +0x9a, +0x62, +0xa3, +0x9a, +0x70, +0xe6, +0xa3, +0xdd, +0xba, +0xd2, +0xa8, +0xf4, +0xff, +0xfb, +0xc7, +0xc5, +0xf4, +0xc8, +0xc4, +0xcf, +0xf2, +0xff, +0xc9, +0xec, +0xfe, +0xff, +0xfe, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xe3, +0xd3, +0xda, +0xd8, +0xd7, +0xef, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xfc, +0xfa, +0xfa, +0xf9, +0xfc, +0xfd, +0xff, +0xe0, +0xc0, +0xaa, +0xb9, +0xf8, +0xef, +0xff, +0xff, +0xfb, +0x9d, +0xa5, +0xc4, +0xa1, +0xc6, +0xb6, +0xfc, +0xdb, +0xb7, +0xa4, +0xb3, +0xd4, +0xe0, +0xde, +0xfc, +0xff, +0xff, +0xff, +0xff, +0xf7, +0xe8, +0xe9, +0xfb, +0xce, +0xb3, +0xd4, +0xec, +0xe4, +0xd5, +0xe5, +0xf0, +0xcf, +0xe5, +0xda, +0x0, +0x0, +0x0, +0x0, +0x0 +}; + +#undef RAW_NAME +#undef IMAGE_NAME