Added mupen64plus-video-z64
This commit is contained in:
parent
8d0cfc60dc
commit
b54fb9e6a6
|
@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-audio-bkm", "..
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-input-bkm", "..\..\..\mupen64plus-input-bkm\mupen64plus-input-bkm\mupen64plus-input-bkm.vcxproj", "{3D8BD211-6002-4698-B5C1-A0F3146B6ACF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-z64", "..\..\..\mupen64plus-video-z64\projects\msvc11\mupen64plus-video-z64.vcxproj", "{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-jabo", "..\..\..\mupen64plus-video-jabo\mupen64plus-video-jabo\mupen64plus-video-jabo.vcxproj", "{0C220B26-3D4D-431D-B829-CADE6508A771}"
|
||||
EndProject
|
||||
Global
|
||||
|
@ -44,6 +46,10 @@ Global
|
|||
{3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Release|Win32.Build.0 = Release|Win32
|
||||
{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}.Release|Win32.Build.0 = Release|Win32
|
||||
{0C220B26-3D4D-431D-B829-CADE6508A771}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0C220B26-3D4D-431D-B829-CADE6508A771}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0C220B26-3D4D-431D-B829-CADE6508A771}.Release|Win32.ActiveCfg = Release|Win32
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\disasm.cpp" />
|
||||
<ClCompile Include="..\..\src\glshader.cpp" />
|
||||
<ClCompile Include="..\..\src\maingl.cpp" />
|
||||
<ClCompile Include="..\..\src\osal_dynamiclib_win32.c" />
|
||||
<ClCompile Include="..\..\src\rdp.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_debugger.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_geometry.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_glut.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_osdep.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_rendermode.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_settings.cpp" />
|
||||
<ClCompile Include="..\..\src\rgl_tiles.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\glshader.h" />
|
||||
<ClInclude Include="..\..\src\osal_dynamiclib.h" />
|
||||
<ClInclude Include="..\..\src\queue.h" />
|
||||
<ClInclude Include="..\..\src\rdp.h" />
|
||||
<ClInclude Include="..\..\src\rgl.h" />
|
||||
<ClInclude Include="..\..\src\rgl_assert.h" />
|
||||
<ClInclude Include="..\..\src\rgl_glut.h" />
|
||||
<ClInclude Include="..\..\src\z64.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7708C1D2-3303-4F90-BCE8-3BCE4046BFD7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>mupen64plusvideoz64</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)..\..\..\..\output\dll\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)..\..\..\..\output\dll\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MUPEN64PLUSVIDEOZ64_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\glew-1.10.0\include\GL</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4996;4005;4244</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;..\..\..\mupen64plus-win32-deps\glew-1.10.0\lib\Release\Win32\glew32.lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MUPEN64PLUSVIDEOZ64_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\glew-1.10.0\include\GL</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4996;4005;4244</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;..\..\..\mupen64plus-win32-deps\glew-1.10.0\lib\Release\Win32\glew32.lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,391 @@
|
|||
#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
# * Mupen64plus-video-z64 - Makefile *
|
||||
# * https://github.com/mupen64plus/mupen64plus-video-z64/ *
|
||||
# * Copyright (C) 2010 Jon Ring *
|
||||
# * Copyright (C) 2007-2009 Richard Goedeken *
|
||||
# * Copyright (C) 2007-2008 DarkJeztr Tillin9 *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU General Public License as published by *
|
||||
# * the Free Software Foundation; either version 2 of the License, or *
|
||||
# * (at your option) any later version. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU General Public License *
|
||||
# * along with this program; if not, write to the *
|
||||
# * Free Software Foundation, Inc., *
|
||||
# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
# Makefile for Z64 Video plugin in Mupen64Plus
|
||||
|
||||
# detect operating system
|
||||
UNAME ?= $(shell uname -s)
|
||||
OS := NONE
|
||||
ifeq ("$(UNAME)","Linux")
|
||||
OS = LINUX
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
endif
|
||||
ifeq ("$(UNAME)","linux")
|
||||
OS = LINUX
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
endif
|
||||
ifneq ("$(filter GNU hurd,$(UNAME))","")
|
||||
OS = LINUX
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
endif
|
||||
ifeq ("$(UNAME)","Darwin")
|
||||
OS = OSX
|
||||
SO_EXTENSION = dylib
|
||||
SHARED = -bundle
|
||||
endif
|
||||
ifeq ("$(UNAME)","FreeBSD")
|
||||
OS = FREEBSD
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
endif
|
||||
ifeq ("$(UNAME)","OpenBSD")
|
||||
OS = FREEBSD
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
$(warning OS type "$(UNAME)" not officially supported.')
|
||||
endif
|
||||
ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","")
|
||||
OS = LINUX
|
||||
SO_EXTENSION = so
|
||||
SHARED = -shared
|
||||
endif
|
||||
ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW")
|
||||
OS = MINGW
|
||||
SO_EXTENSION = dll
|
||||
SHARED = -shared
|
||||
PIC = 0
|
||||
endif
|
||||
ifeq ("$(OS)","NONE")
|
||||
$(error OS type "$(UNAME)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
|
||||
endif
|
||||
|
||||
# detect system architecture
|
||||
HOST_CPU ?= $(shell uname -m)
|
||||
CPU := NONE
|
||||
ifneq ("$(filter x86_64 amd64,$(HOST_CPU))","")
|
||||
CPU := X86
|
||||
ifeq ("$(BITS)", "32")
|
||||
ARCH_DETECTED := 64BITS_32
|
||||
PIC ?= 0
|
||||
else
|
||||
ARCH_DETECTED := 64BITS
|
||||
PIC ?= 1
|
||||
endif
|
||||
endif
|
||||
ifneq ("$(filter pentium i%86,$(HOST_CPU))","")
|
||||
CPU := X86
|
||||
ARCH_DETECTED := 32BITS
|
||||
PIC ?= 0
|
||||
endif
|
||||
ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","")
|
||||
CPU := PPC
|
||||
ARCH_DETECTED := 32BITS
|
||||
BIG_ENDIAN := 1
|
||||
PIC ?= 1
|
||||
NO_ASM := 1
|
||||
$(warning Architecture "$(HOST_CPU)" not officially supported.')
|
||||
endif
|
||||
ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","")
|
||||
CPU := PPC
|
||||
ARCH_DETECTED := 64BITS
|
||||
BIG_ENDIAN := 1
|
||||
PIC ?= 1
|
||||
NO_ASM := 1
|
||||
$(warning Architecture "$(HOST_CPU)" not officially supported.')
|
||||
endif
|
||||
ifneq ("$(filter arm%,$(HOST_CPU))","")
|
||||
ifeq ("$(filter arm%b,$(HOST_CPU))","")
|
||||
CPU := ARM
|
||||
ARCH_DETECTED := 32BITS
|
||||
PIC ?= 1
|
||||
NO_ASM := 1
|
||||
$(warning Architecture "$(HOST_CPU)" not officially supported.')
|
||||
endif
|
||||
endif
|
||||
ifeq ("$(CPU)","NONE")
|
||||
$(error CPU type "$(HOST_CPU)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
|
||||
endif
|
||||
|
||||
# base CFLAGS, LDLIBS, and LDFLAGS
|
||||
OPTFLAGS ?= -O3 -flto
|
||||
WARNFLAGS ?= -Wall
|
||||
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src
|
||||
CXXFLAGS += -fvisibility-inlines-hidden
|
||||
LDFLAGS += $(SHARED)
|
||||
|
||||
# Since we are building a shared library, we must compile with -fPIC on some architectures
|
||||
# On 32-bit x86 systems we do not want to use -fPIC because we don't have to and it has a big performance penalty on this arch
|
||||
ifeq ($(PIC), 1)
|
||||
CFLAGS += -fPIC
|
||||
else
|
||||
CFLAGS += -fno-PIC
|
||||
endif
|
||||
|
||||
ifeq ($(BIG_ENDIAN), 1)
|
||||
CFLAGS += -DM64P_BIG_ENDIAN
|
||||
endif
|
||||
|
||||
# tweak flags for 32-bit build on 64-bit system
|
||||
ifeq ($(ARCH_DETECTED), 64BITS_32)
|
||||
ifeq ($(OS), FREEBSD)
|
||||
$(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386)
|
||||
endif
|
||||
CFLAGS += -m32
|
||||
LDFLAGS += -Wl,-m,elf_i386
|
||||
endif
|
||||
|
||||
# set special flags per-system
|
||||
ifeq ($(OS), LINUX)
|
||||
# only export api symbols
|
||||
LDFLAGS += -Wl,-version-script,$(SRCDIR)/video_api_export.ver
|
||||
endif
|
||||
ifeq ($(OS), OSX)
|
||||
# Select the proper SDK
|
||||
# Also, SDKs are stored in a different location since XCode 4.3
|
||||
OSX_SDK ?= $(shell sw_vers -productVersion | cut -f1 -f2 -d .)
|
||||
OSX_XCODEMAJ = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f1 -d .)
|
||||
OSX_XCODEMIN = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f2 -d .)
|
||||
OSX_XCODEGE43 = $(shell echo "`expr $(OSX_XCODEMAJ) \>= 4``expr $(OSX_XCODEMIN) \>= 3`")
|
||||
ifeq ($(OSX_XCODEGE43), 11)
|
||||
OSX_SYSROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
|
||||
else
|
||||
OSX_SYSROOT := /Developer/SDKs
|
||||
endif
|
||||
|
||||
ifeq ($(CPU), X86)
|
||||
ifeq ($(ARCH_DETECTED), 64BITS)
|
||||
CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
|
||||
LDFLAGS += -bundle
|
||||
LDLIBS += -ldl
|
||||
else
|
||||
CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
|
||||
LDFLAGS += -bundle
|
||||
LDLIBS += -ldl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS), LINUX)
|
||||
LDLIBS += -ldl
|
||||
endif
|
||||
ifeq ($(OS), FREEBSD)
|
||||
LDLIBS += -lc
|
||||
endif
|
||||
|
||||
# test for essential build dependencies
|
||||
ifeq ($(origin PKG_CONFIG), undefined)
|
||||
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
|
||||
ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
|
||||
$(error $(PKG_CONFIG) not found)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(origin GLEW_CFLAGS) $(origin GLEW_LDLIBS), undefined undefined)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion glew 2>/dev/null),)
|
||||
$(error No GLEW development libraries found!)
|
||||
endif
|
||||
GLEW_CFLAGS += $(shell $(PKG_CONFIG) --cflags glew)
|
||||
GLEW_LDLIBS += $(shell $(PKG_CONFIG) --libs glew)
|
||||
endif
|
||||
CFLAGS += $(GLEW_CFLAGS)
|
||||
LDLIBS += $(GLEW_LDLIBS)
|
||||
|
||||
# search for OpenGL libraries
|
||||
ifeq ($(OS), OSX)
|
||||
GL_LDLIBS = -framework OpenGL
|
||||
endif
|
||||
ifeq ($(OS), MINGW)
|
||||
GL_LDLIBS = -lopengl32
|
||||
endif
|
||||
ifeq ($(origin GL_CFLAGS) $(origin GL_LDLIBS), undefined undefined)
|
||||
ifeq ($(shell $(PKG_CONFIG) --modversion gl 2>/dev/null),)
|
||||
$(error No OpenGL development libraries found!)
|
||||
endif
|
||||
GL_CFLAGS += $(shell $(PKG_CONFIG) --cflags gl)
|
||||
GL_LDLIBS += $(shell $(PKG_CONFIG) --libs gl)
|
||||
endif
|
||||
CFLAGS += $(GL_CFLAGS)
|
||||
LDLIBS += $(GL_LDLIBS)
|
||||
|
||||
# test for presence of SDL
|
||||
ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined)
|
||||
SDL_CONFIG = $(CROSS_COMPILE)sdl-config
|
||||
ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),)
|
||||
$(error No SDL development libraries found!)
|
||||
endif
|
||||
ifeq ($(OS),OSX)
|
||||
SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags)
|
||||
# sdl-config on mac screws up when we're trying to build a library and not an executable
|
||||
# SDL 1.3 is supposed to fix that, if it's ever released
|
||||
SDL_LDLIBS += -L/usr/local/lib -lSDL -Wl,-framework,Cocoa
|
||||
else
|
||||
SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags)
|
||||
SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs)
|
||||
endif
|
||||
endif
|
||||
CFLAGS += $(SDL_CFLAGS)
|
||||
LDLIBS += $(SDL_LDLIBS)
|
||||
|
||||
# set mupen64plus core API header path
|
||||
ifneq ("$(APIDIR)","")
|
||||
CFLAGS += "-I$(APIDIR)"
|
||||
else
|
||||
TRYDIR = ../../../mupen64plus-core/src/api
|
||||
ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
|
||||
CFLAGS += -I$(TRYDIR)
|
||||
else
|
||||
TRYDIR = /usr/local/include/mupen64plus
|
||||
ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
|
||||
CFLAGS += -I$(TRYDIR)
|
||||
else
|
||||
TRYDIR = /usr/include/mupen64plus
|
||||
ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
|
||||
CFLAGS += -I$(TRYDIR)
|
||||
else
|
||||
$(error Mupen64Plus API header files not found! Use makefile parameter APIDIR to force a location.)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# reduced compile output when running make without V=1
|
||||
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
||||
ifndef V
|
||||
Q_CC = @echo ' CC '$@;
|
||||
Q_CXX = @echo ' CXX '$@;
|
||||
Q_LD = @echo ' LD '$@;
|
||||
endif
|
||||
endif
|
||||
|
||||
# set base program pointers and flags
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
CXX = $(CROSS_COMPILE)g++
|
||||
RM ?= rm -f
|
||||
INSTALL ?= install
|
||||
MKDIR ?= mkdir -p
|
||||
COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
|
||||
COMPILE.cc = $(Q_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
|
||||
LINK.o = $(Q_LD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TARGET_ARCH)
|
||||
|
||||
# set special flags for given Makefile parameters
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS += -g
|
||||
INSTALL_STRIP_FLAG ?=
|
||||
else
|
||||
INSTALL_STRIP_FLAG ?= -s
|
||||
endif
|
||||
|
||||
# set installation options
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX := /usr/local
|
||||
endif
|
||||
ifeq ($(SHAREDIR),)
|
||||
SHAREDIR := $(PREFIX)/share/mupen64plus
|
||||
endif
|
||||
ifeq ($(LIBDIR),)
|
||||
LIBDIR := $(PREFIX)/lib
|
||||
endif
|
||||
ifeq ($(PLUGINDIR),)
|
||||
PLUGINDIR := $(LIBDIR)/mupen64plus
|
||||
endif
|
||||
|
||||
SRCDIR = ../../src
|
||||
OBJDIR = _obj$(POSTFIX)
|
||||
|
||||
# list of source files to compile
|
||||
SOURCE = \
|
||||
$(SRCDIR)/rgl.cpp \
|
||||
$(SRCDIR)/rgl_settings.cpp \
|
||||
$(SRCDIR)/rgl_tiles.cpp \
|
||||
$(SRCDIR)/rgl_rendermode.cpp \
|
||||
$(SRCDIR)/rgl_geometry.cpp \
|
||||
$(SRCDIR)/rgl_debugger.cpp \
|
||||
$(SRCDIR)/rgl_osdep.cpp \
|
||||
$(SRCDIR)/rdp.cpp \
|
||||
$(SRCDIR)/glshader.cpp \
|
||||
$(SRCDIR)/disasm.cpp \
|
||||
$(SRCDIR)/maingl.cpp
|
||||
|
||||
ifeq ($(OS),MINGW)
|
||||
SOURCE += $(SRCDIR)/osal_dynamiclib_win32.c
|
||||
else
|
||||
SOURCE += $(SRCDIR)/osal_dynamiclib_unix.c
|
||||
endif
|
||||
|
||||
# generate a list of object files build, make a temporary directory for them
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(filter %.c, $(SOURCE)))
|
||||
OBJECTS += $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(filter %.cpp, $(SOURCE)))
|
||||
OBJDIRS = $(dir $(OBJECTS))
|
||||
$(shell $(MKDIR) $(OBJDIRS))
|
||||
|
||||
# build targets
|
||||
TARGET = mupen64plus-video-z64$(POSTFIX).$(SO_EXTENSION)
|
||||
|
||||
targets:
|
||||
@echo "Mupen64plus-video-z64 N64 Graphics plugin makefile. "
|
||||
@echo " Targets:"
|
||||
@echo " all == Build Mupen64plus-video-z64 plugin"
|
||||
@echo " clean == remove object files"
|
||||
@echo " rebuild == clean and re-build all"
|
||||
@echo " install == Install Mupen64Plus-video-z64 plugin"
|
||||
@echo " uninstall == Uninstall Mupen64Plus-video-z64 plugin"
|
||||
@echo " Options:"
|
||||
@echo " BITS=32 == build 32-bit binaries on 64-bit machine"
|
||||
@echo " APIDIR=path == path to find Mupen64Plus Core headers"
|
||||
@echo " OPTFLAGS=flag == compiler optimization (default: -O3 -flto)"
|
||||
@echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)"
|
||||
@echo " PIC=(1|0) == Force enable/disable of position independent code"
|
||||
@echo " POSTFIX=name == String added to the name of the the build (default: '')"
|
||||
@echo " Install Options:"
|
||||
@echo " PREFIX=path == install/uninstall prefix (default: /usr/local)"
|
||||
@echo " SHAREDIR=path == path to install shared data files (default: PREFIX/share/mupen64plus)"
|
||||
@echo " LIBDIR=path == library prefix (default: PREFIX/lib)"
|
||||
@echo " PLUGINDIR=path == path to install plugin libraries (default: LIBDIR/mupen64plus)"
|
||||
@echo " DESTDIR=path == path to prepend to all installation paths (only for packagers)"
|
||||
@echo " Debugging Options:"
|
||||
@echo " DEBUG=1 == add debugging symbols"
|
||||
@echo " V=1 == show verbose compiler output"
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
install: $(TARGET)
|
||||
$(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)"
|
||||
$(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)"
|
||||
$(INSTALL) -d "$(DESTDIR)$(SHAREDIR)"
|
||||
|
||||
uninstall:
|
||||
$(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)"
|
||||
|
||||
clean:
|
||||
$(RM) -r $(OBJDIR) $(TARGET)
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
# build dependency files
|
||||
CFLAGS += -MD -MP
|
||||
-include $(OBJECTS:.o=.d)
|
||||
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
|
||||
# standard build rules
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(COMPILE.c) -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
|
||||
$(COMPILE.cc) -o $@ $<
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||
|
||||
.PHONY: all clean install uninstall targets
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "z64.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static const char *image_format[] = { "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" };
|
||||
static const char *image_size[] = { "4-bit", "8-bit", "16-bit", "32-bit" };
|
||||
|
||||
static const int rdp_command_length[64] =
|
||||
{
|
||||
8, // 0x00, No Op
|
||||
8, // 0x01, ???
|
||||
8, // 0x02, ???
|
||||
8, // 0x03, ???
|
||||
8, // 0x04, ???
|
||||
8, // 0x05, ???
|
||||
8, // 0x06, ???
|
||||
8, // 0x07, ???
|
||||
32, // 0x08, Non-Shaded Triangle
|
||||
32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
|
||||
32+64, // 0x0a, Textured Triangle
|
||||
32+64+16, // 0x0b, Textured, Z-Buffered Triangle
|
||||
32+64, // 0x0c, Shaded Triangle
|
||||
32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
|
||||
32+64+64, // 0x0e, Shaded+Textured Triangle
|
||||
32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
|
||||
8, // 0x10, ???
|
||||
8, // 0x11, ???
|
||||
8, // 0x12, ???
|
||||
8, // 0x13, ???
|
||||
8, // 0x14, ???
|
||||
8, // 0x15, ???
|
||||
8, // 0x16, ???
|
||||
8, // 0x17, ???
|
||||
8, // 0x18, ???
|
||||
8, // 0x19, ???
|
||||
8, // 0x1a, ???
|
||||
8, // 0x1b, ???
|
||||
8, // 0x1c, ???
|
||||
8, // 0x1d, ???
|
||||
8, // 0x1e, ???
|
||||
8, // 0x1f, ???
|
||||
8, // 0x20, ???
|
||||
8, // 0x21, ???
|
||||
8, // 0x22, ???
|
||||
8, // 0x23, ???
|
||||
16, // 0x24, Texture_Rectangle
|
||||
16, // 0x25, Texture_Rectangle_Flip
|
||||
8, // 0x26, Sync_Load
|
||||
8, // 0x27, Sync_Pipe
|
||||
8, // 0x28, Sync_Tile
|
||||
8, // 0x29, Sync_Full
|
||||
8, // 0x2a, Set_Key_GB
|
||||
8, // 0x2b, Set_Key_R
|
||||
8, // 0x2c, Set_Convert
|
||||
8, // 0x2d, Set_Scissor
|
||||
8, // 0x2e, Set_Prim_Depth
|
||||
8, // 0x2f, Set_Other_Modes
|
||||
8, // 0x30, Load_TLUT
|
||||
8, // 0x31, ???
|
||||
8, // 0x32, Set_Tile_Size
|
||||
8, // 0x33, Load_Block
|
||||
8, // 0x34, Load_Tile
|
||||
8, // 0x35, Set_Tile
|
||||
8, // 0x36, Fill_Rectangle
|
||||
8, // 0x37, Set_Fill_Color
|
||||
8, // 0x38, Set_Fog_Color
|
||||
8, // 0x39, Set_Blend_Color
|
||||
8, // 0x3a, Set_Prim_Color
|
||||
8, // 0x3b, Set_Env_Color
|
||||
8, // 0x3c, Set_Combine
|
||||
8, // 0x3d, Set_Texture_Image
|
||||
8, // 0x3e, Set_Mask_Image
|
||||
8 // 0x3f, Set_Color_Image
|
||||
};
|
||||
|
||||
int rdp_dasm(UINT32 * rdp_cmd_data, int rdp_cmd_cur, int length, char *buffer)
|
||||
{
|
||||
//int i;
|
||||
int tile;
|
||||
const char *format, *size;
|
||||
char sl[32], tl[32], sh[32], th[32];
|
||||
char s[32], t[32];//, w[32];
|
||||
char dsdx[32], dtdy[32];
|
||||
#if 0
|
||||
char dsdx[32], dtdx[32], dwdx[32];
|
||||
char dsdy[32], dtdy[32], dwdy[32];
|
||||
char dsde[32], dtde[32], dwde[32];
|
||||
char yl[32], yh[32], ym[32], xl[32], xh[32], xm[32];
|
||||
char dxldy[32], dxhdy[32], dxmdy[32];
|
||||
char rt[32], gt[32], bt[32], at[32];
|
||||
char drdx[32], dgdx[32], dbdx[32], dadx[32];
|
||||
char drdy[32], dgdy[32], dbdy[32], dady[32];
|
||||
char drde[32], dgde[32], dbde[32], dade[32];
|
||||
#endif
|
||||
UINT32 r,g,b,a;
|
||||
|
||||
UINT32 cmd[64];
|
||||
UINT32 command;
|
||||
|
||||
if (length < 8)
|
||||
{
|
||||
sprintf(buffer, "ERROR: length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd[0] = rdp_cmd_data[rdp_cmd_cur+0];
|
||||
cmd[1] = rdp_cmd_data[rdp_cmd_cur+1];
|
||||
|
||||
tile = (cmd[1] >> 24) & 0x7;
|
||||
sprintf(sl, "%4.2f", (float)((cmd[0] >> 12) & 0xfff) / 4.0f);
|
||||
sprintf(tl, "%4.2f", (float)((cmd[0] >> 0) & 0xfff) / 4.0f);
|
||||
sprintf(sh, "%4.2f", (float)((cmd[1] >> 12) & 0xfff) / 4.0f);
|
||||
sprintf(th, "%4.2f", (float)((cmd[1] >> 0) & 0xfff) / 4.0f);
|
||||
|
||||
format = image_format[(cmd[0] >> 21) & 0x7];
|
||||
size = image_size[(cmd[0] >> 19) & 0x3];
|
||||
|
||||
r = (cmd[1] >> 24) & 0xff;
|
||||
g = (cmd[1] >> 16) & 0xff;
|
||||
b = (cmd[1] >> 8) & 0xff;
|
||||
a = (cmd[1] >> 0) & 0xff;
|
||||
|
||||
command = (cmd[0] >> 24) & 0x3f;
|
||||
//printf("command %x\n", command);
|
||||
switch (command)
|
||||
{
|
||||
case 0x00: sprintf(buffer, "No Op"); break;
|
||||
case 0x08:
|
||||
sprintf(buffer, "Tri_NoShade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0a:
|
||||
sprintf(buffer, "Tri_Tex (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0c:
|
||||
sprintf(buffer, "Tri_Shade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0e:
|
||||
sprintf(buffer, "Tri_TexShade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x09:
|
||||
sprintf(buffer, "TriZ_NoShade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0b:
|
||||
sprintf(buffer, "TriZ_Tex (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0d:
|
||||
sprintf(buffer, "TriZ_Shade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
case 0x0f:
|
||||
sprintf(buffer, "TriZ_TexShade (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
|
||||
#if 0
|
||||
case 0x08: // Tri_NoShade
|
||||
{
|
||||
int lft = (command >> 23) & 0x1;
|
||||
|
||||
if (length < rdp_command_length[command])
|
||||
{
|
||||
sprintf(buffer, "ERROR: Tri_NoShade length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd[2] = rdp_cmd_data[rdp_cmd_cur+2];
|
||||
cmd[3] = rdp_cmd_data[rdp_cmd_cur+3];
|
||||
cmd[4] = rdp_cmd_data[rdp_cmd_cur+4];
|
||||
cmd[5] = rdp_cmd_data[rdp_cmd_cur+5];
|
||||
cmd[6] = rdp_cmd_data[rdp_cmd_cur+6];
|
||||
cmd[7] = rdp_cmd_data[rdp_cmd_cur+7];
|
||||
|
||||
sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
|
||||
sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f));
|
||||
sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f));
|
||||
sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f));
|
||||
sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f));
|
||||
sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f));
|
||||
sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f));
|
||||
|
||||
sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
|
||||
break;
|
||||
}
|
||||
case 0x0a: // Tri_Tex
|
||||
{
|
||||
int lft = (command >> 23) & 0x1;
|
||||
|
||||
if (length < rdp_command_length[command])
|
||||
{
|
||||
sprintf(buffer, "ERROR: Tri_Tex length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=2; i < 24; i++)
|
||||
{
|
||||
cmd[i] = rdp_cmd_data[rdp_cmd_cur+i];
|
||||
}
|
||||
|
||||
sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
|
||||
sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
|
||||
sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
|
||||
sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
|
||||
sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
|
||||
sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
|
||||
sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
|
||||
|
||||
sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
|
||||
sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
|
||||
|
||||
|
||||
buffer+=sprintf(buffer, "Tri_Tex %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
|
||||
break;
|
||||
}
|
||||
case 0x0c: // Tri_Shade
|
||||
{
|
||||
int lft = (command >> 23) & 0x1;
|
||||
|
||||
if (length < rdp_command_length[command])
|
||||
{
|
||||
sprintf(buffer, "ERROR: Tri_Shade length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=2; i < 24; i++)
|
||||
{
|
||||
cmd[i] = rdp_cmd_data[i];
|
||||
}
|
||||
|
||||
sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
|
||||
sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
|
||||
sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
|
||||
sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
|
||||
sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
|
||||
sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
|
||||
sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
|
||||
sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
|
||||
sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f);
|
||||
sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f);
|
||||
sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f);
|
||||
sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f);
|
||||
|
||||
buffer+=sprintf(buffer, "Tri_Shade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady);
|
||||
break;
|
||||
}
|
||||
case 0x0e: // Tri_TexShade
|
||||
{
|
||||
int lft = (command >> 23) & 0x1;
|
||||
|
||||
if (length < rdp_command_length[command])
|
||||
{
|
||||
sprintf(buffer, "ERROR: Tri_TexShade length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=2; i < 40; i++)
|
||||
{
|
||||
cmd[i] = rdp_cmd_data[rdp_cmd_cur+i];
|
||||
}
|
||||
|
||||
sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f);
|
||||
sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f);
|
||||
sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f));
|
||||
sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f));
|
||||
sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f));
|
||||
sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f));
|
||||
sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f));
|
||||
sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f));
|
||||
sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f);
|
||||
sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f);
|
||||
sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f);
|
||||
sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f);
|
||||
sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f);
|
||||
sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f);
|
||||
|
||||
sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f);
|
||||
sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f);
|
||||
sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f);
|
||||
sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f);
|
||||
|
||||
|
||||
buffer+=sprintf(buffer, "Tri_TexShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady);
|
||||
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde);
|
||||
buffer+=sprintf(buffer, " ");
|
||||
buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case 0x24:
|
||||
case 0x25:
|
||||
{
|
||||
if (length < 16)
|
||||
{
|
||||
sprintf(buffer, "ERROR: Texture_Rectangle length = %d\n", length);
|
||||
return 0;
|
||||
}
|
||||
cmd[2] = rdp_cmd_data[rdp_cmd_cur+2];
|
||||
cmd[3] = rdp_cmd_data[rdp_cmd_cur+3];
|
||||
sprintf(s, "%4.4f", (float)(INT16)((cmd[2] >> 16) & 0xffff) / 32.0f);
|
||||
sprintf(t, "%4.4f", (float)(INT16)((cmd[2] >> 0) & 0xffff) / 32.0f);
|
||||
sprintf(dsdx, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f);
|
||||
sprintf(dtdy, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f);
|
||||
|
||||
if (command == 0x24)
|
||||
sprintf(buffer, "Texture_Rectangle %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy);
|
||||
else
|
||||
sprintf(buffer, "Texture_Rectangle_Flip %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x26: sprintf(buffer, "Sync_Load"); break;
|
||||
case 0x27: sprintf(buffer, "Sync_Pipe"); break;
|
||||
case 0x28: sprintf(buffer, "Sync_Tile"); break;
|
||||
case 0x29: sprintf(buffer, "Sync_Full"); break;
|
||||
case 0x2d: sprintf(buffer, "Set_Scissor %s, %s, %s, %s", sl, tl, sh, th); break;
|
||||
case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", (cmd[1] >> 16) & 0xffff, cmd[1] & 0xffff); break;
|
||||
case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", cmd[0], cmd[1]); break;
|
||||
case 0x30: sprintf(buffer, "Load_TLUT %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
|
||||
case 0x32: sprintf(buffer, "Set_Tile_Size %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
|
||||
case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, (cmd[0] >> 12) & 0xfff, cmd[0] & 0xfff, (cmd[1] >> 12) & 0xfff, cmd[1] & 0xfff); break;
|
||||
case 0x34: sprintf(buffer, "Load_Tile %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
|
||||
case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, ((cmd[0] >> 9) & 0x1ff) * 8, (cmd[0] & 0x1ff) * 8); break;
|
||||
case 0x36: sprintf(buffer, "Fill_Rectangle %s, %s, %s, %s", sh, th, sl, tl); break;
|
||||
case 0x37: sprintf(buffer, "Set_Fill_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
|
||||
case 0x38: sprintf(buffer, "Set_Fog_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
|
||||
case 0x39: sprintf(buffer, "Set_Blend_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
|
||||
case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", (cmd[0] >> 8) & 0x1f, cmd[0] & 0xff, r, g, b, a); break;
|
||||
case 0x3b: sprintf(buffer, "Set_Env_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
|
||||
case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", cmd[0], cmd[1]); break;
|
||||
case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break;
|
||||
case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", cmd[1]); break;
|
||||
case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break;
|
||||
default: sprintf(buffer, "??? (%08X %08X)", cmd[0], cmd[1]); break;
|
||||
}
|
||||
|
||||
return rdp_command_length[command];
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "rgl_assert.h"
|
||||
#include <glew.h>
|
||||
#if defined(__MACOSX__)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#elif defined(__MACOS__)
|
||||
#include <gl.h>
|
||||
#include <glext.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#ifndef WIN32
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "glshader.h"
|
||||
|
||||
static void printInfoLog(GLhandleARB obj, const char * src)
|
||||
{
|
||||
int infologLength = 0;
|
||||
int charsWritten = 0;
|
||||
char *infoLog;
|
||||
|
||||
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
|
||||
&infologLength);
|
||||
|
||||
if (infologLength > 0)
|
||||
{
|
||||
infoLog = (char *)malloc(infologLength);
|
||||
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
|
||||
if (*infoLog)
|
||||
rdp_log(M64MSG_INFO, "%s\n%s", src, infoLog);
|
||||
free(infoLog);
|
||||
}
|
||||
}
|
||||
|
||||
//#define rglAssert(...)
|
||||
rglShader_t * rglCreateShader(const char * vsrc, const char * fsrc)
|
||||
{
|
||||
GLhandleARB vs, fs, prog;
|
||||
|
||||
//printf("Compiling shader :\n%s", fsrc);
|
||||
|
||||
vs = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
fs = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
glShaderSourceARB(vs, 1, &vsrc,NULL);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glShaderSourceARB(fs, 1, &fsrc,NULL);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glCompileShaderARB(vs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glCompileShaderARB(fs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
printInfoLog(vs, vsrc);
|
||||
printInfoLog(fs, fsrc);
|
||||
prog = glCreateProgramObjectARB();
|
||||
glAttachObjectARB(prog, fs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glAttachObjectARB(prog, vs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
glLinkProgramARB(prog);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
rglShader_t * s = (rglShader_t *) malloc(sizeof(rglShader_t));
|
||||
s->vs = vs;
|
||||
s->fs = fs;
|
||||
s->prog = prog;
|
||||
//LOG("Creating shader %d %d %d\n", s->vs, s->fs, s->prog);
|
||||
#ifdef RDP_DEBUG
|
||||
s->vsrc = strdup(vsrc);
|
||||
s->fsrc = strdup(fsrc);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
void rglUseShader(rglShader_t * shader)
|
||||
{
|
||||
if (!shader)
|
||||
glUseProgramObjectARB(0);
|
||||
else
|
||||
glUseProgramObjectARB(shader->prog);
|
||||
}
|
||||
|
||||
void rglDeleteShader(rglShader_t * shader)
|
||||
{
|
||||
//LOG("Deleting shader %d %d %d\n", shader->vs, shader->fs, shader->prog);
|
||||
glDeleteObjectARB(shader->prog);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glDeleteObjectARB(shader->vs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glDeleteObjectARB(shader->fs);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
free(shader);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _GLSHADER_H_
|
||||
#define _GLSHADER_H_
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
typedef struct {
|
||||
GLhandleARB vs, fs, prog;
|
||||
#ifdef RDP_DEBUG
|
||||
const char * vsrc, * fsrc;
|
||||
#endif
|
||||
} rglShader_t;
|
||||
|
||||
rglShader_t * rglCreateShader(const char * vsrc, const char * fsrc);
|
||||
void rglUseShader(rglShader_t * shader);
|
||||
void rglDeleteShader(rglShader_t * shader);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
#include "osal_dynamiclib.h"
|
||||
#include <SDL.h>
|
||||
|
||||
#define THREADED
|
||||
|
||||
#define PLUGIN_VERSION 0x020000
|
||||
#define VIDEO_PLUGIN_API_VERSION 0x020200
|
||||
#define CONFIG_API_VERSION 0x020000
|
||||
#define VIDEXT_API_VERSION 0x030000
|
||||
|
||||
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
|
||||
|
||||
GFX_INFO gfx;
|
||||
|
||||
void (*render_callback)(int) = NULL;
|
||||
static void (*l_DebugCallback)(void *, int, const char *) = NULL;
|
||||
static void *l_DebugCallContext = NULL;
|
||||
|
||||
|
||||
/* definitions of pointers to Core video extension functions */
|
||||
ptr_VidExt_Init CoreVideo_Init = NULL;
|
||||
ptr_VidExt_Quit CoreVideo_Quit = NULL;
|
||||
ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL;
|
||||
ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL;
|
||||
ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL;
|
||||
ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL;
|
||||
ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL;
|
||||
ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL;
|
||||
ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL;
|
||||
ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL;
|
||||
|
||||
/* definitions of pointers to Core config functions */
|
||||
ptr_ConfigOpenSection ConfigOpenSection = NULL;
|
||||
ptr_ConfigSetParameter ConfigSetParameter = NULL;
|
||||
ptr_ConfigGetParameter ConfigGetParameter = NULL;
|
||||
ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
|
||||
ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL;
|
||||
ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL;
|
||||
ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL;
|
||||
ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
|
||||
ptr_ConfigGetParamInt ConfigGetParamInt = NULL;
|
||||
ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL;
|
||||
ptr_ConfigGetParamBool ConfigGetParamBool = NULL;
|
||||
ptr_ConfigGetParamString ConfigGetParamString = NULL;
|
||||
|
||||
#ifdef THREADED
|
||||
volatile static int waiting;
|
||||
SDL_sem * rdpCommandSema;
|
||||
SDL_sem * rdpCommandCompleteSema;
|
||||
SDL_Thread * rdpThread;
|
||||
int rdpThreadFunc(void * dummy)
|
||||
{
|
||||
while (1) {
|
||||
SDL_SemWait(rdpCommandSema);
|
||||
waiting = 1;
|
||||
if (rglNextStatus == RGL_STATUS_CLOSED)
|
||||
rglUpdateStatus();
|
||||
else
|
||||
rdp_process_list();
|
||||
if (!rglSettings.async)
|
||||
SDL_SemPost(rdpCommandCompleteSema);
|
||||
|
||||
if (rglStatus == RGL_STATUS_CLOSED) {
|
||||
rdpThread = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rdpSignalFullSync()
|
||||
{
|
||||
SDL_SemPost(rdpCommandCompleteSema);
|
||||
}
|
||||
void rdpWaitFullSync()
|
||||
{
|
||||
SDL_SemWait(rdpCommandCompleteSema);
|
||||
}
|
||||
|
||||
void rdpPostCommand()
|
||||
{
|
||||
int sync = rdp_store_list();
|
||||
SDL_SemPost(rdpCommandSema);
|
||||
if (!rglSettings.async)
|
||||
SDL_SemWait(rdpCommandCompleteSema);
|
||||
else if (sync) {
|
||||
rdpWaitFullSync();
|
||||
*gfx.MI_INTR_REG |= 0x20;
|
||||
gfx.CheckInterrupts();
|
||||
}
|
||||
|
||||
waiting = 0;
|
||||
}
|
||||
|
||||
void rdpCreateThread()
|
||||
{
|
||||
if (!rdpCommandSema) {
|
||||
rdpCommandSema = SDL_CreateSemaphore(0);
|
||||
rdpCommandCompleteSema = SDL_CreateSemaphore(0);
|
||||
}
|
||||
if (!rdpThread) {
|
||||
LOG("Creating rdp thread\n");
|
||||
#if SDL_VERSION_ATLEAST(2,0,0)
|
||||
rdpThread = SDL_CreateThread(rdpThreadFunc, "z64rdp", 0);
|
||||
#else
|
||||
rdpThread = SDL_CreateThread(rdpThreadFunc, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void rdp_log(m64p_msg_level level, const char *msg, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
vsnprintf(buf, 1023, msg, args);
|
||||
buf[1023]='\0';
|
||||
va_end(args);
|
||||
if (l_DebugCallback)
|
||||
{
|
||||
l_DebugCallback(l_DebugCallContext, level, buf);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
|
||||
void (*DebugCallback)(void *, int, const char *))
|
||||
{
|
||||
///* first thing is to set the callback function for debug info */
|
||||
l_DebugCallback = DebugCallback;
|
||||
l_DebugCallContext = Context;
|
||||
|
||||
/* Get the core Video Extension function pointers from the library handle */
|
||||
CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
|
||||
CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
|
||||
CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
|
||||
CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
|
||||
CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
|
||||
CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
|
||||
CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
|
||||
CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
|
||||
CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
|
||||
CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
|
||||
|
||||
if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
|
||||
!CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress ||
|
||||
!CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers || !CoreVideo_ResizeWindow)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Couldn't connect to Core video functions");
|
||||
return M64ERR_INCOMPATIBLE;
|
||||
}
|
||||
|
||||
/* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
|
||||
ptr_CoreGetAPIVersions CoreAPIVersionFunc;
|
||||
CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
|
||||
if (CoreAPIVersionFunc == NULL)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");
|
||||
return M64ERR_INCOMPATIBLE;
|
||||
}
|
||||
int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
|
||||
(*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
|
||||
if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
|
||||
VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
|
||||
return M64ERR_INCOMPATIBLE;
|
||||
}
|
||||
if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Emulator core Video Extension API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
|
||||
VERSION_PRINTF_SPLIT(VidextAPIVersion), VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION));
|
||||
return M64ERR_INCOMPATIBLE;
|
||||
}
|
||||
|
||||
/* Get the core config function pointers from the library handle */
|
||||
ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
|
||||
ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
|
||||
ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
|
||||
ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
|
||||
ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
|
||||
ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
|
||||
ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
|
||||
ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
|
||||
ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
|
||||
ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
|
||||
ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
|
||||
if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
|
||||
!ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
|
||||
!ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Couldn't connect to Core configuration functions");
|
||||
return M64ERR_INCOMPATIBLE;
|
||||
}
|
||||
|
||||
rglReadSettings();
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL PluginShutdown(void)
|
||||
{
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
|
||||
{
|
||||
/* set version info */
|
||||
if (PluginType != NULL)
|
||||
*PluginType = M64PLUGIN_GFX;
|
||||
|
||||
if (PluginVersion != NULL)
|
||||
*PluginVersion = PLUGIN_VERSION;
|
||||
|
||||
if (APIVersion != NULL)
|
||||
*APIVersion = VIDEO_PLUGIN_API_VERSION;
|
||||
|
||||
if (PluginNamePtr != NULL)
|
||||
*PluginNamePtr = "Z64gl";
|
||||
|
||||
if (Capabilities != NULL)
|
||||
{
|
||||
*Capabilities = 0;
|
||||
}
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
EXPORT void CALL SetRenderingCallback(void (*callback)(int))
|
||||
{
|
||||
render_callback = callback;
|
||||
}
|
||||
|
||||
EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
|
||||
{
|
||||
LOG("ReadScreen\n");
|
||||
*width = rglSettings.resX;
|
||||
*height = rglSettings.resY;
|
||||
if (dest)
|
||||
{
|
||||
GLint oldMode;
|
||||
glGetIntegerv( GL_READ_BUFFER, &oldMode );
|
||||
if (front)
|
||||
glReadBuffer( GL_FRONT );
|
||||
else
|
||||
glReadBuffer( GL_BACK );
|
||||
glReadPixels( 0, 0, rglSettings.resX, rglSettings.resY,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, dest );
|
||||
glReadBuffer( oldMode );
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info)
|
||||
{
|
||||
LOG("InitiateGFX\n");
|
||||
gfx = Gfx_Info;
|
||||
memset(rdpTiles, 0, sizeof(rdpTiles));
|
||||
memset(rdpTmem, 0, 0x1000);
|
||||
memset(&rdpState, 0, sizeof(rdpState));
|
||||
#ifdef THREADED
|
||||
if (rglSettings.threaded)
|
||||
rdpCreateThread();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
EXPORT void CALL MoveScreen (int xpos, int ypos)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL ChangeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL ProcessDList(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EXPORT void CALL ProcessRDPList(void)
|
||||
{
|
||||
#ifdef THREADED
|
||||
if (rglSettings.threaded) {
|
||||
rdpCreateThread();
|
||||
rdpPostCommand();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rdp_process_list();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT void CALL ResizeVideoOutput(int Width, int Height)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL RomClosed (void)
|
||||
{
|
||||
#ifdef THREADED
|
||||
if (rglSettings.threaded) {
|
||||
rglNextStatus = RGL_STATUS_CLOSED;
|
||||
do
|
||||
rdpPostCommand();
|
||||
while (rglStatus != RGL_STATUS_CLOSED);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rglNextStatus = rglStatus = RGL_STATUS_CLOSED;
|
||||
rglCloseScreen();
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT int CALL RomOpen()
|
||||
{
|
||||
int success = 1;
|
||||
#ifdef THREADED
|
||||
if (rglSettings.threaded) {
|
||||
rdpCreateThread();
|
||||
//while (rglStatus != RGL_STATUS_CLOSED);
|
||||
rglNextStatus = RGL_STATUS_WINDOWED;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rglNextStatus = rglStatus = RGL_STATUS_WINDOWED;
|
||||
success = rglOpenScreen();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
EXPORT void CALL ShowCFB (void)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL UpdateScreen (void)
|
||||
{
|
||||
#ifdef THREADED
|
||||
if (rglSettings.threaded) {
|
||||
rdpPostCommand();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rglUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT void CALL ViStatusChanged (void)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL ViWidthChanged (void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Mupen64plus-core - osal/dynamiclib.h *
|
||||
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||
* Copyright (C) 2009 Richard Goedeken *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#if !defined(OSAL_DYNAMICLIB_H)
|
||||
#define OSAL_DYNAMICLIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "m64p_types.h"
|
||||
|
||||
void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #define OSAL_DYNAMICLIB_H */
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Mupen64plus-core - osal/dynamiclib_unix.c *
|
||||
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||
* Copyright (C) 2009 Richard Goedeken *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "m64p_types.h"
|
||||
#include "osal_dynamiclib.h"
|
||||
|
||||
void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
|
||||
{
|
||||
if (pccProcedureName == NULL)
|
||||
return NULL;
|
||||
|
||||
return dlsym(LibHandle, pccProcedureName);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Mupen64plus-ui-console - osal_dynamiclib_win32.c *
|
||||
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||
* Copyright (C) 2009 Richard Goedeken *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "m64p_types.h"
|
||||
#include "osal_dynamiclib.h"
|
||||
|
||||
m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
|
||||
{
|
||||
if (pLibHandle == NULL || pccLibraryPath == NULL)
|
||||
return M64ERR_INPUT_ASSERT;
|
||||
|
||||
*pLibHandle = LoadLibrary(pccLibraryPath);
|
||||
|
||||
if (*pLibHandle == NULL)
|
||||
{
|
||||
char *pchErrMsg;
|
||||
DWORD dwErr = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
|
||||
fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg);
|
||||
LocalFree(pchErrMsg);
|
||||
return M64ERR_INPUT_NOT_FOUND;
|
||||
}
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
|
||||
{
|
||||
if (pccProcedureName == NULL)
|
||||
return NULL;
|
||||
|
||||
return GetProcAddress(LibHandle, pccProcedureName);
|
||||
}
|
||||
|
||||
m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
|
||||
{
|
||||
int rval = FreeLibrary(LibHandle);
|
||||
|
||||
if (rval == 0)
|
||||
{
|
||||
char *pchErrMsg;
|
||||
DWORD dwErr = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
|
||||
fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg);
|
||||
LocalFree(pchErrMsg);
|
||||
return M64ERR_INTERNAL;
|
||||
}
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* lists, simple queues, tail queues, and circular queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The
|
||||
* elements are singly linked for minimum space and pointer manipulation
|
||||
* overhead at the expense of O(n) removal for arbitrary elements. New
|
||||
* elements can be added to the list after an existing element or at the
|
||||
* head of the list. Elements being removed from the head of the list
|
||||
* should use the explicit macro for this purpose for optimum
|
||||
* efficiency. A singly-linked list may only be traversed in the forward
|
||||
* direction. Singly-linked lists are ideal for applications with large
|
||||
* datasets and few or no removals or for implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define LIST_INIT(head) do { \
|
||||
(head)->lh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.le_next))
|
||||
|
||||
/*
|
||||
* List access methods.
|
||||
*/
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_INIT(head) do { \
|
||||
(head)->slh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->slh_first == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = (head)->slh_first; \
|
||||
while(curelm->field.sle_next != (elm)) \
|
||||
curelm = curelm->field.sle_next; \
|
||||
curelm->field.sle_next = \
|
||||
curelm->field.sle_next->field.sle_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first; /* first element */ \
|
||||
struct type **stqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_INIT(head) do { \
|
||||
(head)->stqh_first = NULL; \
|
||||
(head)->stqh_last = &(head)->stqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
(head)->stqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.stqe_next = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
|
||||
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||
(listelm)->field.stqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
|
||||
(head)->stqh_last = &(head)->stqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->stqh_first == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->stqh_first; \
|
||||
while (curelm->field.stqe_next != (elm)) \
|
||||
curelm = curelm->field.stqe_next; \
|
||||
if ((curelm->field.stqe_next = \
|
||||
curelm->field.stqe_next->field.stqe_next) == NULL) \
|
||||
(head)->stqh_last = &(curelm)->field.stqe_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->stqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.stqe_next))
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue access methods.
|
||||
*/
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define SIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define SIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define SIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->sqh_first == (elm)) { \
|
||||
SIMPLEQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->sqh_first; \
|
||||
while (curelm->field.sqe_next != (elm)) \
|
||||
curelm = curelm->field.sqe_next; \
|
||||
if ((curelm->field.sqe_next = \
|
||||
curelm->field.sqe_next->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(curelm)->field.sqe_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.sqe_next))
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
|
||||
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define _TAILQ_HEAD(name, type, qual) \
|
||||
struct name { \
|
||||
qual type *tqh_first; /* first element */ \
|
||||
qual type *qual *tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define _TAILQ_ENTRY(type, qual) \
|
||||
struct { \
|
||||
qual type *tqe_next; /* next element */ \
|
||||
qual type *qual *tqe_prev; /* address of previous next element */\
|
||||
}
|
||||
#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.tqe_next))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
|
||||
(var); \
|
||||
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
|
||||
|
||||
/*
|
||||
* Tail queue access methods.
|
||||
*/
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
|
||||
/*
|
||||
* Circular queue definitions.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(type, head) \
|
||||
{ (type *)&head, (type *)&head }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_INIT(type, head) do { \
|
||||
(head)->cqh_first = (type *)(head); \
|
||||
(head)->cqh_last = (type *)(head); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(type, head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||
(elm)->field.cqe_prev = (listelm); \
|
||||
if ((listelm)->field.cqe_next == (type *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||
(listelm)->field.cqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(type, head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm); \
|
||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||
if ((listelm)->field.cqe_prev == (type *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||
(listelm)->field.cqe_prev = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(type, head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||
(elm)->field.cqe_prev = (type *)(head); \
|
||||
if ((head)->cqh_last == (type *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||
(head)->cqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(type, head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (type *)(head); \
|
||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||
if ((head)->cqh_first == (type *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(head)->cqh_last->field.cqe_next = (elm); \
|
||||
(head)->cqh_last = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if ((elm)->field.cqe_next == (void *)(head)) \
|
||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||
else \
|
||||
(elm)->field.cqe_next->field.cqe_prev = \
|
||||
(elm)->field.cqe_prev; \
|
||||
if ((elm)->field.cqe_prev == (void *)(head)) \
|
||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||
else \
|
||||
(elm)->field.cqe_prev->field.cqe_next = \
|
||||
(elm)->field.cqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define CIRCLEQ_FOREACH(type, var, head, field) \
|
||||
for ((var) = ((head)->cqh_first); \
|
||||
(var) != (const type *)(head); \
|
||||
(var) = ((var)->field.cqe_next))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(type, var, head, field) \
|
||||
for ((var) = ((head)->cqh_last); \
|
||||
(var) != (const type *)(head); \
|
||||
(var) = ((var)->field.cqe_prev))
|
||||
|
||||
/*
|
||||
* Circular queue access methods.
|
||||
*/
|
||||
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
||||
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
||||
|
||||
#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
|
||||
(((elm)->field.cqe_next == (void *)(head)) \
|
||||
? ((head)->cqh_first) \
|
||||
: (elm->field.cqe_next))
|
||||
#define CIRCLEQ_LOOP_PREV(head, elm, field) \
|
||||
(((elm)->field.cqe_prev == (void *)(head)) \
|
||||
? ((head)->cqh_last) \
|
||||
: (elm->field.cqe_prev))
|
||||
|
||||
#endif /* sys/queue.h */
|
|
@ -0,0 +1,858 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const char *rdpImageFormats[] =
|
||||
{ "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" };
|
||||
|
||||
rdpState_t rdpState;
|
||||
uint32_t rdpChanged;
|
||||
//rdpColor_t rdpTlut[1024];
|
||||
uint8_t rdpTmem[4*0x1000];
|
||||
int rdpFbFormat;
|
||||
int rdpFbSize;
|
||||
int rdpFbWidth;
|
||||
uint32_t rdpFbAddress;
|
||||
uint32_t rdpZbAddress;
|
||||
int rdpTiFormat;
|
||||
int rdpTiSize;
|
||||
int rdpTiWidth;
|
||||
uint32_t rdpTiAddress;
|
||||
rdpTile_t rdpTiles[8];
|
||||
int rdpTileSet;
|
||||
|
||||
struct area_t {
|
||||
int start, stop;
|
||||
uint32_t from;
|
||||
int fromLine, fromFormat, fromSize;
|
||||
};
|
||||
|
||||
#define MAX_TMEM_AREAS 16
|
||||
static area_t tmemAreas[MAX_TMEM_AREAS];
|
||||
static int nbTmemAreas;
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
int rdp_dump;
|
||||
#endif
|
||||
|
||||
#define MAXCMD 0x100000
|
||||
static uint32_t rdp_cmd_data[MAXCMD+44];
|
||||
static volatile int rdp_cmd_ptr = 0;
|
||||
static volatile int rdp_cmd_cur = 0;
|
||||
static int rdp_cmd_left = 0;
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
uint32_t rdpTraceBuf[0x100000];
|
||||
int rdpTracePos;
|
||||
#endif
|
||||
|
||||
|
||||
static void MarkTmemArea(int start, int stop, uint32_t from, uint32_t fromLine,
|
||||
int fromFormat, int fromSize)
|
||||
{
|
||||
int i;
|
||||
|
||||
// remove areas that intersect
|
||||
for (i=0; i<nbTmemAreas; i++)
|
||||
while (i<nbTmemAreas &&
|
||||
tmemAreas[i].start<stop && tmemAreas[i].stop>start) {
|
||||
memmove(tmemAreas+i, tmemAreas+i+1, nbTmemAreas-i-1);
|
||||
nbTmemAreas--;
|
||||
}
|
||||
|
||||
DUMP("marking tmem %x --> %x rdram %x\n", start, stop, from);
|
||||
|
||||
// add new area
|
||||
//rglAssert(nbTmemAreas < MAX_TMEM_AREAS);
|
||||
if (nbTmemAreas == MAX_TMEM_AREAS) {
|
||||
LOG("tmem areas buffer full, clearing\n");
|
||||
nbTmemAreas = 0;
|
||||
}
|
||||
tmemAreas[nbTmemAreas].start = start;
|
||||
tmemAreas[nbTmemAreas].stop = stop;
|
||||
tmemAreas[nbTmemAreas].from = from;
|
||||
tmemAreas[nbTmemAreas].fromLine = fromLine;
|
||||
tmemAreas[nbTmemAreas].fromFormat = fromFormat;
|
||||
tmemAreas[nbTmemAreas].fromSize = fromSize;
|
||||
nbTmemAreas++;
|
||||
}
|
||||
|
||||
uint32_t rdpGetTmemOrigin(int tmem, int * line, int * stop, int * format, int * size)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<nbTmemAreas; i++)
|
||||
if (tmemAreas[i].start == tmem) {
|
||||
*line = tmemAreas[i].fromLine;
|
||||
*stop = tmemAreas[i].stop;
|
||||
*format = tmemAreas[i].fromFormat;
|
||||
*size = tmemAreas[i].fromSize;
|
||||
return tmemAreas[i].from;
|
||||
}
|
||||
|
||||
return ~0;
|
||||
}
|
||||
|
||||
inline uint32_t READ_RDP_DATA(uint32_t address)
|
||||
{
|
||||
if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
|
||||
{
|
||||
return rsp_dmem[(address & 0xfff) / 4];
|
||||
}
|
||||
else
|
||||
{
|
||||
return rdram[(address / 4)];
|
||||
}
|
||||
}
|
||||
|
||||
static const int rdp_command_length[64] =
|
||||
{
|
||||
8, // 0x00, No Op
|
||||
8, // 0x01, ???
|
||||
8, // 0x02, ???
|
||||
8, // 0x03, ???
|
||||
8, // 0x04, ???
|
||||
8, // 0x05, ???
|
||||
8, // 0x06, ???
|
||||
8, // 0x07, ???
|
||||
32, // 0x08, Non-Shaded Triangle
|
||||
32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
|
||||
32+64, // 0x0a, Textured Triangle
|
||||
32+64+16, // 0x0b, Textured, Z-Buffered Triangle
|
||||
32+64, // 0x0c, Shaded Triangle
|
||||
32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
|
||||
32+64+64, // 0x0e, Shaded+Textured Triangle
|
||||
32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
|
||||
8, // 0x10, ???
|
||||
8, // 0x11, ???
|
||||
8, // 0x12, ???
|
||||
8, // 0x13, ???
|
||||
8, // 0x14, ???
|
||||
8, // 0x15, ???
|
||||
8, // 0x16, ???
|
||||
8, // 0x17, ???
|
||||
8, // 0x18, ???
|
||||
8, // 0x19, ???
|
||||
8, // 0x1a, ???
|
||||
8, // 0x1b, ???
|
||||
8, // 0x1c, ???
|
||||
8, // 0x1d, ???
|
||||
8, // 0x1e, ???
|
||||
8, // 0x1f, ???
|
||||
8, // 0x20, ???
|
||||
8, // 0x21, ???
|
||||
8, // 0x22, ???
|
||||
8, // 0x23, ???
|
||||
16, // 0x24, Texture_Rectangle
|
||||
16, // 0x25, Texture_Rectangle_Flip
|
||||
8, // 0x26, Sync_Load
|
||||
8, // 0x27, Sync_Pipe
|
||||
8, // 0x28, Sync_Tile
|
||||
8, // 0x29, Sync_Full
|
||||
8, // 0x2a, Set_Key_GB
|
||||
8, // 0x2b, Set_Key_R
|
||||
8, // 0x2c, Set_Convert
|
||||
8, // 0x2d, Set_Scissor
|
||||
8, // 0x2e, Set_Prim_Depth
|
||||
8, // 0x2f, Set_Other_Modes
|
||||
8, // 0x30, Load_TLUT
|
||||
8, // 0x31, ???
|
||||
8, // 0x32, Set_Tile_Size
|
||||
8, // 0x33, Load_Block
|
||||
8, // 0x34, Load_Tile
|
||||
8, // 0x35, Set_Tile
|
||||
8, // 0x36, Fill_Rectangle
|
||||
8, // 0x37, Set_Fill_Color
|
||||
8, // 0x38, Set_Fog_Color
|
||||
8, // 0x39, Set_Blend_Color
|
||||
8, // 0x3a, Set_Prim_Color
|
||||
8, // 0x3b, Set_Env_Color
|
||||
8, // 0x3c, Set_Combine
|
||||
8, // 0x3d, Set_Texture_Image
|
||||
8, // 0x3e, Set_Mask_Image
|
||||
8 // 0x3f, Set_Color_Image
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
////////////////////////
|
||||
// RDP COMMANDS
|
||||
////////////////////////
|
||||
|
||||
static void rdp_invalid(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
LOGERROR("RDP: invalid command %d, %08X %08X\n", (w1 >> 24) & 0x3f, w1, w2);
|
||||
}
|
||||
|
||||
static void rdp_noop(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void triangle(uint32_t w1, uint32_t w2, int shade, int texture, int zbuffer)
|
||||
{
|
||||
rglTriangle(w1, w2, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);
|
||||
}
|
||||
|
||||
static void rdp_tri_noshade(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void rdp_tri_noshade_z(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 0, 0, 1);
|
||||
}
|
||||
|
||||
static void rdp_tri_tex(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 0, 1, 0);
|
||||
}
|
||||
|
||||
static void rdp_tri_tex_z(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 0, 1, 1);
|
||||
}
|
||||
|
||||
static void rdp_tri_shade(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void rdp_tri_shade_z(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 1, 0, 1);
|
||||
}
|
||||
|
||||
static void rdp_tri_texshade(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 1, 1, 0);
|
||||
}
|
||||
|
||||
static void rdp_tri_texshade_z(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
triangle(w1, w2, 1, 1, 1);
|
||||
}
|
||||
|
||||
static void rdp_tex_rect(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
uint32_t w3, w4;
|
||||
rdpTexRect_t rect;
|
||||
|
||||
w3 = rdp_cmd_data[rdp_cmd_cur+2];
|
||||
w4 = rdp_cmd_data[rdp_cmd_cur+3];
|
||||
|
||||
rect.tilenum = (w2 >> 24) & 0x7;
|
||||
rect.xl = (w1 >> 12) & 0xfff;
|
||||
rect.yl = (w1 >> 0) & 0xfff;
|
||||
rect.xh = (w2 >> 12) & 0xfff;
|
||||
rect.yh = (w2 >> 0) & 0xfff;
|
||||
rect.s = (w3 >> 16) & 0xffff;
|
||||
rect.t = (w3 >> 0) & 0xffff;
|
||||
rect.dsdx = (w4 >> 16) & 0xffff;
|
||||
rect.dtdy = (w4 >> 0) & 0xffff;
|
||||
|
||||
rglTextureRectangle(&rect, 0);
|
||||
}
|
||||
|
||||
static void rdp_tex_rect_flip(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
uint32_t w3, w4;
|
||||
rdpTexRect_t rect;
|
||||
|
||||
w3 = rdp_cmd_data[rdp_cmd_cur+2];
|
||||
w4 = rdp_cmd_data[rdp_cmd_cur+3];
|
||||
|
||||
rect.tilenum = (w2 >> 24) & 0x7;
|
||||
rect.xl = (w1 >> 12) & 0xfff;
|
||||
rect.yl = (w1 >> 0) & 0xfff;
|
||||
rect.xh = (w2 >> 12) & 0xfff;
|
||||
rect.yh = (w2 >> 0) & 0xfff;
|
||||
rect.t = (w3 >> 16) & 0xffff;
|
||||
rect.s = (w3 >> 0) & 0xffff;
|
||||
rect.dtdy = (w4 >> 16) & 0xffff;
|
||||
rect.dsdx = (w4 >> 0) & 0xffff;
|
||||
|
||||
rglTextureRectangle(&rect, 1);
|
||||
}
|
||||
|
||||
static void rdp_sync_load(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
// Nothing to do?
|
||||
}
|
||||
|
||||
static void rdp_sync_pipe(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
// Nothing to do?
|
||||
}
|
||||
|
||||
static void rdp_sync_tile(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
// Nothing to do?
|
||||
}
|
||||
|
||||
void rdpSignalFullSync();
|
||||
void rdpWaitFullSync();
|
||||
#ifdef RDP_DEBUG
|
||||
int nbFullSync;
|
||||
#endif
|
||||
static void rdp_sync_full(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
//printf("full sync\n");
|
||||
rglFullSync();
|
||||
rglUpdate();
|
||||
|
||||
if (rglSettings.async)
|
||||
rdpSignalFullSync();
|
||||
else {
|
||||
*gfx.MI_INTR_REG |= 0x20;
|
||||
gfx.CheckInterrupts();
|
||||
}
|
||||
#ifdef RDP_DEBUG
|
||||
nbFullSync++;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rdp_set_key_gb(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
//osd_die("RDP: unhandled command set_key_gb, %08X %08X\n", w1, w2);
|
||||
}
|
||||
|
||||
static void rdp_set_key_r(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
//osd_die("RDP: unhandled command set_key_r, %08X %08X\n", w1, w2);
|
||||
}
|
||||
|
||||
static void rdp_set_convert(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpState.k5 = w2&0xff;
|
||||
//osd_die("RDP: unhandled command set_convert, %08X %08X\n", w1, w2);
|
||||
}
|
||||
|
||||
static void rdp_set_scissor(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_CLIP;
|
||||
rdpState.clipMode = (w2 >> 24) & 3;
|
||||
rdpState.clip.xh = (w1 >> 12) & 0xfff;
|
||||
rdpState.clip.yh = (w1 >> 0) & 0xfff;
|
||||
rdpState.clip.xl = (w2 >> 12) & 0xfff;
|
||||
rdpState.clip.yl = (w2 >> 0) & 0xfff;
|
||||
// TODO: handle f & o?
|
||||
}
|
||||
|
||||
static void rdp_set_prim_depth(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_MISC;
|
||||
rdpState.primitiveZ = (uint16_t)(w2 >> 16);
|
||||
rdpState.primitiveDeltaZ = (uint16_t)(w1);
|
||||
}
|
||||
|
||||
static void rdp_set_other_modes(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_OTHER_MODES;
|
||||
rdpState.otherModes.w1 = w1;
|
||||
rdpState.otherModes.w2 = w2;
|
||||
}
|
||||
|
||||
static void rdp_load_tlut(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
int tilenum = (w2 >> 24) & 0x7;
|
||||
|
||||
rdpChanged |= RDP_BITS_TILE_SETTINGS;
|
||||
|
||||
#define tile rdpTiles[tilenum]
|
||||
//rdpTile_t tile;
|
||||
tile.sl = (w1 >> 12) & 0xfff;
|
||||
tile.tl = (w1 >> 0) & 0xfff;
|
||||
tile.sh = (w2 >> 12) & 0xfff;
|
||||
tile.th = (w2 >> 0) & 0xfff;
|
||||
|
||||
int i;
|
||||
|
||||
rdpChanged |= RDP_BITS_TLUT;
|
||||
|
||||
int count = ((tile.sh - tile.sl + 4) >>2) * ((tile.th - tile.tl + 4) >>2);
|
||||
|
||||
switch (rdpTiSize)
|
||||
{
|
||||
case RDP_PIXEL_SIZE_16BIT:
|
||||
{
|
||||
uint16_t *src = (uint16_t *)&rdram[(rdpTiAddress + (tile.tl >>2) * rdpTiWidth * 2 + ((tile.sl >>2) << rdpTiSize >> 1))/4];
|
||||
uint16_t *dst = (uint16_t *)(rdpTmem + rdpTiles[tilenum].tmem);
|
||||
|
||||
// printf("loading TLUT from %x --> %x\n",
|
||||
// tile.th * rdpTiWidth / 2 + (tile.sh << rdpTiSize >> 1)/4
|
||||
|
||||
for (i=0; i < count; i++)
|
||||
{
|
||||
dst[i*4] = src[i^1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: LOGERROR("RDP: load_tlut: size = %d\n", rdpTiSize);
|
||||
}
|
||||
#undef tile
|
||||
}
|
||||
|
||||
static void rdp_set_tile_size(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
int tilenum = (w2 >> 24) & 0x7;
|
||||
|
||||
rdpChanged |= RDP_BITS_TILE_SETTINGS;
|
||||
|
||||
#define tile rdpTiles[tilenum]
|
||||
tile.sl = (w1 >> 12) & 0xfff;
|
||||
tile.tl = (w1 >> 0) & 0xfff;
|
||||
tile.sh = (w2 >> 12) & 0xfff;
|
||||
tile.th = (w2 >> 0) & 0xfff;
|
||||
#undef tile
|
||||
}
|
||||
|
||||
static void rdp_load_block(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
int i, width;
|
||||
uint16_t sl, sh, tl, dxt;
|
||||
int tilenum = (w2 >> 24) & 0x7;
|
||||
uint32_t *src, *tc;
|
||||
int tb;
|
||||
|
||||
rdpChanged |= RDP_BITS_TMEM;
|
||||
|
||||
sl = ((w1 >> 12) & 0xfff);
|
||||
tl = ((w1 >> 0) & 0xfff) << 11;
|
||||
sh = ((w2 >> 12) & 0xfff);
|
||||
dxt = ((w2 >> 0) & 0xfff);
|
||||
|
||||
width = (sh - sl + 1) << rdpTiSize >> 1;
|
||||
|
||||
src = (uint32_t*)&rdram[0];
|
||||
tc = (uint32_t*)rdpTmem;
|
||||
tb = rdpTiles[tilenum].tmem/4;
|
||||
|
||||
//printf("Load block to %x width %x\n", rdpTiles[tilenum].tmem, width);
|
||||
|
||||
MarkTmemArea(rdpTiles[tilenum].tmem, rdpTiles[tilenum].tmem + width,
|
||||
tl * rdpTiWidth*4 + rdpTiAddress + sl*4, 0, ~0, ~0);
|
||||
|
||||
if (tb+width/4 > 0x1000/4) {
|
||||
LOG("load_block : fixup too large width\n");
|
||||
width = 0x1000-tb*4;
|
||||
}
|
||||
|
||||
if (dxt != 0)
|
||||
{
|
||||
int j=0;
|
||||
|
||||
//rglAssert(tb+width/4 <= 0x1000/4);
|
||||
|
||||
int swap = rdpTiles[tilenum].size == 3? 2 : 1;
|
||||
|
||||
for (i=0; i < width / 4; i+=2)
|
||||
{
|
||||
int t = j >> 11;
|
||||
|
||||
tc[(((tb+i) + 0) ^ ((t & 1) ? swap : 0))&0x3ff] =
|
||||
src[rdpTiAddress / 4 + ((tl * rdpTiWidth) / 4) + sl + i + 0];
|
||||
tc[(((tb+i) + 1) ^ ((t & 1) ? swap : 0))&0x3ff] =
|
||||
src[rdpTiAddress / 4 + ((tl * rdpTiWidth) / 4) + sl + i + 1];
|
||||
|
||||
j += dxt;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//rglAssert(tb+width/4 <= 0x1000/4);
|
||||
for (i=0; i < width / 4; i++)
|
||||
{
|
||||
tc[(tb+i)&0x3ff] = src[((tl * rdpTiWidth) / 4) + rdpTiAddress / 4 + sl + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rdp_load_tile(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
int i, j;
|
||||
uint16_t sl, sh, tl, th;
|
||||
int width, height;
|
||||
int tilenum = (w2 >> 24) & 0x7;
|
||||
int line;
|
||||
|
||||
rdpChanged |= RDP_BITS_TMEM;
|
||||
|
||||
sl = ((w1 >> 12) & 0xfff) / 4;
|
||||
tl = ((w1 >> 0) & 0xfff) / 4;
|
||||
sh = ((w2 >> 12) & 0xfff) / 4;
|
||||
th = ((w2 >> 0) & 0xfff) / 4;
|
||||
|
||||
width = (sh - sl) + 1;
|
||||
height = (th - tl) + 1;
|
||||
|
||||
// printf("Load tile to %x line %x height %d\n",
|
||||
// rdpTiles[tilenum].tmem,
|
||||
// rdpTiles[tilenum].line,
|
||||
// height);
|
||||
|
||||
rdpTiles[tilenum].size = rdpTiSize; // CHECK THIS
|
||||
line = rdpTiles[tilenum].line;
|
||||
switch (rdpTiles[tilenum].size /*rdpTiSize*/)
|
||||
{
|
||||
case RDP_PIXEL_SIZE_8BIT:
|
||||
{
|
||||
uint8_t *src = (uint8_t*)&rdram[0];
|
||||
uint8_t *tc = (uint8_t*)rdpTmem;
|
||||
int tb = rdpTiles[tilenum].tmem;
|
||||
|
||||
MarkTmemArea(tb, tb + height*line, rdpTiAddress + tl * rdpTiWidth + sl,
|
||||
rdpTiWidth, rdpTiFormat, rdpTiSize);
|
||||
|
||||
if (tb + (line * (height-1) + width) > 4096)
|
||||
{
|
||||
LOGERROR("rdp_load_tile 8-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
|
||||
height = (4096-tb)/line;
|
||||
}
|
||||
|
||||
for (j=0; j < height; j++)
|
||||
{
|
||||
int tline = tb + (rdpTiles[tilenum].line * j);
|
||||
int s = ((j + tl) * rdpTiWidth) + sl;
|
||||
|
||||
for (i=0; i < width; i++)
|
||||
{
|
||||
tc[(((tline+i) ^ BYTE_ADDR_XOR) ^ ((j & 1) ? 4 : 0))&0xfff] = src[(rdpTiAddress + s++) ^ BYTE_ADDR_XOR];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RDP_PIXEL_SIZE_16BIT:
|
||||
{
|
||||
uint16_t *src = (uint16_t*)&rdram[0];
|
||||
uint16_t *tc = (uint16_t*)rdpTmem;
|
||||
int tb = (rdpTiles[tilenum].tmem / 2);
|
||||
|
||||
if (tb + (line/2 * (height-1) + width) > 2048)
|
||||
{
|
||||
LOGERROR("rdp_load_tile 16-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
|
||||
height = (2048 - tb) / (line/2);
|
||||
}
|
||||
|
||||
MarkTmemArea(tb*2, tb*2 + height*line,
|
||||
rdpTiAddress + (tl * rdpTiWidth + sl)*2,
|
||||
rdpTiWidth*2, rdpTiFormat, rdpTiSize);
|
||||
|
||||
for (j=0; j < height; j++)
|
||||
{
|
||||
int tline = tb + ((rdpTiles[tilenum].line / 2) * j);
|
||||
int s = ((j + tl) * rdpTiWidth) + sl;
|
||||
|
||||
for (i=0; i < width; i++)
|
||||
{
|
||||
tc[(((tline+i) ^ WORD_ADDR_XOR) ^ ((j & 1) ? 2 : 0))&0x7ff] = src[(rdpTiAddress / 2 + s++) ^ WORD_ADDR_XOR];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RDP_PIXEL_SIZE_32BIT:
|
||||
{
|
||||
uint32_t *src = (uint32_t*)&rdram[0];
|
||||
uint32_t *tc = (uint32_t*)rdpTmem;
|
||||
int tb = (rdpTiles[tilenum].tmem / 4);
|
||||
|
||||
MarkTmemArea(tb*4, tb*4 + height*line*2,
|
||||
rdpTiAddress + (tl * rdpTiWidth + sl)*4,
|
||||
rdpTiWidth*4, rdpTiFormat, rdpTiSize);
|
||||
|
||||
if (tb + (line/2 * (height-1) + width) > 1024)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "rdp_load_tile 32-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
|
||||
}
|
||||
|
||||
for (j=0; j < height; j++)
|
||||
{
|
||||
int tline = tb + ((rdpTiles[tilenum].line / 2) * j);
|
||||
int s = ((j + tl) * rdpTiWidth) + sl;
|
||||
|
||||
for (i=0; i < width; i++)
|
||||
{
|
||||
tc[((tline+i) ^ ((j & 1) ? 2 : 0))&0x3ff] = src[(rdpTiAddress / 4 + s++)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
rdp_log(M64MSG_ERROR, "RDP: load_tile: size = %d\n", rdpTiSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdp_set_tile(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
int tilenum = (w2 >> 24) & 0x7;
|
||||
//int i;
|
||||
|
||||
rdpChanged |= RDP_BITS_TILE_SETTINGS;
|
||||
rdpTileSet |= 1<<tilenum;
|
||||
|
||||
#define tile rdpTiles[tilenum]
|
||||
tile.format = (w1 >> 21) & 0x7;
|
||||
tile.size = (w1 >> 19) & 0x3;
|
||||
tile.line = ((w1 >> 9) & 0x1ff) * 8;
|
||||
tile.tmem = ((w1 >> 0) & 0x1ff) * 8;
|
||||
tile.palette= (w2 >> 20) & 0xf;
|
||||
tile.ct = (w2 >> 19) & 0x1;
|
||||
tile.mt = (w2 >> 18) & 0x1;
|
||||
tile.mask_t = (w2 >> 14) & 0xf;
|
||||
tile.shift_t= (w2 >> 10) & 0xf;
|
||||
if (tile.shift_t >= 12) tile.shift_t -= 16;
|
||||
tile.cs = (w2 >> 9) & 0x1;
|
||||
tile.ms = (w2 >> 8) & 0x1;
|
||||
tile.mask_s = (w2 >> 4) & 0xf;
|
||||
tile.shift_s= (w2 >> 0) & 0xf;
|
||||
if (tile.shift_s >= 12) tile.shift_s -= 16;
|
||||
#undef tile
|
||||
}
|
||||
|
||||
static void rdp_fill_rect(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpRect_t rect;
|
||||
rect.xl = (w1 >> 12) & 0xfff;
|
||||
rect.yl = (w1 >> 0) & 0xfff;
|
||||
rect.xh = (w2 >> 12) & 0xfff;
|
||||
rect.yh = (w2 >> 0) & 0xfff;
|
||||
|
||||
rglFillRectangle(&rect);
|
||||
}
|
||||
|
||||
static void rdp_set_fill_color(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_FILL_COLOR;
|
||||
rdpState.fillColor = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_fog_color(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_FOG_COLOR;
|
||||
rdpState.fogColor = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_blend_color(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_BLEND_COLOR;
|
||||
rdpState.blendColor = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_prim_color(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_PRIM_COLOR;
|
||||
// TODO: prim min level, prim_level
|
||||
rdpState.primColor = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_env_color(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_ENV_COLOR;
|
||||
rdpState.envColor = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_combine(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_COMBINE_MODES;
|
||||
|
||||
rdpState.combineModes.w1 = w1;
|
||||
rdpState.combineModes.w2 = w2;
|
||||
}
|
||||
|
||||
static void rdp_set_texture_image(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_TI_SETTINGS;
|
||||
|
||||
rdpTiFormat = (w1 >> 21) & 0x7;
|
||||
rdpTiSize = (w1 >> 19) & 0x3;
|
||||
rdpTiWidth = (w1 & 0x3ff) + 1;
|
||||
rdpTiAddress = w2 & 0x01ffffff;
|
||||
}
|
||||
|
||||
static void rdp_set_mask_image(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_ZB_SETTINGS;
|
||||
rdpZbAddress = w2 & 0x01ffffff;
|
||||
}
|
||||
|
||||
static void rdp_set_color_image(uint32_t w1, uint32_t w2)
|
||||
{
|
||||
rdpChanged |= RDP_BITS_FB_SETTINGS;
|
||||
rdpFbFormat = (w1 >> 21) & 0x7;
|
||||
rdpFbSize = (w1 >> 19) & 0x3;
|
||||
rdpFbWidth = (w1 & 0x3ff) + 1;
|
||||
rdpFbAddress = w2 & 0x01ffffff;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void (* rdp_command_table[64])(uint32_t w1, uint32_t w2) =
|
||||
{
|
||||
/* 0x00 */
|
||||
rdp_noop, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_tri_noshade, rdp_tri_noshade_z, rdp_tri_tex, rdp_tri_tex_z,
|
||||
rdp_tri_shade, rdp_tri_shade_z, rdp_tri_texshade, rdp_tri_texshade_z,
|
||||
/* 0x10 */
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
/* 0x20 */
|
||||
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
|
||||
rdp_tex_rect, rdp_tex_rect_flip, rdp_sync_load, rdp_sync_pipe,
|
||||
rdp_sync_tile, rdp_sync_full, rdp_set_key_gb, rdp_set_key_r,
|
||||
rdp_set_convert, rdp_set_scissor, rdp_set_prim_depth, rdp_set_other_modes,
|
||||
/* 0x30 */
|
||||
rdp_load_tlut, rdp_invalid, rdp_set_tile_size, rdp_load_block,
|
||||
rdp_load_tile, rdp_set_tile, rdp_fill_rect, rdp_set_fill_color,
|
||||
rdp_set_fog_color, rdp_set_blend_color, rdp_set_prim_color, rdp_set_env_color,
|
||||
rdp_set_combine, rdp_set_texture_image, rdp_set_mask_image, rdp_set_color_image
|
||||
};
|
||||
|
||||
void rdp_process_list(void)
|
||||
{
|
||||
//int i;
|
||||
uint32_t cmd;//, length, cmd_length;
|
||||
|
||||
rglUpdateStatus();
|
||||
if (!rglSettings.threaded)
|
||||
rdp_store_list();
|
||||
|
||||
if (rglStatus == RGL_STATUS_CLOSED)
|
||||
return;
|
||||
|
||||
// this causes problem with depth writeback in zelda mm
|
||||
// but is necessary for in fisherman
|
||||
rglUpdate();
|
||||
|
||||
while (rdp_cmd_cur != rdp_cmd_ptr)
|
||||
{
|
||||
cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
|
||||
// if (((rdp_cmd_data[rdp_cmd_cur] >> 24) & 0xc0) != 0xc0)
|
||||
// {
|
||||
// LOGERROR("rdp_process_list: invalid rdp command %08X at %08X\n", rdp_cmd_data[rdp_cmd_cur], dp_start+(rdp_cmd_cur * 4));
|
||||
// }
|
||||
|
||||
if ((((rdp_cmd_ptr-rdp_cmd_cur)&(MAXCMD-1)) * 4) < rdp_command_length[cmd])
|
||||
{
|
||||
// LOGERROR("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", rdp_cmd_cur, rdp_cmd_ptr, rdp_command_length[cmd]);
|
||||
// return;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
if (rdp_dump)
|
||||
{
|
||||
char string[4000];
|
||||
int rdp_dasm(uint32_t * rdp_cmd_data, int rdp_cmd_cur, int length, char *buffer);
|
||||
rdp_dasm(rdp_cmd_data, rdp_cmd_cur, rdp_command_length[cmd], string);
|
||||
|
||||
fprintf(stderr, "%08X: %08X %08X %s\n", dp_start+(rdp_cmd_cur * 4), rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1], string);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
memcpy(rdpTraceBuf+rdpTracePos, rdp_cmd_data+rdp_cmd_cur, rdp_command_length[cmd]);
|
||||
#endif
|
||||
|
||||
if (rdp_cmd_cur + rdp_command_length[cmd]/4 > MAXCMD)
|
||||
memcpy(rdp_cmd_data + MAXCMD, rdp_cmd_data, rdp_command_length[cmd] - (MAXCMD - rdp_cmd_cur)*4);
|
||||
|
||||
// execute the command
|
||||
rdp_command_table[cmd](rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1]);
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
rdpTracePos += rdp_command_length[cmd] / 4;
|
||||
rglAssert(rdpTracePos < sizeof(rdpTraceBuf)/sizeof(rdpTraceBuf[0]));
|
||||
#endif
|
||||
|
||||
rdp_cmd_cur = (rdp_cmd_cur + rdp_command_length[cmd] / 4) & (MAXCMD-1);
|
||||
}
|
||||
|
||||
// dp_current = dp_end;
|
||||
// dp_start = dp_end;
|
||||
dp_start = dp_current;
|
||||
|
||||
dp_status &= ~0x0002;
|
||||
}
|
||||
|
||||
int rdp_store_list(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t data, cmd, length;
|
||||
int sync = 0;
|
||||
|
||||
// while (dp_current < dp_end) {
|
||||
|
||||
// }
|
||||
// dp_status &= ~0x0002;
|
||||
|
||||
length = dp_end - dp_current;
|
||||
|
||||
// LOG("rdp start %x cur %x end %x length %d dp_status %x\n",
|
||||
// dp_start, dp_current, dp_end,
|
||||
// length, dp_status);
|
||||
|
||||
if (dp_end <= dp_current) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// load command data
|
||||
for (i=0; i < length; i += 4)
|
||||
{
|
||||
data = READ_RDP_DATA(dp_current + i);
|
||||
if (rglSettings.async) {
|
||||
if (rdp_cmd_left) {
|
||||
rdp_cmd_left--;
|
||||
} else {
|
||||
cmd = (data >> 24) & 0x3f;
|
||||
rdp_cmd_left = rdp_command_length[cmd]/4-1;
|
||||
if (cmd == 0x29) // full_sync
|
||||
sync = 1;
|
||||
}
|
||||
}
|
||||
rdp_cmd_data[rdp_cmd_ptr] = data;
|
||||
rdp_cmd_ptr = (rdp_cmd_ptr + 1) & (MAXCMD-1);
|
||||
}
|
||||
|
||||
dp_current += length;
|
||||
|
||||
return sync;
|
||||
}
|
||||
|
||||
|
||||
int rdp_init()
|
||||
{
|
||||
rdp_cmd_cur = rdp_cmd_ptr = 0;
|
||||
rdp_cmd_left = 0;
|
||||
#ifdef RDP_DEBUG
|
||||
rdpTracePos = 0;
|
||||
#endif
|
||||
nbTmemAreas = 0;
|
||||
return rglInit();
|
||||
}
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _RDP_H_
|
||||
#define _RDP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define M64P_PLUGIN_PROTOTYPES 1
|
||||
#include "m64p_types.h"
|
||||
#include "m64p_common.h"
|
||||
#include "m64p_plugin.h"
|
||||
#include "m64p_vidext.h"
|
||||
#include "m64p_config.h"
|
||||
|
||||
#define LSB_FIRST 1 // TODO : check for platform
|
||||
#ifdef LSB_FIRST
|
||||
#define BYTE_ADDR_XOR 3
|
||||
#define WORD_ADDR_XOR 1
|
||||
#define BYTE4_XOR_BE(a) ((a) ^ 3) /* read/write a byte to a 32-bit space */
|
||||
#else
|
||||
#define BYTE_ADDR_XOR 0
|
||||
#define WORD_ADDR_XOR 0
|
||||
#define BYTE4_XOR_BE(a) (a)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define RDP_PIXEL_SIZE_4BIT 0
|
||||
#define RDP_PIXEL_SIZE_8BIT 1
|
||||
#define RDP_PIXEL_SIZE_16BIT 2
|
||||
#define RDP_PIXEL_SIZE_32BIT 3
|
||||
|
||||
#define RDP_FORMAT_RGBA 0
|
||||
#define RDP_FORMAT_YUV 1
|
||||
#define RDP_FORMAT_CI 2
|
||||
#define RDP_FORMAT_IA 3
|
||||
#define RDP_FORMAT_I 4
|
||||
|
||||
#define RDP_CYCLE_TYPE_1 0
|
||||
#define RDP_CYCLE_TYPE_2 1
|
||||
#define RDP_CYCLE_TYPE_COPY 2
|
||||
#define RDP_CYCLE_TYPE_FILL 3
|
||||
|
||||
typedef uint32_t rdpColor_t;
|
||||
|
||||
#define RDP_GETC32_R(c) ( ((c)>>24) & 0xff )
|
||||
#define RDP_GETC32_G(c) ( ((c)>>16) & 0xff )
|
||||
#define RDP_GETC32_B(c) ( ((c)>> 8) & 0xff )
|
||||
#define RDP_GETC32_A(c) ( ((c)>> 0) & 0xff )
|
||||
|
||||
#define RDP_GETC16_R(c) ( ((c)>>11) & 0x1f )
|
||||
#define RDP_GETC16_G(c) ( ((c)>> 6) & 0x1f )
|
||||
#define RDP_GETC16_B(c) ( ((c)>> 1) & 0x1f )
|
||||
#define RDP_GETC16_A(c) ( ((c)>> 0) & 0x1 )
|
||||
|
||||
struct rdpRect_t {
|
||||
uint16_t xl, yl, xh, yh; // 10.2 fixed-point
|
||||
};
|
||||
|
||||
struct rdpTexRect_t {
|
||||
int tilenum;
|
||||
uint16_t xl, yl, xh, yh; // 10.2 fixed-point
|
||||
int16_t s, t; // 10.5 fixed-point
|
||||
int16_t dsdx, dtdy; // 5.10 fixed-point
|
||||
};
|
||||
|
||||
extern const char *rdpImageFormats[];
|
||||
|
||||
// TODO put ct ... palette in a bitfield
|
||||
struct rdpTile_t {
|
||||
uint16_t line;
|
||||
uint16_t tmem;
|
||||
uint16_t sl, tl, sh, th; // 10.2 fixed-point
|
||||
uint16_t w, h;
|
||||
int8_t format, size;
|
||||
int8_t mask_t, shift_t, mask_s, shift_s;
|
||||
int8_t ct, mt, cs, ms;
|
||||
int8_t palette;
|
||||
};
|
||||
|
||||
struct rdpCombineModes_t {
|
||||
uint32_t w1, w2;
|
||||
};
|
||||
|
||||
#define RDP_GETCM_SUB_A_RGB0(cm) (((cm).w1 >> 20) & 0xf)
|
||||
#define RDP_GETCM_MUL_RGB0(cm) (((cm).w1 >> 15) & 0x1f)
|
||||
#define RDP_GETCM_SUB_A_A0(cm) (((cm).w1 >> 12) & 0x7)
|
||||
#define RDP_GETCM_MUL_A0(cm) (((cm).w1 >> 9) & 0x7)
|
||||
#define RDP_GETCM_SUB_A_RGB1(cm) (((cm).w1 >> 5) & 0xf)
|
||||
#define RDP_GETCM_MUL_RGB1(cm) (((cm).w1 >> 0) & 0x1f)
|
||||
|
||||
#define RDP_GETCM_SUB_B_RGB0(cm) (((cm).w2 >> 28) & 0xf)
|
||||
#define RDP_GETCM_SUB_B_RGB1(cm) (((cm).w2 >> 24) & 0xf)
|
||||
#define RDP_GETCM_SUB_A_A1(cm) (((cm).w2 >> 21) & 0x7)
|
||||
#define RDP_GETCM_MUL_A1(cm) (((cm).w2 >> 18) & 0x7)
|
||||
#define RDP_GETCM_ADD_RGB0(cm) (((cm).w2 >> 15) & 0x7)
|
||||
#define RDP_GETCM_SUB_B_A0(cm) (((cm).w2 >> 12) & 0x7)
|
||||
#define RDP_GETCM_ADD_A0(cm) (((cm).w2 >> 9) & 0x7)
|
||||
#define RDP_GETCM_ADD_RGB1(cm) (((cm).w2 >> 6) & 0x7)
|
||||
#define RDP_GETCM_SUB_B_A1(cm) (((cm).w2 >> 3) & 0x7)
|
||||
#define RDP_GETCM_ADD_A1(cm) (((cm).w2 >> 0) & 0x7)
|
||||
|
||||
#define RDP_COMBINE_MASK11 ((0xfu<<20)|(0x1fu<<15)|(0x7u<<12)|(0x7u<<9))
|
||||
#define RDP_COMBINE_MASK12 ((0xfu<<28)|(0x7u<<15)|(0x7u<<12)|(0x7u<<9))
|
||||
#define RDP_COMBINE_MASK21 ((0xfu<<5)|(0x1fu<<0))
|
||||
#define RDP_COMBINE_MASK22 ((0xfu<<24)|(0x7u<<21)|(0x7u<<18)|(0x7u<<6)|(0x7u<<3)|(0x7u<<0))
|
||||
|
||||
static const rdpCombineModes_t rdpCombineMasks[4] = {
|
||||
{ ~RDP_COMBINE_MASK21, ~RDP_COMBINE_MASK22 },
|
||||
{ ~0u, ~0u },
|
||||
{ ~(RDP_COMBINE_MASK11|RDP_COMBINE_MASK21), ~(RDP_COMBINE_MASK12|RDP_COMBINE_MASK22) },
|
||||
{ ~(RDP_COMBINE_MASK11|RDP_COMBINE_MASK21), ~(RDP_COMBINE_MASK12|RDP_COMBINE_MASK22) },
|
||||
};
|
||||
|
||||
struct rdpOtherModes_t {
|
||||
uint32_t w1, w2;
|
||||
};
|
||||
|
||||
#define RDP_OM_MISSING1 (~((3<<20)|0x80000|0x40000|0x20000|0x10000|0x08000| \
|
||||
0x04000|0x02000|0x01000|0x00800|0x00400|0x00200| \
|
||||
0x00100|(3<<6)|(3<<4)))
|
||||
#define RDP_OM_MISSING2 (~(0xffff0000|0x4000|0x2000|0x1000|(3<<10)|(3<<8)| \
|
||||
0x80|0x40|0x20|0x10|0x08|0x04|0x02|0x01))
|
||||
|
||||
#define RDP_GETOM_CYCLE_TYPE(om) (((om).w1 >> 20) & 0x3)
|
||||
#define RDP_GETOM_PERSP_TEX_EN(om) (((om).w1 & 0x80000) ? 1 : 0)
|
||||
#define RDP_GETOM_DETAIL_TEX_EN(om) (((om).w1 & 0x40000) ? 1 : 0)
|
||||
#define RDP_GETOM_SHARPEN_TEX_EN(om) (((om).w1 & 0x20000) ? 1 : 0)
|
||||
#define RDP_GETOM_TEX_LOD_EN(om) (((om).w1 & 0x10000) ? 1 : 0)
|
||||
#define RDP_GETOM_EN_TLUT(om) (((om).w1 & 0x08000) ? 1 : 0)
|
||||
#define RDP_GETOM_TLUT_TYPE(om) (((om).w1 & 0x04000) ? 1 : 0)
|
||||
#define RDP_GETOM_SAMPLE_TYPE(om) (((om).w1 & 0x02000) ? 1 : 0)
|
||||
#define RDP_GETOM_MID_TEXEL(om) (((om).w1 & 0x01000) ? 1 : 0)
|
||||
#define RDP_GETOM_BI_LERP0(om) (((om).w1 & 0x00800) ? 1 : 0)
|
||||
#define RDP_GETOM_BI_LERP1(om) (((om).w1 & 0x00400) ? 1 : 0)
|
||||
#define RDP_GETOM_CONVERT_ONE(om) (((om).w1 & 0x00200) ? 1 : 0)
|
||||
#define RDP_GETOM_KEY_EN(om) (((om).w1 & 0x00100) ? 1 : 0)
|
||||
#define RDP_GETOM_RGB_DITHER_SEL(om) (((om).w1 >> 6) & 0x3)
|
||||
#define RDP_GETOM_ALPHA_DITHER_SEL(om) (((om).w1 >> 4) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M1A_0(om) (((om).w2 >> 30) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M1A_1(om) (((om).w2 >> 28) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M1B_0(om) (((om).w2 >> 26) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M1B_1(om) (((om).w2 >> 24) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M2A_0(om) (((om).w2 >> 22) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M2A_1(om) (((om).w2 >> 20) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M2B_0(om) (((om).w2 >> 18) & 0x3)
|
||||
#define RDP_GETOM_BLEND_M2B_1(om) (((om).w2 >> 16) & 0x3)
|
||||
#define RDP_GETOM_FORCE_BLEND(om) (((om).w2 & 0x4000) ? 1 : 0)
|
||||
#define RDP_GETOM_ALPHA_CVG_SELECT(om) (((om).w2 & 0x2000) ? 1 : 0)
|
||||
#define RDP_GETOM_CVG_TIMES_ALPHA(om) (((om).w2 & 0x1000) ? 1 : 0)
|
||||
#define RDP_GETOM_Z_MODE(om) (((om).w2 >> 10) & 0x3)
|
||||
#define RDP_GETOM_CVG_DEST(om) (((om).w2 >> 8) & 0x3)
|
||||
#define RDP_GETOM_COLOR_ON_CVG(om) (((om).w2 & 0x80) ? 1 : 0)
|
||||
#define RDP_GETOM_IMAGE_READ_EN(om) (((om).w2 & 0x40) ? 1 : 0)
|
||||
#define RDP_GETOM_Z_UPDATE_EN(om) (((om).w2 & 0x20) ? 1 : 0)
|
||||
#define RDP_GETOM_Z_COMPARE_EN(om) (((om).w2 & 0x10) ? 1 : 0)
|
||||
#define RDP_GETOM_ANTIALIAS_EN(om) (((om).w2 & 0x08) ? 1 : 0)
|
||||
#define RDP_GETOM_Z_SOURCE_SEL(om) (((om).w2 & 0x04) ? 1 : 0)
|
||||
#define RDP_GETOM_DITHER_ALPHA_EN(om) (((om).w2 & 0x02) ? 1 : 0)
|
||||
#define RDP_GETOM_ALPHA_COMPARE_EN(om) (((om).w2 & 0x01) ? 1 : 0)
|
||||
|
||||
#define RDP_BLEND_MASK1 ((3u<<30)|(3u<<26)|(3u<<22)|(3u<<18))
|
||||
#define RDP_BLEND_MASK2 ((3u<<28)|(3u<<24)|(3u<<20)|(3u<<16))
|
||||
|
||||
static const rdpOtherModes_t rdpBlendMasks[4] = {
|
||||
{ ~0u, ~RDP_BLEND_MASK2 },
|
||||
{ ~0u, ~0u },
|
||||
{ ~0u, ~(RDP_BLEND_MASK1|RDP_BLEND_MASK2) },
|
||||
{ ~0u, ~(RDP_BLEND_MASK1|RDP_BLEND_MASK2) },
|
||||
};
|
||||
|
||||
struct rdpState_t {
|
||||
rdpCombineModes_t combineModes;
|
||||
rdpOtherModes_t otherModes;
|
||||
rdpColor_t blendColor;
|
||||
rdpColor_t primColor;
|
||||
rdpColor_t envColor;
|
||||
rdpColor_t fogColor;
|
||||
rdpColor_t fillColor;
|
||||
int primitiveZ;
|
||||
int primitiveDeltaZ;
|
||||
rdpRect_t clip;
|
||||
uint8_t k5, clipMode;
|
||||
};
|
||||
|
||||
extern rdpState_t rdpState;
|
||||
extern uint32_t rdpChanged;
|
||||
//extern rdpColor_t rdpTlut[];
|
||||
#define rdpTlut ((uint16_t *) (rdpTmem + 0x800))
|
||||
extern uint8_t rdpTmem[];
|
||||
extern int rdpFbFormat;
|
||||
extern int rdpFbSize;
|
||||
extern int rdpFbWidth;
|
||||
extern uint32_t rdpFbAddress;
|
||||
extern uint32_t rdpZbAddress;
|
||||
extern int rdpTiFormat;
|
||||
extern int rdpTiSize;
|
||||
extern int rdpTiWidth;
|
||||
extern uint32_t rdpTiAddress;
|
||||
extern rdpTile_t rdpTiles[8];
|
||||
extern int rdpTileSet;
|
||||
|
||||
#define RDP_BITS_COMBINE_MODES (1<<0)
|
||||
#define RDP_BITS_OTHER_MODES (1<<1)
|
||||
#define RDP_BITS_CLIP (1<<2)
|
||||
#define RDP_BITS_BLEND_COLOR (1<<3)
|
||||
#define RDP_BITS_PRIM_COLOR (1<<4)
|
||||
#define RDP_BITS_ENV_COLOR (1<<5)
|
||||
#define RDP_BITS_FOG_COLOR (1<<6)
|
||||
#define RDP_BITS_FB_SETTINGS (1<<7)
|
||||
#define RDP_BITS_ZB_SETTINGS (1<<8)
|
||||
#define RDP_BITS_TI_SETTINGS (1<<9)
|
||||
#define RDP_BITS_TMEM (1<<10)
|
||||
#define RDP_BITS_TLUT (1<<11)
|
||||
#define RDP_BITS_TILE_SETTINGS (1<<12)
|
||||
#define RDP_BITS_FILL_COLOR (1<<13)
|
||||
#define RDP_BITS_MISC (1<<14)
|
||||
|
||||
// return where the data in rdram came from at this address in tmem
|
||||
uint32_t rdpGetTmemOrigin(int tmem, int * line, int * stop, int * fromFormat, int * size);
|
||||
|
||||
|
||||
int rdp_init();
|
||||
int rdp_dasm(uint32_t * rdp_cmd_data, int rdp_cmd_cur, int length, char *buffer);
|
||||
void rdp_process_list(void);
|
||||
int rdp_store_list(void);
|
||||
|
||||
void rdp_log(m64p_msg_level level, const char *msg, ...);
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
|
||||
extern uint32_t rdpTraceBuf[];
|
||||
extern int rdpTracePos;
|
||||
|
||||
extern int rdp_dump;
|
||||
|
||||
#define DUMP if (!rdp_dump) ; else LOG
|
||||
|
||||
static void LOG(const char * s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
vfprintf(stderr, s, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#define LOGERROR LOG
|
||||
|
||||
#else // RDP_DEBUG
|
||||
|
||||
#define DUMP(...) rdp_log(M64MSG_VERBOSE, __VA_ARGS__)
|
||||
#define LOG(...) rdp_log(M64MSG_VERBOSE, __VA_ARGS__)
|
||||
#define LOGERROR(...) rdp_log(M64MSG_WARNING, __VA_ARGS__)
|
||||
|
||||
#endif // RDP_DEBUG
|
||||
|
||||
|
||||
#endif // _RDP_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _RGL_H_
|
||||
#define _RGL_H_
|
||||
|
||||
#include "queue.h"
|
||||
#include "rgl_assert.h"
|
||||
#include "rdp.h"
|
||||
|
||||
#include <glew.h>
|
||||
#if defined(__MACOSX__)
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(__MACOS__)
|
||||
#include <gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
//#include <IL/il.h>
|
||||
#endif
|
||||
|
||||
#include "glshader.h"
|
||||
|
||||
#include <limits.h> //for PATH_MAX
|
||||
|
||||
#define DWORD unsigned int
|
||||
extern GFX_INFO gfx;
|
||||
#define rdram ((uint32_t*)gfx.RDRAM)
|
||||
#define rsp_imem ((uint32_t*)gfx.IMEM)
|
||||
#define rsp_dmem ((uint32_t*)gfx.DMEM)
|
||||
#define vi_origin (*(uint32_t*)gfx.VI_ORIGIN_REG)
|
||||
#define vi_width (*(uint32_t*)gfx.VI_WIDTH_REG)
|
||||
#define vi_control (*(uint32_t*)gfx.VI_STATUS_REG)
|
||||
|
||||
#define dp_start (*(uint32_t*)gfx.DPC_START_REG)
|
||||
#define dp_end (*(uint32_t*)gfx.DPC_END_REG)
|
||||
#define dp_current (*(uint32_t*)gfx.DPC_CURRENT_REG)
|
||||
#define dp_status (*(uint32_t*)gfx.DPC_STATUS_REG)
|
||||
|
||||
// highly experimental AND slow
|
||||
//#define RGL_EXACT_BLEND
|
||||
|
||||
struct rglSettings_t {
|
||||
int hiresFb;
|
||||
int resX, resY;
|
||||
int fsResX, fsResY;
|
||||
int fbInfo;
|
||||
int forceSwap;
|
||||
int threaded;
|
||||
int async;
|
||||
int noNpotFbos;
|
||||
int lowres;
|
||||
int fullscreen;
|
||||
};
|
||||
|
||||
extern rglSettings_t rglSettings;
|
||||
extern void (*render_callback)(int);
|
||||
|
||||
struct rglDepthBuffer_t {
|
||||
uint32_t address;
|
||||
int width, height;
|
||||
GLuint zbid;
|
||||
};
|
||||
#define MAX_DEPTH_BUFFERS 16
|
||||
extern rglDepthBuffer_t zBuffers[MAX_DEPTH_BUFFERS];
|
||||
extern int nbZBuffers;
|
||||
|
||||
struct rglRenderBuffer_t;
|
||||
struct rglDepthSection_t {
|
||||
rglRenderBuffer_t * buffer;
|
||||
int chunkId;
|
||||
};
|
||||
#define RGL_MAX_DEPTH_SECTIONS 16
|
||||
|
||||
struct rglRenderBuffer_t {
|
||||
CIRCLEQ_ENTRY(rglRenderBuffer_t) link;
|
||||
uint32_t addressStart, addressStop;
|
||||
int format, size, fbWidth, line;
|
||||
int width, height;
|
||||
int flags;
|
||||
GLuint texid, fbid;
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
GLuint texid2, fbid2;
|
||||
#endif
|
||||
int realWidth, realHeight;
|
||||
int fboWidth, fboHeight;
|
||||
int redimensionStamp;
|
||||
rdpRect_t area;
|
||||
rdpRect_t mod;
|
||||
rglDepthBuffer_t * depthBuffer;
|
||||
int chunkId;
|
||||
rglDepthSection_t depthSections[16];
|
||||
int nbDepthSections;
|
||||
};
|
||||
#define RGL_RB_DEPTH 1
|
||||
#define RGL_RB_FULL 2
|
||||
#define RGL_RB_ERASED 4
|
||||
#define RGL_RB_FBMOD 8 // the GL framebuffer was modified
|
||||
#define RGL_RB_RAMMOD 16 // the framebuffer was modified in rdram
|
||||
#define RGL_RB_HASTRIANGLES 32 // we assume it's not a depth buffer in this case
|
||||
|
||||
CIRCLEQ_HEAD(rglRenderBufferHead_t, rglRenderBuffer_t);
|
||||
|
||||
#define MAX_RENDER_BUFFERS 64
|
||||
extern rglRenderBuffer_t rBuffers[MAX_RENDER_BUFFERS];
|
||||
extern int nbRBuffers;
|
||||
extern rglRenderBuffer_t * curRBuffer;
|
||||
extern rglRenderBuffer_t * curZBuffer;
|
||||
extern rglRenderBufferHead_t rBufferHead;
|
||||
|
||||
extern int rglTexCacheCounter;
|
||||
struct rglTexture_t {
|
||||
CIRCLEQ_ENTRY(rglTexture_t) byCrc, byUsage;
|
||||
GLuint id, zid;
|
||||
uint32_t crc;
|
||||
int w, h, fmt;
|
||||
int clipw, cliph;
|
||||
GLuint ws, wt, filter; // current settings
|
||||
};
|
||||
CIRCLEQ_HEAD(rglTextureHead_t, rglTexture_t);
|
||||
#define RGL_TEX_CACHE_SIZE 1024
|
||||
extern rglTexture_t rglTextures[RGL_TEX_CACHE_SIZE];
|
||||
struct rglTexCache_t {
|
||||
int counter;
|
||||
rglTexture_t * tex;
|
||||
};
|
||||
extern rglTexCache_t rglTexCache[0x1000];
|
||||
extern uint8_t rglTmpTex[];
|
||||
extern uint8_t rglTmpTex2[];
|
||||
|
||||
struct rglTile_t : public rdpTile_t {
|
||||
rglTexture_t * tex;
|
||||
rglRenderBuffer_t * hiresBuffer;
|
||||
uint32_t hiresAddress;
|
||||
GLuint ws, wt; // GL clamping modes
|
||||
GLuint filter; // GL filter mode
|
||||
};
|
||||
|
||||
struct rglVertex_t {
|
||||
float x, y, z, w;
|
||||
float s, t;
|
||||
uint8_t r, g, b, a;
|
||||
};
|
||||
|
||||
struct rglStrip_t {
|
||||
int tilenum;
|
||||
int nbVtxs;
|
||||
int flags;
|
||||
rglVertex_t * vtxs;
|
||||
};
|
||||
|
||||
#define RGL_STRIP_TEX1 1
|
||||
#define RGL_STRIP_TEX2 2
|
||||
#define RGL_STRIP_SHADE 4
|
||||
#define RGL_STRIP_ZBUFFER 8
|
||||
|
||||
struct rglRenderChunk_t {
|
||||
rdpState_t rdpState;
|
||||
rglTile_t tiles[8];
|
||||
rglRenderBuffer_t * renderBuffer;
|
||||
uint32_t depthAddress;
|
||||
int flags;
|
||||
int nbStrips;
|
||||
rglStrip_t * strips;
|
||||
#ifdef RDP_DEBUG
|
||||
rglShader_t * shader;
|
||||
int tracePos;
|
||||
#endif
|
||||
};
|
||||
|
||||
// first 8 bits used for tile usage
|
||||
#define RGL_CHUNK_CLEAR (1<<8)
|
||||
|
||||
#define MAX_RENDER_CHUNKS 40000
|
||||
extern rglRenderChunk_t chunks[MAX_RENDER_CHUNKS];
|
||||
extern rglRenderChunk_t * curChunk;
|
||||
extern int nbChunks;
|
||||
|
||||
#define MAX_STRIPS 80000
|
||||
extern rglStrip_t strips[MAX_STRIPS];
|
||||
extern rglVertex_t vtxs[6*MAX_STRIPS];
|
||||
extern int nbStrips, nbVtxs;
|
||||
|
||||
struct rglRenderMode_t {
|
||||
rdpOtherModes_t otherModes;
|
||||
rdpCombineModes_t combineModes;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define RGL_RM_DEPTH 1
|
||||
|
||||
// TODO use a hash table
|
||||
#define MAX_RENDER_MODES 1024
|
||||
extern rglRenderMode_t renderModesDb[MAX_RENDER_MODES];
|
||||
extern int nbRenderModes;
|
||||
|
||||
extern rglShader_t * rglCopyShader;
|
||||
extern rglShader_t * rglCopyDepthShader;
|
||||
|
||||
|
||||
#define RGL_COMB_FMT_RGBA 0
|
||||
#define RGL_COMB_FMT_I 1
|
||||
#define RGL_COMB_FMT_DEPTH 2
|
||||
#define RGL_COMB_FMT 3
|
||||
#define RGL_COMB_IN0_DEPTH 4
|
||||
#define RGL_COMB_IN0 4
|
||||
#define RGL_COMB_IN1_DEPTH 8
|
||||
#define RGL_COMB_IN1 8
|
||||
#define RGL_COMB_TILE7 16
|
||||
|
||||
extern volatile int rglStatus, rglNextStatus;
|
||||
#define RGL_STATUS_CLOSED 0
|
||||
#define RGL_STATUS_WINDOWED 1
|
||||
#define RGL_STATUS_FULLSCREEN 2
|
||||
|
||||
|
||||
void rglUpdateStatus();
|
||||
void rglTouchTMEM();
|
||||
void rglResetTextureCache();
|
||||
void rglTile(rdpTile_t & tile, rglTile_t & rtile, int recth);
|
||||
void rglRenderMode(rglRenderChunk_t & chunk);
|
||||
void rglBlender(rglRenderChunk_t & chunk);
|
||||
void rglClearCombiners();
|
||||
void rglSetCombiner(rglRenderChunk_t & chunk, int format);
|
||||
void rglPrepareRendering(int texturing, int tilenum, int recth, int depth);
|
||||
rglRenderBuffer_t * rglSelectRenderBuffer(uint32_t addr, int width, int size, int format);
|
||||
char * rglCombiner2String(rdpState_t & state);
|
||||
|
||||
|
||||
int rglInit();
|
||||
void rglClose();
|
||||
int rglOpenScreen();
|
||||
void rglCloseScreen();
|
||||
int rglReadSettings();
|
||||
void rglUpdate();
|
||||
void rglFullSync();
|
||||
void rglTextureRectangle(rdpTexRect_t * rect, int flip);
|
||||
void rglFillRectangle(rdpRect_t * rect);
|
||||
void rglTriangle(uint32_t w1, uint32_t w2, int shade, int texture, int zbuffer,
|
||||
uint32_t * rdp_cmd);
|
||||
void rglRenderChunks();
|
||||
void rglDisplayFramebuffers();
|
||||
int rglT1Usage(rdpState_t & state);
|
||||
int rglT2Usage(rdpState_t & state);
|
||||
void rglDebugger();
|
||||
void rglCloseDebugger();
|
||||
void rglFramebuffer2Rdram(rglRenderBuffer_t & buffer, uint32_t start, uint32_t stop);
|
||||
void rglRdram2Framebuffer(rglRenderBuffer_t & buffer, uint32_t start, uint32_t stop);
|
||||
void rglRenderChunks(rglRenderBuffer_t * upto);
|
||||
void rglRenderChunks(int upto);
|
||||
float rglZscale(uint16_t z);
|
||||
|
||||
void rglSwapBuffers();
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
extern void check();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _RGL_ASSERT_H_
|
||||
#define _RGL_ASSERT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef RGL_ASSERT
|
||||
inline void _rglAssert(int test, const char * s, int line, const char * file) {
|
||||
if (!test) {
|
||||
fprintf(stderr, "z64 assert failed (%s : %d) : %s\n", file, line, s);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
*(unsigned int *)0 = 0xdeadbeef; // hopefully will generate a segfault
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#define rglAssert(test) _rglAssert((test), #test, __LINE__, __FILE__)
|
||||
#else
|
||||
#define rglAssert(test)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,861 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
static const char *saRGBText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "NOISE", "1",
|
||||
"0", "0", "0", "0",
|
||||
"0", "0", "0", "0"
|
||||
};
|
||||
|
||||
static const char *mRGBText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "SCALE", "PREV_ALPHA",
|
||||
"TEXEL0_ALPHA", "TEXEL1_ALPHA", "PRIM_ALPHA", "SHADE_ALPHA",
|
||||
"ENV_ALPHA", "LOD_FRACTION", "PRIM_LOD_FRAC", "K5",
|
||||
"0", "0", "0", "0",
|
||||
"0", "0", "0", "0",
|
||||
"0", "0", "0", "0",
|
||||
"0", "0", "0", "0"
|
||||
};
|
||||
|
||||
static const char *aRGBText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "1", "0",
|
||||
};
|
||||
|
||||
static const char *saAText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "1", "0",
|
||||
};
|
||||
|
||||
static const char *sbAText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "1", "0",
|
||||
};
|
||||
|
||||
static const char *mAText[] =
|
||||
{
|
||||
"LOD_FRACTION", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "PRIM_LOD_FRAC", "0",
|
||||
};
|
||||
|
||||
static const char *aAText[] =
|
||||
{
|
||||
"PREV", "TEXEL0", "TEXEL1", "PRIM",
|
||||
"SHADE", "ENV", "1", "0",
|
||||
};
|
||||
|
||||
const static char * bRGBText[] = { "PREV", "FRAG", "BLEND", "FOG" };
|
||||
const static char * bAText[2][4] = { {"PREVA", "FOGA", "SHADEA", "0"},
|
||||
{"(1.0-ALPHA)", "FRAGA", "1", "0"}};
|
||||
|
||||
char * rglCombiner2String(rdpState_t & state)
|
||||
{
|
||||
rdpOtherModes_t om = state.otherModes;
|
||||
int cycle = RDP_GETOM_CYCLE_TYPE(om);
|
||||
static char res[256];
|
||||
char * p = res;
|
||||
if (cycle < 2) {
|
||||
p += sprintf(
|
||||
p,
|
||||
"c = [ (%s - %s) * %s + %s | (%s - %s) * %s + %s ]\n",
|
||||
saRGBText[RDP_GETCM_SUB_A_RGB0(state.combineModes)],
|
||||
saRGBText[RDP_GETCM_SUB_B_RGB0(state.combineModes)],
|
||||
mRGBText[RDP_GETCM_MUL_RGB0(state.combineModes)],
|
||||
aRGBText[RDP_GETCM_ADD_RGB0(state.combineModes)],
|
||||
saAText[RDP_GETCM_SUB_A_A0(state.combineModes)],
|
||||
sbAText[RDP_GETCM_SUB_B_A0(state.combineModes)],
|
||||
mAText[RDP_GETCM_MUL_A0(state.combineModes)],
|
||||
aAText[RDP_GETCM_ADD_A0(state.combineModes)]);
|
||||
}
|
||||
if (cycle == 1) {
|
||||
p += sprintf(
|
||||
p,
|
||||
"c = [ (%s - %s) * %s + %s | (%s - %s) * %s + %s ]\n",
|
||||
saRGBText[RDP_GETCM_SUB_A_RGB1(state.combineModes)],
|
||||
saRGBText[RDP_GETCM_SUB_B_RGB1(state.combineModes)],
|
||||
mRGBText[RDP_GETCM_MUL_RGB1(state.combineModes)],
|
||||
aRGBText[RDP_GETCM_ADD_RGB1(state.combineModes)],
|
||||
saAText[RDP_GETCM_SUB_A_A1(state.combineModes)],
|
||||
sbAText[RDP_GETCM_SUB_B_A1(state.combineModes)],
|
||||
mAText[RDP_GETCM_MUL_A1(state.combineModes)],
|
||||
aAText[RDP_GETCM_ADD_A1(state.combineModes)]);
|
||||
}
|
||||
if (cycle < 2) {
|
||||
p += sprintf(
|
||||
p,
|
||||
"%s*%s + %s*%s\n"
|
||||
,bAText[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M1A_0(state.otherModes)],
|
||||
bAText[1][RDP_GETOM_BLEND_M2B_0(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M2A_0(state.otherModes)]
|
||||
);
|
||||
}
|
||||
if (cycle == 1) {
|
||||
p += sprintf(
|
||||
p,
|
||||
"%s*%s + %s*%s\n"
|
||||
,bAText[0][RDP_GETOM_BLEND_M1B_1(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M1A_1(state.otherModes)],
|
||||
bAText[1][RDP_GETOM_BLEND_M2B_1(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M2A_1(state.otherModes)]
|
||||
);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
|
||||
#include <SDL.h>
|
||||
//#include <IL/il.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <FTGLTextureFont.h>
|
||||
|
||||
#define FONT "LucidaTypewriterRegular.ttf"
|
||||
#define SMALLFONT "LucidaTypewriterRegular.ttf"
|
||||
//#define SMALLFONT "/usr/share/fonts/corefonts/arial.ttf"
|
||||
#define FS 12
|
||||
#define SMALLFS 12
|
||||
|
||||
static FTFont * font;
|
||||
static FTFont * smallfont;
|
||||
static FTFont * curfont;
|
||||
|
||||
static int fbindex;
|
||||
static int chunkindex, stripindex;
|
||||
static int mx, my;
|
||||
static float scalex, scaley;
|
||||
static rglShader_t * alphaShader;
|
||||
|
||||
static int lines[0x10000], nblines;
|
||||
static char dasm[512];
|
||||
|
||||
void gglPrint(int x, int y, const char * text)
|
||||
{
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0);
|
||||
|
||||
glEnable( GL_TEXTURE_2D);
|
||||
glDisable( GL_DEPTH_TEST);
|
||||
//glRasterPos2i( x , y);
|
||||
curfont->Render(text);
|
||||
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
|
||||
//printf("%s\n", text);
|
||||
}
|
||||
|
||||
void gglPrintf(int x, int y, const char * s, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
vsprintf(buf, s, ap);
|
||||
va_end(ap);
|
||||
gglPrint(x, y, buf);
|
||||
}
|
||||
|
||||
void rglDisplayTrace(int x, int y, int start, int lines)
|
||||
{
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
rglUseShader(0);
|
||||
curfont = smallfont;
|
||||
start = ::lines[start];
|
||||
while (lines-->0 && start <= rdpTracePos) {
|
||||
glColor4f(0,0,0, 0.5);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glVertex2f(x, y);
|
||||
glVertex2f(x+2*screen_width*3/4, y);
|
||||
glVertex2f(x, y-(SMALLFS+2));
|
||||
glVertex2f(x+2*screen_width*3/4, y-(SMALLFS+2));
|
||||
glEnd();
|
||||
|
||||
glColor4f(1,1,0.5,1);
|
||||
glDisable(GL_BLEND);
|
||||
start += rdp_dasm(rdpTraceBuf, start, start+256, dasm)/4;
|
||||
gglPrintf(x, y-(SMALLFS), "%4x %s", start, dasm);
|
||||
y -= (SMALLFS+2);
|
||||
}
|
||||
curfont = font;
|
||||
// glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void rglDisplayColor(uint32_t color, int x , int y, const char * name, int sixteen = 0)
|
||||
{
|
||||
float r, g, b, a;
|
||||
if (sixteen) {
|
||||
r = RDP_GETC16_R(color)/ 31.0f;
|
||||
g = RDP_GETC16_G(color)/ 31.0f;
|
||||
b = RDP_GETC16_B(color)/ 31.0f;
|
||||
a = RDP_GETC16_A(color)/ 1.0f;
|
||||
} else {
|
||||
r = RDP_GETC32_R(color)/255.0f;
|
||||
g = RDP_GETC32_G(color)/255.0f;
|
||||
b = RDP_GETC32_B(color)/255.0f;
|
||||
a = RDP_GETC32_A(color)/255.0f;
|
||||
}
|
||||
y -= FS+2;
|
||||
glColor4f(r, g, b, 1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glVertex2f(x, y);
|
||||
glVertex2f(x+128, y);
|
||||
glVertex2f(x, y-16);
|
||||
glVertex2f(x+128, y-16);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glColor4f(1,1,1,1);
|
||||
gglPrintf(x, y+2, "%5s %08x", name, color);
|
||||
|
||||
}
|
||||
|
||||
void rglDisplayChunkInfo(rglRenderChunk_t & chunk)
|
||||
{
|
||||
int x = 0, y = screen_height;
|
||||
int i;
|
||||
rdpState_t & state = chunk.rdpState;
|
||||
rdpOtherModes_t om = state.otherModes;
|
||||
rdpCombineModes_t cm = state.combineModes;
|
||||
int cycle = RDP_GETOM_CYCLE_TYPE(om);
|
||||
|
||||
rglDisplayColor(chunk.rdpState.primColor, x, y, "prim");
|
||||
y -= 16+FS+10;
|
||||
rglDisplayColor(chunk.rdpState.blendColor, x, y, "blend");
|
||||
y -= 16+FS+10;
|
||||
rglDisplayColor(chunk.rdpState.envColor, x, y, "env");
|
||||
y -= 16+FS+10;
|
||||
rglDisplayColor(chunk.rdpState.fogColor, x, y, "fog");
|
||||
y -= 16+FS+10;
|
||||
rglDisplayColor(chunk.rdpState.fillColor, x, y, "fill", 1);
|
||||
y -= 16+FS+10;
|
||||
|
||||
y += 5*(16+FS+10);
|
||||
x += 128+20;
|
||||
|
||||
glColor4f(1,1,1,1);
|
||||
int oldy = y;
|
||||
for (i=0; i<8; i++) {
|
||||
int j;
|
||||
int oldx = x;
|
||||
if (!(chunk.flags & (1<<i))) continue;
|
||||
rglTile_t & tile = chunk.tiles[i];
|
||||
int w = tile.w, h = tile.h;
|
||||
if (w > 64) w = 64;
|
||||
if (h > 64) h = 64;
|
||||
gglPrintf(x, y-h-FS, "#%d %dx%d %x", i, tile.w, tile.h, tile.hiresBuffer? 0 : tile.tex->crc);
|
||||
gglPrintf(x, y-h-2*FS, "fmt %s-%d %d %d", rdpImageFormats[tile.format], tile.size, tile.line, tile.hiresBuffer? tile.hiresBuffer-rBuffers : -1);
|
||||
gglPrintf(x, y-h-3*FS, "clip %dx%d %dx%d", tile.sl, tile.tl, tile.sh, tile.th);
|
||||
gglPrintf(x, y-h-4*FS, "mask %dx%d shift %dx%d", tile.mask_s, tile.mask_t, tile.shift_s, tile.shift_t);
|
||||
gglPrintf(x, y-h-5*FS, "%d %d %d %d pal %d", tile.cs, tile.ms, tile.ct, tile.ms, tile.palette);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
if (tile.hiresBuffer)
|
||||
glBindTexture(GL_TEXTURE_2D, tile.hiresBuffer->texid);
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, tile.tex->id);
|
||||
for (j=0; j<2; j++) {
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(0, 0); glVertex2f(x, y);
|
||||
glTexCoord2f(0, 1); glVertex2f(x, y-h);
|
||||
glTexCoord2f(1, 0); glVertex2f(x+w, y);
|
||||
glTexCoord2f(1, 1); glVertex2f(x+w, y-h);
|
||||
glEnd();
|
||||
rglUseShader(alphaShader);
|
||||
x += w+2;
|
||||
}
|
||||
rglUseShader(0);
|
||||
// if ((tile.w+2)*2 < 256)
|
||||
// x += 256 - (tile.w+2)*2;
|
||||
x = oldx;
|
||||
y -= h + 5*FS + 5;
|
||||
}
|
||||
|
||||
y = oldy;
|
||||
x = 128+210;
|
||||
|
||||
y -= FS;
|
||||
gglPrintf(x, y, "cycle %d persp %d detail %d sharpen %d tex_lod %d en_tlut %d tlut_type %d clipm %d",
|
||||
RDP_GETOM_CYCLE_TYPE(om),
|
||||
RDP_GETOM_PERSP_TEX_EN(om),
|
||||
RDP_GETOM_DETAIL_TEX_EN(om),
|
||||
RDP_GETOM_SHARPEN_TEX_EN(om),
|
||||
RDP_GETOM_TEX_LOD_EN(om),
|
||||
RDP_GETOM_EN_TLUT(om),
|
||||
RDP_GETOM_TLUT_TYPE(om),
|
||||
chunk.rdpState.clipMode);
|
||||
|
||||
y -= FS;
|
||||
gglPrintf(x, y, "sample_type %d mid %d lerp0 %d lerp1 %d convert1 %d key_en %d rgb_dith_sel %d",
|
||||
RDP_GETOM_SAMPLE_TYPE(om),
|
||||
RDP_GETOM_MID_TEXEL(om),
|
||||
RDP_GETOM_BI_LERP0(om),
|
||||
RDP_GETOM_BI_LERP1(om),
|
||||
RDP_GETOM_CONVERT_ONE(om),
|
||||
RDP_GETOM_KEY_EN(om),
|
||||
RDP_GETOM_RGB_DITHER_SEL(om));
|
||||
|
||||
y -= FS;
|
||||
gglPrintf(x, y, "A_dith_sel %d force_blend %d A_cvg_sel %d cvgXA %d Zmode %d cvg_dest %d col_on %d",
|
||||
RDP_GETOM_ALPHA_DITHER_SEL(om),
|
||||
RDP_GETOM_FORCE_BLEND(om),
|
||||
RDP_GETOM_ALPHA_CVG_SELECT(om),
|
||||
RDP_GETOM_CVG_TIMES_ALPHA(om),
|
||||
RDP_GETOM_Z_MODE(om),
|
||||
RDP_GETOM_CVG_DEST(om),
|
||||
RDP_GETOM_COLOR_ON_CVG(om));
|
||||
|
||||
y -= FS;
|
||||
gglPrintf(x, y, "img_read %d Zupdate %d Zcmp_sel %d antialias %d Zsource %d dith_A_en %d A_cmp %d",
|
||||
RDP_GETOM_IMAGE_READ_EN(om),
|
||||
RDP_GETOM_Z_UPDATE_EN(om),
|
||||
RDP_GETOM_Z_COMPARE_EN(om),
|
||||
RDP_GETOM_ANTIALIAS_EN(om),
|
||||
RDP_GETOM_Z_SOURCE_SEL(om),
|
||||
RDP_GETOM_DITHER_ALPHA_EN(om),
|
||||
RDP_GETOM_ALPHA_COMPARE_EN(om));
|
||||
|
||||
y -= 2*FS;
|
||||
|
||||
if (cycle < 2) {
|
||||
gglPrintf(x, y,
|
||||
"c = [ (%s - %s) * %s + %s | (%s - %s) * %s + %s ];",
|
||||
saRGBText[RDP_GETCM_SUB_A_RGB0(state.combineModes)],
|
||||
saRGBText[RDP_GETCM_SUB_B_RGB0(state.combineModes)],
|
||||
mRGBText[RDP_GETCM_MUL_RGB0(state.combineModes)],
|
||||
aRGBText[RDP_GETCM_ADD_RGB0(state.combineModes)],
|
||||
saAText[RDP_GETCM_SUB_A_A0(state.combineModes)],
|
||||
sbAText[RDP_GETCM_SUB_B_A0(state.combineModes)],
|
||||
mAText[RDP_GETCM_MUL_A0(state.combineModes)],
|
||||
aAText[RDP_GETCM_ADD_A0(state.combineModes)]);
|
||||
|
||||
y -= FS;
|
||||
}
|
||||
if (cycle == 1) {
|
||||
//if (cycle < 2) {
|
||||
gglPrintf(x, y,
|
||||
"c = [ (%s - %s) * %s + %s | (%s - %s) * %s + %s ];",
|
||||
saRGBText[RDP_GETCM_SUB_A_RGB1(state.combineModes)],
|
||||
saRGBText[RDP_GETCM_SUB_B_RGB1(state.combineModes)],
|
||||
mRGBText[RDP_GETCM_MUL_RGB1(state.combineModes)],
|
||||
aRGBText[RDP_GETCM_ADD_RGB1(state.combineModes)],
|
||||
saAText[RDP_GETCM_SUB_A_A1(state.combineModes)],
|
||||
sbAText[RDP_GETCM_SUB_B_A1(state.combineModes)],
|
||||
mAText[RDP_GETCM_MUL_A1(state.combineModes)],
|
||||
aAText[RDP_GETCM_ADD_A1(state.combineModes)]);
|
||||
|
||||
y -= FS;
|
||||
}
|
||||
if (cycle < 2) {
|
||||
gglPrintf(x, y,
|
||||
"%s*%s + %s*%s"
|
||||
,bAText[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M1A_0(state.otherModes)],
|
||||
bAText[1][RDP_GETOM_BLEND_M2B_0(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M2A_0(state.otherModes)]
|
||||
);
|
||||
|
||||
y -= FS;
|
||||
}
|
||||
if (cycle == 1) {
|
||||
//if (cycle < 2) {
|
||||
gglPrintf(x, y,
|
||||
"%s*%s + %s*%s"
|
||||
,bAText[0][RDP_GETOM_BLEND_M1B_1(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M1A_1(state.otherModes)],
|
||||
bAText[1][RDP_GETOM_BLEND_M2B_1(state.otherModes)],
|
||||
bRGBText[RDP_GETOM_BLEND_M2A_1(state.otherModes)]
|
||||
);
|
||||
|
||||
y -= FS;
|
||||
}
|
||||
|
||||
if (chunk.nbStrips) {
|
||||
y -= FS;
|
||||
rglStrip_t & strip = chunk.strips[chunkindex >= 0? stripindex:0];
|
||||
|
||||
int i;
|
||||
for (i=0; i<strip.nbVtxs; i++) {
|
||||
rglVertex_t vtx = strip.vtxs[i];
|
||||
int oldx;
|
||||
gglPrintf(x, y, "%g %g %g %g", vtx.x, vtx.y, vtx.z, vtx.w);
|
||||
x += 256;
|
||||
if (strip.flags & RGL_STRIP_SHADE) {
|
||||
gglPrintf(x, y, "%d %d %d %d", vtx.r, vtx.g, vtx.b, vtx.a);
|
||||
x += 200;
|
||||
}
|
||||
if (strip.flags & (RGL_STRIP_TEX1|RGL_STRIP_TEX2)) {
|
||||
gglPrintf(x, y, "%g %g", vtx.s, vtx.t);
|
||||
x += 192;
|
||||
}
|
||||
y -= FS;
|
||||
x = oldx;
|
||||
}
|
||||
}
|
||||
|
||||
// LOG("missing om %x %x (%x %x)\n",
|
||||
// chunk.rdpState.otherModes.w1&RDP_OM_MISSING1,
|
||||
// chunk.rdpState.otherModes.w2&RDP_OM_MISSING2,
|
||||
// RDP_OM_MISSING1,
|
||||
// RDP_OM_MISSING2);
|
||||
// LOG("missing cm %x %x\n",
|
||||
// chunk.rdpState.combineModes.w1&~(RDP_COMBINE_MASK11|RDP_COMBINE_MASK21),
|
||||
// chunk.rdpState.combineModes.w2&~(RDP_COMBINE_MASK12|RDP_COMBINE_MASK22));
|
||||
}
|
||||
|
||||
void rglDisplayFramebuffer(rglRenderBuffer_t & buffer, int alpha)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (alpha)
|
||||
rglUseShader(alphaShader);
|
||||
else
|
||||
rglUseShader(rglCopyShader);
|
||||
glBindTexture(GL_TEXTURE_2D, buffer.texid);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glColor4ub(255, 255, 255, 255);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(1, 1); glVertex2f(1, 0);
|
||||
glTexCoord2f(0, 1); glVertex2f(0, 0);
|
||||
glTexCoord2f(1, 0); glVertex2f(1, 1);
|
||||
glTexCoord2f(0, 0); glVertex2f(0, 1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void rglDisplayFlat(rglRenderChunk_t & chunk)
|
||||
{
|
||||
int j;
|
||||
rglRenderBuffer_t & buffer = *chunk.renderBuffer;
|
||||
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
//glEnable(GL_SCISSOR_TEST);
|
||||
rglUseShader(0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// glScissor((chunk.rdpState.clip.xh >>2)*buffer.realWidth/buffer.width,
|
||||
// (chunk.rdpState.clip.yh >>2)*buffer.realHeight/buffer.height,
|
||||
// (chunk.rdpState.clip.xl-chunk.rdpState.clip.xh >>2)*buffer.realWidth/buffer.width,
|
||||
// (chunk.rdpState.clip.yl-chunk.rdpState.clip.yh >>2)*buffer.realHeight/buffer.height);
|
||||
|
||||
|
||||
for (j=0; j<chunk.nbStrips; j++) {
|
||||
rglStrip_t & strip = chunk.strips[j];
|
||||
int k;
|
||||
|
||||
if (chunkindex >= 0 && j == stripindex) {
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glColor4ub(255, 255, 128, 255);
|
||||
}
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (k=0; k<strip.nbVtxs; k++) {
|
||||
glVertex2f((strip.vtxs[k].x/(buffer.width)),
|
||||
1-(strip.vtxs[k].y/(buffer.height)));
|
||||
}
|
||||
glEnd();
|
||||
if (chunkindex >= 0 && j == stripindex)
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
int rglFindStrip(rglRenderChunk_t & chunk, float mx, float my)
|
||||
{
|
||||
int j;
|
||||
rglRenderBuffer_t & buffer = *chunk.renderBuffer;
|
||||
for (j=chunk.nbStrips-1; j>=0; j--) {
|
||||
rglStrip_t & strip = chunk.strips[j];
|
||||
int k;
|
||||
struct { float x, y; } s[3];
|
||||
|
||||
for (k=0; k<strip.nbVtxs; k++) {
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2].x = strip.vtxs[k].x/(buffer.width);
|
||||
s[2].y = 1 - strip.vtxs[k].y/(buffer.height);
|
||||
if (k >= 2) {
|
||||
float last = 0;
|
||||
int i;
|
||||
for (i=0; i<3; i++) {
|
||||
float dx1 = s[(i+1)%3].x - s[i].x;
|
||||
float dy1 = s[(i+1)%3].y - s[i].y;
|
||||
float dx2 = mx - s[i].x;
|
||||
float dy2 = my - s[i].y;
|
||||
dx1 = dx1*dy2-dx2*dy1;
|
||||
if (dx1 == 0) goto next;
|
||||
if (last*dx1 < 0)
|
||||
goto next;
|
||||
last = dx1;
|
||||
}
|
||||
stripindex = j;
|
||||
return j;
|
||||
next:;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void rglDisplayFlat(rglRenderBuffer_t & buffer)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<nbChunks; i++) {
|
||||
rglRenderChunk_t & chunk = chunks[i];
|
||||
if (chunk.renderBuffer != &buffer) continue;
|
||||
rglDisplayFlat(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
int rglFindChunk(rglRenderBuffer_t & buffer, float mx, float my)
|
||||
{
|
||||
int i;
|
||||
if (chunkindex <= 0)
|
||||
i = nbChunks-1;
|
||||
else
|
||||
i = chunkindex-1;
|
||||
for (; i>=0; i--) {
|
||||
rglRenderChunk_t & chunk = chunks[i];
|
||||
if (chunk.renderBuffer != &buffer) continue;
|
||||
if (rglFindStrip(chunk, mx, my) >= 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void rglShowCursor(int state)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#else
|
||||
SDL_ShowCursor(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
static int keys[512];
|
||||
#define MOUSEBUT 511
|
||||
#else
|
||||
# define MOUSEBUT VK_LBUTTON
|
||||
# define SDLK_ESCAPE VK_ESCAPE
|
||||
# define SDLK_KP_PLUS VK_ADD
|
||||
# define SDLK_KP_MINUS VK_SUBTRACT
|
||||
# define SDLK_TAB VK_TAB
|
||||
# define SDLK_UP VK_UP
|
||||
# define SDLK_DOWN VK_DOWN
|
||||
# define SDLK_PAGEUP VK_PRIOR
|
||||
# define SDLK_PAGEDOWN VK_NEXT
|
||||
#endif
|
||||
|
||||
int rglCheckKey(int key)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return GetAsyncKeyState (key) & 1;
|
||||
#else
|
||||
if (key >= 'A' && key <= 'Z') key += 'a' - 'A';
|
||||
int res = keys[key];
|
||||
keys[key] = 0;
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
void rglDebugger()
|
||||
{
|
||||
SDL_Event event;
|
||||
int paused = 1;
|
||||
int i, j;
|
||||
int traceX = 1;
|
||||
int tracepos = 0;
|
||||
int tracepage = (screen_height*3/4)/(SMALLFS+2);
|
||||
int oldchunkindex = -1;
|
||||
|
||||
fbindex = 0;
|
||||
chunkindex = -1;
|
||||
|
||||
void rglInitDebugger();
|
||||
rglInitDebugger();
|
||||
|
||||
rglShowCursor(SDL_ENABLE);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glActiveTextureARB(GL_TEXTURE2_ARB);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glDrawBuffer(GL_BACK);
|
||||
|
||||
for (i=nblines=0; i<=rdpTracePos; i += rdp_dasm(rdpTraceBuf, i, i+256, dasm)/4, nblines++)
|
||||
lines[nblines] = i;
|
||||
|
||||
if (nbChunks > 1)
|
||||
// skip chunk 0 as it's usually depth clear
|
||||
fbindex = chunks[1].renderBuffer - rBuffers;
|
||||
|
||||
while (paused) {
|
||||
#ifndef WIN32
|
||||
int res = SDL_WaitEvent(&event);
|
||||
while (res) {
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
keys[MOUSEBUT] = 1;
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
keys[MOUSEBUT] = 0;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym < MOUSEBUT)
|
||||
keys[event.key.keysym.sym] = 1;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
if (event.key.keysym.sym < MOUSEBUT)
|
||||
keys[event.key.keysym.sym] = 0;
|
||||
break;
|
||||
}
|
||||
res = SDL_PollEvent(&event);
|
||||
}
|
||||
#endif
|
||||
rglRenderBuffer_t & buffer = rBuffers[fbindex];
|
||||
scalex = buffer.realWidth; scaley = buffer.realHeight;
|
||||
|
||||
if (rBuffers[fbindex].fbid) {
|
||||
if (buffer.realWidth > scalex*3/4 ||
|
||||
buffer.realHeight > scaley*3/4) {
|
||||
scalex = scalex*3/4;
|
||||
scaley = scaley*3/4;
|
||||
}
|
||||
}
|
||||
|
||||
if (rglCheckKey(MOUSEBUT)) {
|
||||
if (buffer.fbid) {
|
||||
#ifdef WIN32
|
||||
POINT pt;
|
||||
GetCursorPos(&pt);
|
||||
mx = pt.x;
|
||||
my = pt.y;
|
||||
#else
|
||||
SDL_GetMouseState(&mx, &my);
|
||||
#endif
|
||||
int old = chunkindex;
|
||||
if (old >= 0)
|
||||
chunkindex++;
|
||||
chunkindex = rglFindChunk(buffer, float(mx)/scalex, float(screen_height - my)/scaley);
|
||||
if (old >= 0 && chunkindex == old) {
|
||||
} else {
|
||||
chunkindex = -1;
|
||||
}
|
||||
chunkindex = rglFindChunk(buffer, float(mx)/scalex, float(screen_height - my)/scaley);
|
||||
if (chunkindex >= 0 && nbChunks)
|
||||
printf("%s\n", chunks[chunkindex].shader->fsrc);
|
||||
}
|
||||
}
|
||||
if (rglCheckKey('P') || rglCheckKey(SDLK_ESCAPE))
|
||||
paused = 0;
|
||||
if (rglCheckKey(SDLK_KP_PLUS)) {
|
||||
if (fbindex < MAX_RENDER_BUFFERS-1/* &&
|
||||
rBuffers[fbindex+1].fbid*/)
|
||||
fbindex++;
|
||||
chunkindex = -1;
|
||||
}
|
||||
if (rglCheckKey(SDLK_KP_MINUS)) {
|
||||
if (fbindex > 0/* &&
|
||||
rBuffers[fbindex-1].fbid*/)
|
||||
fbindex--;
|
||||
chunkindex = -1;
|
||||
}
|
||||
if (rglCheckKey(SDLK_TAB))
|
||||
traceX = !traceX;
|
||||
if (rglCheckKey(SDLK_UP))
|
||||
tracepos--;
|
||||
if (rglCheckKey(SDLK_DOWN))
|
||||
tracepos++;
|
||||
if (rglCheckKey(SDLK_PAGEUP))
|
||||
tracepos -= tracepage/2;
|
||||
if (rglCheckKey(SDLK_PAGEDOWN))
|
||||
tracepos += tracepage/2;
|
||||
if (tracepos < 0)
|
||||
tracepos = 0;
|
||||
if (tracepos > nblines-tracepage/2)
|
||||
tracepos = nblines-tracepage/2;
|
||||
|
||||
//rglRenderChunks();
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDrawBuffer(GL_BACK);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (buffer.fbid) {
|
||||
//glViewport(0, 0, scalex*screen_width/buffer.realWidth, scaley*screen_height/buffer.realHeight);
|
||||
glViewport(0, 0, scalex, scaley);
|
||||
rglDisplayFramebuffer(buffer, 0);
|
||||
glViewport(scalex, 0, scalex, scaley);
|
||||
rglDisplayFramebuffer(buffer, 1);
|
||||
|
||||
glViewport(0, 0, scalex, scaley);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glEnable(GL_BLEND);
|
||||
//glBlendFunc( GL_ONE, GL_ONE );
|
||||
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_DST_COLOR);
|
||||
if (chunkindex < 0) {
|
||||
//glColor4f(0.1, 0, 0.1, 0.5);
|
||||
glColor4f(0.6, 0, 0.6, 0.5);
|
||||
rglDisplayFlat(buffer);
|
||||
} else {
|
||||
glColor4f(0.6, 0, 0.6, 0.5);
|
||||
rglDisplayFlat(chunks[chunkindex]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
||||
glMatrixMode( GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, screen_width, 0, screen_height);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
rglUseShader(0);
|
||||
|
||||
glColor3f(1,0.5,0.5);
|
||||
gglPrintf(0, 0, "Fb #%d at $%x --> %x (%dx%d fmt %s-%d) upto %d %s", fbindex,
|
||||
buffer.addressStart, buffer.addressStop,
|
||||
buffer.width, buffer.height,
|
||||
(buffer.flags & RGL_RB_DEPTH)? "Z":rdpImageFormats[buffer.format], buffer.size,
|
||||
buffer.chunkId,
|
||||
(buffer.flags & RGL_RB_ERASED)? "ERASED":"");
|
||||
|
||||
if (chunkindex >= 0) {
|
||||
gglPrintf(0, FS, "Chunk #%d", chunkindex);
|
||||
|
||||
rglDisplayChunkInfo(chunks[chunkindex]);
|
||||
}
|
||||
|
||||
if (oldchunkindex != chunkindex) {
|
||||
oldchunkindex = chunkindex;
|
||||
if (chunkindex >= 0)
|
||||
for (i=0; i<nblines; i++)
|
||||
if (lines[i] == chunks[chunkindex].tracePos)
|
||||
tracepos = i;
|
||||
}
|
||||
rglDisplayTrace(traceX*scalex, screen_height*3/4, tracepos, tracepage);
|
||||
|
||||
glMatrixMode( GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
rglSwapBuffers();
|
||||
}
|
||||
|
||||
rglShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
void rglCloseDebugger()
|
||||
{
|
||||
if (font) {
|
||||
delete font;
|
||||
font = 0;
|
||||
}
|
||||
if (smallfont) {
|
||||
delete smallfont;
|
||||
smallfont = 0;
|
||||
}
|
||||
if (alphaShader) {
|
||||
rglDeleteShader(alphaShader);
|
||||
alphaShader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rglInitDebugger()
|
||||
{
|
||||
if (!font) {
|
||||
char s[1024];
|
||||
extern char rgl_cwd[512];
|
||||
sprintf(s, "%s/"FONT, rgl_cwd);
|
||||
curfont = font = new FTGLTextureFont(s);
|
||||
sprintf(s, "%s/"SMALLFONT, rgl_cwd);
|
||||
smallfont = new FTGLTextureFont(s);
|
||||
if (!font || !smallfont) {
|
||||
LOGERROR("Couldn't load font '%s'\n", s);
|
||||
return;
|
||||
}
|
||||
font->FaceSize(FS);
|
||||
smallfont->FaceSize(SMALLFS);
|
||||
}
|
||||
|
||||
if (!alphaShader) {
|
||||
alphaShader = rglCreateShader(
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_FrontColor = gl_Color; \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
"} \n"
|
||||
,
|
||||
"uniform sampler2D texture0; \n"
|
||||
" \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_FragColor = gl_Color * texture2D(texture0, vec2(gl_TexCoord[0])).a; \n"
|
||||
"} \n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void rdpBacktrace()
|
||||
{
|
||||
int i=0;
|
||||
while (i <= rdpTracePos) {
|
||||
i += rdp_dasm(rdpTraceBuf, i, i+256, dasm)/4;
|
||||
printf("%4x %s\n", i, dasm);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,576 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
inline float _zscale(uint16_t z)
|
||||
{
|
||||
uint32_t res;
|
||||
int e = z>>(16-3);
|
||||
int m = (z>>2)&((1<<11)-1);
|
||||
|
||||
static struct {
|
||||
int shift;
|
||||
long add;
|
||||
} z_format[8] = {
|
||||
{6, 0x00000},
|
||||
{5, 0x20000},
|
||||
{4, 0x30000},
|
||||
{3, 0x38000},
|
||||
{2, 0x3c000},
|
||||
{1, 0x3e000},
|
||||
{0, 0x3f000},
|
||||
{0, 0x3f800},
|
||||
};
|
||||
|
||||
res = (m << z_format[e].shift) +
|
||||
z_format[e].add;
|
||||
return float(res)/0x3ffff;
|
||||
}
|
||||
|
||||
inline float zscale(uint16_t z)
|
||||
{
|
||||
return float(z)/0xffff;
|
||||
}
|
||||
//#define zscale _zscale
|
||||
|
||||
float rglZscale(uint16_t z)
|
||||
{
|
||||
return _zscale(z);
|
||||
}
|
||||
|
||||
void rglTextureRectangle(rdpTexRect_t * rect, int flip)
|
||||
{
|
||||
int tilenum = rect->tilenum;
|
||||
int x1,x2,y1,y2,z;
|
||||
int s, t;
|
||||
int dx, dy;
|
||||
|
||||
// if (tilenum == 7) {
|
||||
// LOG("Fixing tilenum from 7 to 0\n");
|
||||
// tilenum = 0;
|
||||
// }
|
||||
|
||||
x1 = (rect->xh);
|
||||
x2 = (rect->xl);
|
||||
y1 = (rect->yh);
|
||||
y2 = (rect->yl);
|
||||
s = int(rect->s)<<5;
|
||||
t = int(rect->t)<<5;
|
||||
|
||||
DUMP("texrect %d x %d --> %d x %d s %d t %d flip %d\n",
|
||||
x1, y1, x2, y2, s, t, flip);
|
||||
|
||||
if (RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL ||
|
||||
RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY)
|
||||
{
|
||||
rect->dsdx /= 4;
|
||||
//s /= 4;
|
||||
x2 += 4;
|
||||
y2 += 4;
|
||||
} else {
|
||||
x2 += 1;
|
||||
y2 += 1;
|
||||
}
|
||||
|
||||
x1 /= 4;
|
||||
x2 /= 4;
|
||||
y1 /= 4;
|
||||
y2 /= 4;
|
||||
|
||||
if (x2 < x1) x2 = x1+1; // black gauge in SCARS (E)
|
||||
|
||||
int t1 = rglT1Usage(rdpState)? RGL_STRIP_TEX1:0;
|
||||
int t2 = (rect->tilenum < 7 && rglT2Usage(rdpState))? RGL_STRIP_TEX2:0;
|
||||
if (t1)
|
||||
rglPrepareRendering(1, (tilenum==7 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes)==1)? 0:tilenum, y2-y1, 1);
|
||||
if (t2)
|
||||
rglPrepareRendering(1, tilenum+1, y2-y1, 1);
|
||||
else if (!t1)
|
||||
rglPrepareRendering(0, 0, 0, 1);
|
||||
|
||||
// TO BE REMOVED when we implement depth texture writing
|
||||
curRBuffer->flags |= RGL_RB_HASTRIANGLES;
|
||||
|
||||
// TO CHECK should this before or after the rescaling above ?
|
||||
// s -= (rdpTiles[tilenum].sl << 8);
|
||||
// t -= (rdpTiles[tilenum].tl << 8);
|
||||
// if (/*!tile.ms && */tile.mask_s)
|
||||
// s &= (1<<tile.mask_s+10) - 1;
|
||||
// if (/*!tile.mt && */tile.mask_t)
|
||||
// t &= (1<<tile.mask_t+10) - 1;
|
||||
|
||||
#define XSCALE(x) (float(x))
|
||||
#define YSCALE(y) (float(y))
|
||||
#define ZSCALE(z) (zscale(z))
|
||||
#define SSCALE(s) (float(s)/(1 << 10))
|
||||
#define TSCALE(s) (float(s)/(1 << 10))
|
||||
// #define glTexCoord2f(s, t) printf("tex %g %g\n", s, t), glTexCoord2f(s, t)
|
||||
// #define glVertex3f(s, t, z) printf("vert %g %g %g\n", s, t, z), glVertex3f(s, t, z)
|
||||
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
if (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes))
|
||||
z = rdpState.primitiveZ;
|
||||
else
|
||||
z = 0xffff;
|
||||
// if (dump)
|
||||
// fprintf(stderr, "fillrect cycle %d\n", other_modes.cycle_type);
|
||||
|
||||
rglStrip_t * strip = strips + nbStrips++;
|
||||
rglAssert(nbStrips < MAX_STRIPS);
|
||||
curChunk->nbStrips++;
|
||||
rglVertex_t * vtx = vtxs + nbVtxs;
|
||||
|
||||
strip->flags = t1 | t2 | RGL_STRIP_ZBUFFER;
|
||||
strip->vtxs = vtx;
|
||||
strip->tilenum = tilenum;
|
||||
|
||||
float s2, tr;
|
||||
s2 = s+int(rect->dsdx)*dx;
|
||||
tr = t+int(rect->dtdy)*dy;
|
||||
//LOG("%d %d\n", rect->dsdx, rect->dtdy);
|
||||
if (0 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) < 2)
|
||||
{
|
||||
//if (rect->dsdx == (1<<10))
|
||||
{
|
||||
s += 1<<9;
|
||||
s2 -= 1<<9;
|
||||
}
|
||||
//if (rect->dtdy == (1<<10))
|
||||
{
|
||||
t += 1<<9;
|
||||
tr -= 1<<9;
|
||||
}
|
||||
}
|
||||
|
||||
if (flip) { vtx->t = SSCALE(s2); vtx->s = TSCALE(t);
|
||||
} else { vtx->s = SSCALE(s2); vtx->t = TSCALE(t); }
|
||||
vtx->x = XSCALE(x2); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
if (flip) { vtx->t = SSCALE(s); vtx->s = TSCALE(t);
|
||||
} else { vtx->s = SSCALE(s); vtx->t = TSCALE(t); }
|
||||
vtx->x = XSCALE(x1); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
if (flip) { vtx->t = SSCALE(s2); vtx->s = TSCALE(tr);
|
||||
} else { vtx->s = SSCALE(s2); vtx->t = TSCALE(tr); }
|
||||
vtx->x = XSCALE(x2); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
if (flip) { vtx->t = SSCALE(s); vtx->s = TSCALE(tr);
|
||||
} else { vtx->s = SSCALE(s); vtx->t = TSCALE(tr); }
|
||||
vtx->x = XSCALE(x1); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
|
||||
strip->nbVtxs = vtx - strip->vtxs;
|
||||
nbVtxs = vtx - vtxs;
|
||||
}
|
||||
|
||||
void rglFillRectangle(rdpRect_t * rect)
|
||||
{
|
||||
int x1,x2,y1,y2,z;
|
||||
//int s, t;
|
||||
//int dx, dy;
|
||||
|
||||
rglPrepareRendering(0, 0, 0, 1);
|
||||
DUMP("fillrect curRBuffer->flags %x %x %x\n", curRBuffer->flags, curRBuffer->addressStart, rdpZbAddress);
|
||||
// if (/*(curRBuffer->flags & RGL_RB_DEPTH) &&*/
|
||||
// RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL &&
|
||||
// rect->xh-4 <= rdpState.clip.xh && rect->xl+8 >= rdpState.clip.xl &&
|
||||
// rect->yh-4 <= rdpState.clip.yh && rect->yl+8 >= rdpState.clip.yl
|
||||
// ) {
|
||||
// curChunk->flags |= RGL_CHUNK_CLEAR;
|
||||
// return;
|
||||
// }
|
||||
|
||||
x1 = (rect->xh / 4);
|
||||
x2 = (rect->xl / 4);
|
||||
y1 = (rect->yh / 4);
|
||||
y2 = (rect->yl / 4);
|
||||
|
||||
if (RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL ||
|
||||
RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY)
|
||||
{
|
||||
x2 += 1;
|
||||
y2 += 1;
|
||||
} else {
|
||||
//rglAssert(!(curRBuffer->flags & RGL_RB_DEPTH));
|
||||
// x2 -= 1;
|
||||
// y2 -= 1;
|
||||
}
|
||||
|
||||
if (x2 < x1) x2 = x1+1; // black gauge in SCARS (E)
|
||||
|
||||
#define XSCALE(x) (float(x))
|
||||
#define YSCALE(y) (float(y))
|
||||
#define ZSCALE(z) (zscale(z))
|
||||
|
||||
if (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes))
|
||||
z = rdpState.primitiveZ;
|
||||
else
|
||||
z = 0xffff;
|
||||
// if (dump)
|
||||
// fprintf(stderr, "fillrect cycle %d\n", other_modes.cycle_type);
|
||||
|
||||
rglStrip_t * strip = strips + nbStrips++;
|
||||
rglAssert(nbStrips < MAX_STRIPS);
|
||||
curChunk->nbStrips++;
|
||||
rglVertex_t * vtx = vtxs + nbVtxs;
|
||||
|
||||
strip->flags = RGL_STRIP_ZBUFFER;
|
||||
strip->vtxs = vtx;
|
||||
|
||||
vtx->x = XSCALE(x2); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
vtx->x = XSCALE(x1); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
vtx->x = XSCALE(x2); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
vtx->x = XSCALE(x1); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;
|
||||
|
||||
strip->nbVtxs = vtx - strip->vtxs;
|
||||
nbVtxs = vtx - vtxs;
|
||||
}
|
||||
|
||||
void rglTriangle(uint32_t w1, uint32_t w2, int shade, int texture, int zbuffer,
|
||||
uint32_t * rdp_cmd)
|
||||
{
|
||||
int tilenum = (w1 >> 16) & 0x7;
|
||||
// if (tilenum == 7) {
|
||||
// LOG("Fixing tilenum from 7 to 0\n");
|
||||
// tilenum = 0;
|
||||
// }
|
||||
int j;
|
||||
int xleft, xright, xleft_inc, xright_inc;
|
||||
//int xstart, xend;
|
||||
int r, g, b, a, z, s, t, w;
|
||||
int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
|
||||
int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
|
||||
int flip = (w1 & 0x800000) ? 1 : 0;
|
||||
|
||||
int32_t yl, ym, yh;
|
||||
int32_t xl, xm, xh;
|
||||
int64_t dxldy, dxhdy, dxmdy;
|
||||
uint32_t w3, w4, w5, w6, w7, w8;
|
||||
|
||||
uint32_t * shade_base = rdp_cmd + 8;
|
||||
uint32_t * texture_base = rdp_cmd + 8;
|
||||
uint32_t * zbuffer_base = rdp_cmd + 8;
|
||||
|
||||
int t1 = (texture && rglT1Usage(rdpState))? RGL_STRIP_TEX1:0;
|
||||
int t2 = (texture && tilenum < 7 && rglT2Usage(rdpState))? RGL_STRIP_TEX2:0;
|
||||
if (t1)
|
||||
rglPrepareRendering(1, (tilenum==7 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes)==1)? 0:tilenum, 0, zbuffer);
|
||||
if (t2)
|
||||
rglPrepareRendering(1, tilenum+1, 0, zbuffer);
|
||||
else if (!t1)
|
||||
rglPrepareRendering(0, 0, 0, zbuffer);
|
||||
|
||||
curRBuffer->flags |= RGL_RB_HASTRIANGLES;
|
||||
|
||||
if (shade)
|
||||
{
|
||||
texture_base += 16;
|
||||
zbuffer_base += 16;
|
||||
}
|
||||
if (texture)
|
||||
{
|
||||
zbuffer_base += 16;
|
||||
}
|
||||
|
||||
w3 = rdp_cmd[2];
|
||||
w4 = rdp_cmd[3];
|
||||
w5 = rdp_cmd[4];
|
||||
w6 = rdp_cmd[5];
|
||||
w7 = rdp_cmd[6];
|
||||
w8 = rdp_cmd[7];
|
||||
|
||||
yl = (w1 & 0x3fff);
|
||||
ym = ((w2 >> 16) & 0x3fff);
|
||||
yh = ((w2 >> 0) & 0x3fff);
|
||||
xl = (int32_t)(w3);
|
||||
xh = (int32_t)(w5);
|
||||
xm = (int32_t)(w7);
|
||||
dxldy = (int32_t)(w4);
|
||||
dxhdy = (int32_t)(w6);
|
||||
dxmdy = (int32_t)(w8);
|
||||
|
||||
if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
|
||||
if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
|
||||
if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
|
||||
|
||||
yh &= ~3;
|
||||
|
||||
r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;
|
||||
|
||||
if (shade)
|
||||
{
|
||||
r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);
|
||||
g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);
|
||||
b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);
|
||||
a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);
|
||||
drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);
|
||||
dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);
|
||||
dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);
|
||||
dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);
|
||||
drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);
|
||||
dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);
|
||||
dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);
|
||||
dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);
|
||||
}
|
||||
if (texture)
|
||||
{
|
||||
s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);
|
||||
t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);
|
||||
w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);
|
||||
dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);
|
||||
dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);
|
||||
dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);
|
||||
dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);
|
||||
dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);
|
||||
dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);
|
||||
}
|
||||
if (zbuffer)
|
||||
{
|
||||
//rglAssert(!(curRBuffer->flags & RGL_RB_DEPTH));
|
||||
|
||||
z = zbuffer_base[0];
|
||||
dzdx = zbuffer_base[1];
|
||||
dzde = zbuffer_base[2];
|
||||
}
|
||||
|
||||
xh <<= 2; xm <<= 2; xl <<= 2;
|
||||
r <<= 2; g <<= 2; b <<= 2; a <<= 2;
|
||||
dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;
|
||||
dzdx >>= 2; dzde >>= 2;
|
||||
dwdx >>= 2; dwde >>= 2;
|
||||
|
||||
|
||||
// #define tile rdpTiles[tilenum]
|
||||
// s -= (rdpTiles[tilenum].sl << 8);
|
||||
// t -= (rdpTiles[tilenum].tl << 8);
|
||||
// if (/*!tile.ms && */tile.mask_s)
|
||||
// s &= (1<<tile.mask_s+10) - 1;
|
||||
// if (/*!tile.mt && */tile.mask_t)
|
||||
// t &= (1<<tile.mask_t+10) - 1;
|
||||
// #undef tile
|
||||
|
||||
|
||||
xleft = xm;
|
||||
xright = xh;
|
||||
xleft_inc = dxmdy;
|
||||
xright_inc = dxhdy;
|
||||
|
||||
while (yh<ym &&
|
||||
!((!flip && xleft < xright+0x10000) ||
|
||||
(flip && xleft > xright-0x10000))) {
|
||||
xleft += xleft_inc; xright += xright_inc;
|
||||
s += dsde; t += dtde; w += dwde;
|
||||
r += drde; g += dgde; b += dbde; a += dade;
|
||||
z += dzde;
|
||||
yh++;
|
||||
}
|
||||
|
||||
j = ym-yh;
|
||||
//rglAssert(j >= 0);
|
||||
#undef XSCALE
|
||||
#undef YSCALE
|
||||
#undef ZSCALE
|
||||
#undef SSCALE
|
||||
#undef TSCALE
|
||||
#define XSCALE(x) (float(x)/(1<<18))
|
||||
#define YSCALE(y) (float(y)/(1<<2))
|
||||
#define ZSCALE(z) (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes)? zscale(rdpState.primitiveZ) : zscale((z)>>16))
|
||||
#define WSCALE(z) 1.0f/(RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? (float(uint32_t(z) + 0x10000)/0xffff0000) : 1.0f)
|
||||
//#define WSCALE(w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? 65536.0f*65536.0f/float((w+ 0x10000)) : 1.0f)
|
||||
#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)
|
||||
#define _PERSP(w) ( w )
|
||||
#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )
|
||||
#define SSCALE(s, _w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))
|
||||
#define TSCALE(s, w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))
|
||||
|
||||
rglStrip_t * strip = strips + nbStrips++;
|
||||
rglAssert(nbStrips < MAX_STRIPS);
|
||||
curChunk->nbStrips++;
|
||||
rglVertex_t * vtx = vtxs + nbVtxs;
|
||||
|
||||
strip->flags = (shade? RGL_STRIP_SHADE : 0) | t1 | t2
|
||||
| RGL_STRIP_ZBUFFER;
|
||||
//| (zbuffer? RGL_STRIP_ZBUFFER : 0);
|
||||
strip->vtxs = vtx;
|
||||
strip->tilenum = tilenum;
|
||||
|
||||
//int sw;
|
||||
if (j > 0)
|
||||
{
|
||||
int dx = ((xleft-xright)>>16);
|
||||
if ((!flip && xleft < xright) ||
|
||||
(flip/* && xleft > xright*/))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r+drdx*dx);
|
||||
vtx->g = CSCALE(g+dgdx*dx);
|
||||
vtx->b = CSCALE(b+dbdx*dx);
|
||||
vtx->a = CSCALE(a+dadx*dx);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
||||
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
||||
}
|
||||
vtx->x = XSCALE(xleft);
|
||||
vtx->y = YSCALE(yh);
|
||||
vtx->z = ZSCALE(z+dzdx*dx);
|
||||
vtx->w = WSCALE(w+dwdx*dx);
|
||||
vtx++;
|
||||
}
|
||||
if ((!flip/* && xleft < xright*/) ||
|
||||
(flip && xleft > xright))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r);
|
||||
vtx->g = CSCALE(g);
|
||||
vtx->b = CSCALE(b);
|
||||
vtx->a = CSCALE(a);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s, w);
|
||||
vtx->t = TSCALE(t, w);
|
||||
}
|
||||
vtx->x = XSCALE(xright);
|
||||
vtx->y = YSCALE(yh);
|
||||
vtx->z = ZSCALE(z);
|
||||
vtx->w = WSCALE(w);
|
||||
vtx++;
|
||||
}
|
||||
}
|
||||
xleft += xleft_inc*j; xright += xright_inc*j;
|
||||
s += dsde*j; t += dtde*j; w += dwde*j;
|
||||
r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
|
||||
z += dzde*j;
|
||||
// render ...
|
||||
|
||||
xleft = xl;
|
||||
|
||||
//if (yl-ym > 0)
|
||||
{
|
||||
int dx = ((xleft-xright)>>16);
|
||||
if ((!flip && xleft <= xright) ||
|
||||
(flip/* && xleft >= xright*/))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r+drdx*dx);
|
||||
vtx->g = CSCALE(g+dgdx*dx);
|
||||
vtx->b = CSCALE(b+dbdx*dx);
|
||||
vtx->a = CSCALE(a+dadx*dx);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
||||
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
||||
}
|
||||
vtx->x = XSCALE(xleft);
|
||||
vtx->y = YSCALE(ym);
|
||||
vtx->z = ZSCALE(z+dzdx*dx);
|
||||
vtx->w = WSCALE(w+dwdx*dx);
|
||||
vtx++;
|
||||
}
|
||||
if ((!flip/* && xleft <= xright*/) ||
|
||||
(flip && xleft >= xright))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r);
|
||||
vtx->g = CSCALE(g);
|
||||
vtx->b = CSCALE(b);
|
||||
vtx->a = CSCALE(a);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s, w);
|
||||
vtx->t = TSCALE(t, w);
|
||||
}
|
||||
vtx->x = XSCALE(xright);
|
||||
vtx->y = YSCALE(ym);
|
||||
vtx->z = ZSCALE(z);
|
||||
vtx->w = WSCALE(w);
|
||||
vtx++;
|
||||
}
|
||||
}
|
||||
xleft_inc = dxldy;
|
||||
xright_inc = dxhdy;
|
||||
|
||||
j = yl-ym;
|
||||
//rglAssert(j >= 0);
|
||||
//j--; // ?
|
||||
xleft += xleft_inc*j; xright += xright_inc*j;
|
||||
s += dsde*j; t += dtde*j; w += dwde*j;
|
||||
r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
|
||||
z += dzde*j;
|
||||
|
||||
while (yl>ym &&
|
||||
!((!flip && xleft < xright+0x10000) ||
|
||||
(flip && xleft > xright-0x10000))) {
|
||||
xleft -= xleft_inc; xright -= xright_inc;
|
||||
s -= dsde; t -= dtde; w -= dwde;
|
||||
r -= drde; g -= dgde; b -= dbde; a -= dade;
|
||||
z -= dzde;
|
||||
j--;
|
||||
yl--;
|
||||
}
|
||||
|
||||
// render ...
|
||||
if (j >= 0) {
|
||||
int dx = ((xleft-xright)>>16);
|
||||
if ((!flip && xleft <= xright) ||
|
||||
(flip/* && xleft >= xright*/))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r+drdx*dx);
|
||||
vtx->g = CSCALE(g+dgdx*dx);
|
||||
vtx->b = CSCALE(b+dbdx*dx);
|
||||
vtx->a = CSCALE(a+dadx*dx);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
||||
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
||||
}
|
||||
vtx->x = XSCALE(xleft);
|
||||
vtx->y = YSCALE(yl);
|
||||
vtx->z = ZSCALE(z+dzdx*dx);
|
||||
vtx->w = WSCALE(w+dwdx*dx);
|
||||
vtx++;
|
||||
}
|
||||
if ((!flip/* && xleft <= xright*/) ||
|
||||
(flip && xleft >= xright))
|
||||
{
|
||||
if (shade) {
|
||||
vtx->r = CSCALE(r);
|
||||
vtx->g = CSCALE(g);
|
||||
vtx->b = CSCALE(b);
|
||||
vtx->a = CSCALE(a);
|
||||
}
|
||||
if (texture) {
|
||||
vtx->s = SSCALE(s, w);
|
||||
vtx->t = TSCALE(t, w);
|
||||
}
|
||||
vtx->x = XSCALE(xright);
|
||||
vtx->y = YSCALE(yl);
|
||||
vtx->z = ZSCALE(z);
|
||||
vtx->w = WSCALE(w);
|
||||
vtx++;
|
||||
}
|
||||
}
|
||||
|
||||
strip->nbVtxs = vtx - strip->vtxs;
|
||||
nbVtxs = vtx - vtxs;
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "rgl_glut.h"
|
||||
|
||||
#ifdef RGL_USE_GLUT
|
||||
#include <GL/glui.h>
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
/** These are the live variables passed into GLUI ***/
|
||||
int wireframe = 0;
|
||||
int segments = 8;
|
||||
int main_window;
|
||||
|
||||
static GLUI *glui;
|
||||
|
||||
static SDL_sem * commandSem;
|
||||
static SDL_cond * commandCond;
|
||||
static SDL_mutex * commandMutex;
|
||||
static SDL_sem * commandFinishedSem;
|
||||
static rglGlutCommand_f command, nextCommand;
|
||||
|
||||
/***************************************** myGlutIdle() ***********/
|
||||
|
||||
void myGlutIdle( )
|
||||
{
|
||||
// SDL_LockMutex(commandMutex);
|
||||
// if (!SDL_CondWaitTimeout(commandCond, commandMutex, 1)) {
|
||||
if (!SDL_SemWaitTimeout(commandSem, 1)) {
|
||||
//if (!SDL_SemWait(commandSem)) {
|
||||
//printf("receive a command\n");
|
||||
if ( glutGetWindow() && glutGetWindow() != main_window )
|
||||
glutSetWindow(main_window);
|
||||
nextCommand = command;
|
||||
command = 0;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
// SDL_UnlockMutex(commandMutex);
|
||||
}
|
||||
|
||||
void myGlutTimer( int dummy )
|
||||
{
|
||||
|
||||
/* According to the GLUT specification, the current window is
|
||||
undefined during an idle callback. So we need to explicitly change
|
||||
it if necessary */
|
||||
if ( glutGetWindow() != main_window )
|
||||
glutSetWindow(main_window);
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
/**************************************** myGlutReshape() *************/
|
||||
|
||||
void myGlutReshape( int x, int y )
|
||||
{
|
||||
float xy_aspect;
|
||||
|
||||
xy_aspect = (float)x / (float)y;
|
||||
glViewport( 0, 0, x, y );
|
||||
|
||||
// glMatrixMode( GL_PROJECTION );
|
||||
// glLoadIdentity();
|
||||
// glFrustum( -xy_aspect*.08, xy_aspect*.08, -.08, .08, .1, 15.0 );
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
/***************************************** myGlutDisplay() *****************/
|
||||
|
||||
void myGlutDisplay( void )
|
||||
{
|
||||
if (nextCommand) {
|
||||
nextCommand();
|
||||
nextCommand = 0;
|
||||
SDL_SemPost(commandFinishedSem);
|
||||
}
|
||||
|
||||
//glutSwapBuffers();
|
||||
|
||||
//glutTimerFunc(1, myGlutTimer, 0);
|
||||
}
|
||||
|
||||
|
||||
/**************************************** main() ********************/
|
||||
|
||||
static int glutmain(int argc, char* argv[])
|
||||
{
|
||||
/****************************************/
|
||||
/* Initialize GLUT and create window */
|
||||
/****************************************/
|
||||
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
|
||||
//glutInitWindowPosition( 50, 50 );
|
||||
glutInitWindowSize( screen_width, screen_height );
|
||||
|
||||
main_window = glutCreateWindow( "z64gl" );
|
||||
glutDisplayFunc( myGlutDisplay );
|
||||
glutReshapeFunc( myGlutReshape );
|
||||
|
||||
/****************************************/
|
||||
/* Here's the GLUI code */
|
||||
/****************************************/
|
||||
|
||||
glui = GLUI_Master.create_glui( "GLUI" );
|
||||
new GLUI_Checkbox( glui, "Wireframe", &wireframe );
|
||||
(new GLUI_Spinner( glui, "Segments:", &segments ))
|
||||
->set_int_limits( 3, 60 );
|
||||
|
||||
glui->set_main_gfx_window( main_window );
|
||||
|
||||
/* We register the idle callback with GLUI, *not* with GLUT */
|
||||
GLUI_Master.set_glutIdleFunc( myGlutIdle );
|
||||
//glutTimerFunc(1, myGlutTimer, 0);
|
||||
|
||||
glutMainLoop();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static SDL_Thread * thread;
|
||||
|
||||
int rglGlutThread(void * dummy)
|
||||
{
|
||||
int argc = 1;
|
||||
char * argv[2] = { "z64gl", 0 };
|
||||
|
||||
glutmain(argc, argv);
|
||||
|
||||
thread = 0;
|
||||
|
||||
// in case of, but glutMainLoop never exits anyway
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void rglGlutMinimizeWindow()
|
||||
{
|
||||
//glutDestroyWindow(main_window);
|
||||
myGlutReshape(64, 64);
|
||||
}
|
||||
|
||||
void rglGlutRecreateWindow()
|
||||
{
|
||||
int oldmain = main_window;
|
||||
|
||||
glutInitWindowSize( screen_width, screen_height );
|
||||
main_window = glutCreateWindow( "z64gl" );
|
||||
glutDisplayFunc( myGlutDisplay );
|
||||
glutReshapeFunc( myGlutReshape );
|
||||
|
||||
glui->set_main_gfx_window( main_window );
|
||||
/* We register the idle callback with GLUI, *not* with GLUT */
|
||||
GLUI_Master.set_glutIdleFunc( myGlutIdle );
|
||||
//glutTimerFunc(1, myGlutTimer, 0);
|
||||
|
||||
glutSetWindow(main_window);
|
||||
|
||||
glutDestroyWindow(oldmain);
|
||||
}
|
||||
|
||||
void rglGlutCreateThread(int recreate)
|
||||
{
|
||||
if (!thread) {
|
||||
commandSem = SDL_CreateSemaphore(0);
|
||||
commandCond = SDL_CreateCond();
|
||||
commandMutex = SDL_CreateMutex();
|
||||
commandFinishedSem = SDL_CreateSemaphore(0);
|
||||
|
||||
thread = SDL_CreateThread(rglGlutThread, 0);
|
||||
} else if (recreate)
|
||||
rglGlutPostCommand(rglGlutRecreateWindow);
|
||||
}
|
||||
|
||||
void rglGlutPostCommand(rglGlutCommand_f c)
|
||||
{
|
||||
command = c;
|
||||
SDL_SemPost(commandSem);
|
||||
// SDL_LockMutex(commandMutex);
|
||||
// SDL_CondSignal(commandCond);
|
||||
// SDL_UnlockMutex(commandMutex);
|
||||
SDL_SemWait(commandFinishedSem);
|
||||
}
|
||||
|
||||
void rglSwapBuffers()
|
||||
{
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
typedef void (* rglGlutCommand_f)();
|
||||
|
||||
void rglGlutCreateThread(int recreatewindows);
|
||||
|
||||
void rglGlutPostCommand(rglGlutCommand_f c);
|
||||
|
||||
void rglSwapBuffers();
|
||||
|
||||
void rglGlutMinimizeWindow();
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
SDL_Surface *sdl_Screen;
|
||||
int viewportOffset;
|
||||
|
||||
/* definitions of pointers to Core video extension functions */
|
||||
extern ptr_VidExt_Init CoreVideo_Init;
|
||||
extern ptr_VidExt_Quit CoreVideo_Quit;
|
||||
extern ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes;
|
||||
extern ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode;
|
||||
extern ptr_VidExt_SetCaption CoreVideo_SetCaption;
|
||||
extern ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen;
|
||||
extern ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow;
|
||||
extern ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress;
|
||||
extern ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute;
|
||||
extern ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers;
|
||||
|
||||
//int screen_width = 640, screen_height = 480;
|
||||
int screen_width = 1024, screen_height = 768;
|
||||
//int screen_width = 320, screen_height = 240;
|
||||
|
||||
int viewport_offset;
|
||||
|
||||
void rglSwapBuffers()
|
||||
{
|
||||
//TODO: if screenshot capabilities are ever implemented, replace the
|
||||
//hard-coded 1 with a value indicating whether the screen has been redrawn
|
||||
if (render_callback != NULL)
|
||||
render_callback(1);
|
||||
CoreVideo_GL_SwapBuffers();
|
||||
return;
|
||||
}
|
||||
|
||||
int rglOpenScreen()
|
||||
{
|
||||
if (CoreVideo_Init() != M64ERR_SUCCESS) {
|
||||
rdp_log(M64MSG_ERROR, "Could not initialize video.");
|
||||
return 0;
|
||||
}
|
||||
if (rglStatus == RGL_STATUS_WINDOWED) {
|
||||
screen_width = rglSettings.resX;
|
||||
screen_height = rglSettings.resY;
|
||||
} else {
|
||||
screen_width = rglSettings.fsResX;
|
||||
screen_height = rglSettings.fsResY;
|
||||
}
|
||||
|
||||
m64p_video_mode screen_mode = M64VIDEO_WINDOWED;
|
||||
if (rglSettings.fullscreen)
|
||||
screen_mode = M64VIDEO_FULLSCREEN;
|
||||
|
||||
viewportOffset = 0;
|
||||
|
||||
if (CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1) != M64ERR_SUCCESS ||
|
||||
CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 32) != M64ERR_SUCCESS ||
|
||||
CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 24) != M64ERR_SUCCESS)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Could not set video attributes.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CoreVideo_SetVideoMode(screen_width, screen_height, 32, screen_mode, (m64p_video_flags) 0) != M64ERR_SUCCESS)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Could not set video mode.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
CoreVideo_SetCaption("Z64gl");
|
||||
|
||||
rdp_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rglCloseScreen()
|
||||
{
|
||||
rglClose();
|
||||
CoreVideo_Quit();
|
||||
}
|
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
void rglRenderMode(rglRenderChunk_t & chunk)
|
||||
{
|
||||
//int i;
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
if (RDP_GETOM_CYCLE_TYPE(chunk.rdpState.otherModes) < 2) {
|
||||
glDepthMask(RDP_GETOM_Z_UPDATE_EN(chunk.rdpState.otherModes)? GL_TRUE:GL_FALSE);
|
||||
if (RDP_GETOM_Z_COMPARE_EN(chunk.rdpState.otherModes))
|
||||
glDepthFunc(GL_LESS);
|
||||
else
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
}
|
||||
|
||||
|
||||
// if (RDP_GETOM_Z_MODE(chunk.rdpState.otherModes) & 1) {
|
||||
// glEnable( GL_POLYGON_OFFSET_FILL );
|
||||
// switch(RDP_GETOM_Z_MODE(chunk.rdpState.otherModes)) {
|
||||
// case 3:
|
||||
// glPolygonOffset( -3, -300 );
|
||||
// break;
|
||||
// default:
|
||||
// // FIXME tune this value
|
||||
// //glPolygonOffset( -3.0f, -3.0f );
|
||||
// glPolygonOffset( -3, -40 );
|
||||
// break;
|
||||
// }
|
||||
// //glDepthMask(GL_FALSE);
|
||||
// } else {
|
||||
// glDisable( GL_POLYGON_OFFSET_FILL );
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct rglCombiner_t {
|
||||
rdpCombineModes_t combineModes;
|
||||
rdpOtherModes_t otherModes;
|
||||
rglShader_t * shader;
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
GLuint srcBlend, dstBlend;
|
||||
#endif
|
||||
int format;
|
||||
};
|
||||
#define RGL_MAX_COMBINERS 128
|
||||
static int rglNbCombiners;
|
||||
static rglCombiner_t rglCombiners[RGL_MAX_COMBINERS];
|
||||
|
||||
void rglClearCombiners()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<rglNbCombiners; i++)
|
||||
rglDeleteShader(rglCombiners[i].shader);
|
||||
rglNbCombiners = 0;
|
||||
}
|
||||
|
||||
|
||||
int rglT1Usage(rdpState_t & state)
|
||||
{
|
||||
//return 1;
|
||||
int cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
||||
if (cycle == RDP_CYCLE_TYPE_COPY) return 1;
|
||||
if (cycle >= 2) return 0;
|
||||
if (cycle == 1 && (
|
||||
RDP_GETCM_SUB_A_RGB1(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_B_RGB1(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_RGB1(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_RGB1(state.combineModes)==9 ||
|
||||
RDP_GETCM_ADD_RGB1(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_A_A1(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_B_A1(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_A1(state.combineModes)==2 ||
|
||||
RDP_GETCM_ADD_A1(state.combineModes)==2))
|
||||
return 1;
|
||||
if (
|
||||
(RDP_GETOM_CVG_TIMES_ALPHA(state.otherModes) &&
|
||||
!RDP_GETOM_ALPHA_CVG_SELECT(state.otherModes)) ||
|
||||
|
||||
RDP_GETCM_SUB_A_RGB0(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_B_RGB0(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_RGB0(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_RGB0(state.combineModes)==8 ||
|
||||
RDP_GETCM_ADD_RGB0(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_A_A0(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_B_A0(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_A0(state.combineModes)==1 ||
|
||||
RDP_GETCM_ADD_A0(state.combineModes)==1)
|
||||
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int rglT2Usage(rdpState_t & state)
|
||||
{
|
||||
//return 1;
|
||||
int cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
||||
if (cycle >= 2) return 0;
|
||||
if (cycle == 1 && (
|
||||
RDP_GETCM_SUB_A_RGB1(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_B_RGB1(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_RGB1(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_RGB1(state.combineModes)==8 ||
|
||||
RDP_GETCM_ADD_RGB1(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_A_A1(state.combineModes)==1 ||
|
||||
RDP_GETCM_SUB_B_A1(state.combineModes)==1 ||
|
||||
RDP_GETCM_MUL_A1(state.combineModes)==1 ||
|
||||
RDP_GETCM_ADD_A1(state.combineModes)==1))
|
||||
return 1;
|
||||
|
||||
if (
|
||||
RDP_GETCM_SUB_A_RGB0(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_B_RGB0(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_RGB0(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_RGB0(state.combineModes)==9 ||
|
||||
RDP_GETCM_ADD_RGB0(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_A_A0(state.combineModes)==2 ||
|
||||
RDP_GETCM_SUB_B_A0(state.combineModes)==2 ||
|
||||
RDP_GETCM_MUL_A0(state.combineModes)==2 ||
|
||||
RDP_GETCM_ADD_A0(state.combineModes)==2)
|
||||
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void rglSetCombiner(rglRenderChunk_t & chunk, int format)
|
||||
{
|
||||
static char _1ma[64];
|
||||
static char t1[64];
|
||||
static char t1a[64];
|
||||
static char t2[64];
|
||||
static char t2a[64];
|
||||
static char prim_lod_frac[64];
|
||||
|
||||
static const char *saRGB[] = {
|
||||
"c", t1, t2, "p/*PRIM*/",
|
||||
"gl_Color", "e", "1.0/*NOISE*/", "1.0",
|
||||
"0.0", "0.0", "0.0", "0.0",
|
||||
"0.0", "0.0", "0.0", "0.0"
|
||||
};
|
||||
|
||||
static const char *mRGB[] = {
|
||||
"c", t1, t2, "p/*PRIM*/",
|
||||
"gl_Color/*SHADE*/","e", "0.0/*SCALE*/", "c.a/*COMBINED_A*/",
|
||||
"t1.a/*TEXEL0_A*/", "t2.a/*TEXEL1_A*/", "p.a/*PRIM_A*/", "gl_Color.a/*SHADEA*/",
|
||||
"e.a/*ENV_ALPHA*/", "0.5/*LOD_FRACTION*/","0.5/*PRIM_LOD_FRAC*/","k5/*K5*/",
|
||||
"0.0", "0.0", "0.0", "0.0",
|
||||
"0.0", "0.0", "0.0", "0.0",
|
||||
"0.0", "0.0", "0.0", "0.0",
|
||||
"0.0", "0.0", "0.0", "0.0"
|
||||
};
|
||||
|
||||
static const char *aRGB[] = {
|
||||
"c", t1, t2, "p/*PRIM*/",
|
||||
"gl_Color/*SHADE*/","e/*ENV*/", "1.0", "0.0",
|
||||
};
|
||||
|
||||
static const char *saA[] = {
|
||||
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
||||
"gl_Color.a", "e.a", "1.0", "0.0",
|
||||
};
|
||||
|
||||
static const char *sbA[] = {
|
||||
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
||||
"gl_Color.a", "e.a", "1.0", "0.0",
|
||||
};
|
||||
|
||||
static const char *mA[] = {
|
||||
"0.5/*LOD_FRACTION*/", t1a, t2a, "p.a/*PRIM*/",
|
||||
"gl_Color.a/*SHADE*/", "e.a", prim_lod_frac, "0.0",
|
||||
};
|
||||
|
||||
static const char *aA[] = {
|
||||
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
||||
"gl_Color.a/*SHADE*/", "e.a", "1.0", "0.0",
|
||||
};
|
||||
|
||||
const static char * bRGB[] =
|
||||
{ "c/*PREV*/", "f", "b", "fog/*FOG*/" };
|
||||
const static char * bA[2][4] =
|
||||
{ {"c.a/*PREVA*/", "fog.a/*FOGA*/", "gl_Color.a/*SHADEA*/", "0.0/*ZERO*/"},
|
||||
{_1ma/*"(1.0-c.a/ *PREVA)"*/, "0.0/*f.a*//*FRAGA*/", "1.0", "0.0"}}; // need clamping on 1-alpha ?
|
||||
|
||||
|
||||
rdpState_t & state = chunk.rdpState;
|
||||
static rglCombiner_t * c;
|
||||
uint32_t cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
||||
int i; //, fmt, size;
|
||||
char * p;
|
||||
const char * alphaTest;
|
||||
const char * alphaTest2;
|
||||
const char * write;
|
||||
static char src[4*4096];
|
||||
|
||||
float env[4];
|
||||
env[0] = RDP_GETC32_R(state.envColor)/255.0f;
|
||||
env[1] = RDP_GETC32_G(state.envColor)/255.0f;
|
||||
env[2] = RDP_GETC32_B(state.envColor)/255.0f;
|
||||
env[3] = RDP_GETC32_A(state.envColor)/255.0f;
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env);
|
||||
|
||||
env[0] = RDP_GETC32_R(state.blendColor)/255.0f;
|
||||
env[1] = RDP_GETC32_G(state.blendColor)/255.0f;
|
||||
env[2] = RDP_GETC32_B(state.blendColor)/255.0f;
|
||||
env[3] = RDP_GETC32_A(state.blendColor)/255.0f;
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, env);
|
||||
|
||||
env[0] = RDP_GETC32_R(state.fogColor)/255.0f;
|
||||
env[1] = RDP_GETC32_G(state.fogColor)/255.0f;
|
||||
env[2] = RDP_GETC32_B(state.fogColor)/255.0f;
|
||||
env[3] = RDP_GETC32_A(state.fogColor)/255.0f;
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, env);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
env[0] = state.k5/255.0f;
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env);
|
||||
if (cycle == RDP_CYCLE_TYPE_FILL) {
|
||||
if (0/*fb_size == 3*/) { // FIXME
|
||||
env[0] = RDP_GETC32_R(state.fillColor)/255.0f;
|
||||
env[1] = RDP_GETC32_G(state.fillColor)/255.0f;
|
||||
env[2] = RDP_GETC32_B(state.fillColor)/255.0f;
|
||||
env[3] = RDP_GETC32_A(state.fillColor)/255.0f;
|
||||
} else {
|
||||
env[0] = RDP_GETC16_R(state.fillColor)/31.0f;
|
||||
env[1] = RDP_GETC16_G(state.fillColor)/31.0f;
|
||||
env[2] = RDP_GETC16_B(state.fillColor)/31.0f;
|
||||
env[3] = RDP_GETC16_A(state.fillColor);
|
||||
}
|
||||
} else {
|
||||
env[0] = RDP_GETC32_R(state.primColor)/255.0f;
|
||||
env[1] = RDP_GETC32_G(state.primColor)/255.0f;
|
||||
env[2] = RDP_GETC32_B(state.primColor)/255.0f;
|
||||
env[3] = RDP_GETC32_A(state.primColor)/255.0f;
|
||||
}
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, env);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
// if (c && rglNbCombiners &&
|
||||
// RDP_GETOM_CYCLE_TYPE(c->otherModes) == cycle &&
|
||||
// (RDP_GETOM_CYCLE_TYPE(c->otherModes) >= 2 ||
|
||||
// (!memcmp(&c->combineModes, &state.combineModes, sizeof(rdpCombineModes_t)) &&
|
||||
// !memcmp(&c->otherModes, &state.otherModes, sizeof(rdpOtherModes_t))))) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
for (i=0; i<rglNbCombiners; i++) {
|
||||
c = rglCombiners + i;
|
||||
if (c->format == format &&
|
||||
RDP_GETOM_CYCLE_TYPE(c->otherModes) == cycle &&
|
||||
(RDP_GETOM_CYCLE_TYPE(c->otherModes) >= 2 ||
|
||||
(!memcmp(&c->combineModes, &state.combineModes, sizeof(rdpCombineModes_t))
|
||||
&& !memcmp(&c->otherModes, &state.otherModes, sizeof(rdpOtherModes_t))
|
||||
))) {
|
||||
#ifdef RDP_DEBUG
|
||||
chunk.shader = c->shader;
|
||||
#endif
|
||||
rglUseShader(c->shader);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (rglNbCombiners == RGL_MAX_COMBINERS)
|
||||
rglClearCombiners();
|
||||
|
||||
c = rglCombiners + rglNbCombiners++;
|
||||
c->otherModes = state.otherModes;
|
||||
c->combineModes = state.combineModes;
|
||||
c->format = format;
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
c->srcBlend = GL_ONE;
|
||||
c->dstBlend = GL_ZERO;
|
||||
#endif
|
||||
|
||||
switch (format & RGL_COMB_FMT) {
|
||||
case RGL_COMB_FMT_RGBA:
|
||||
write = "gl_FragColor = c;";
|
||||
break;
|
||||
case RGL_COMB_FMT_I:
|
||||
write = "gl_FragColor = vec4(c[0]);";
|
||||
break;
|
||||
case RGL_COMB_FMT_DEPTH:
|
||||
write = "gl_FragDepth = c[0];";
|
||||
break;
|
||||
}
|
||||
|
||||
if (cycle == RDP_CYCLE_TYPE_FILL) {
|
||||
sprintf(
|
||||
src,
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
//" c = gl_TextureEnvColor[1];\n"
|
||||
" vec4 c = gl_LightSource[0].specular;\n"
|
||||
" %s\n"
|
||||
"} \n",
|
||||
write);
|
||||
c->shader = rglCreateShader(
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_FrontColor = gl_Color; \n"
|
||||
" gl_BackColor = gl_Color; \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
"} \n"
|
||||
,
|
||||
src
|
||||
);
|
||||
#ifdef RDP_DEBUG
|
||||
chunk.shader = c->shader;
|
||||
#endif
|
||||
rglUseShader(c->shader);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
alphaTest = "";
|
||||
alphaTest2 = "";
|
||||
|
||||
if (//cycle < 2 && // CHECK THIS
|
||||
RDP_GETOM_CVG_TIMES_ALPHA(chunk.rdpState.otherModes)
|
||||
//&& rglT1Usage(chunk.rdpState)
|
||||
) {
|
||||
if (RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes))
|
||||
alphaTest = "if (c.a < 0.5) discard; \n";
|
||||
else
|
||||
alphaTest = "if (t1.a < 0.5) discard; \n";
|
||||
alphaTest2 = "if (c.a < 0.5) discard; \n";
|
||||
}
|
||||
else if (RDP_GETOM_ALPHA_COMPARE_EN(chunk.rdpState.otherModes) &&
|
||||
!RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes)) {
|
||||
if (RDP_GETC32_A(chunk.rdpState.blendColor) > 0) {
|
||||
alphaTest = "if (c.a < b.a) discard; \n";
|
||||
alphaTest2 =
|
||||
" vec4 b = gl_LightSource[0].ambient; \n"
|
||||
" if (c.a < b.a) discard; \n";
|
||||
//alphaTest2 = "if (c.a < 0.5) discard; \n";
|
||||
} else {
|
||||
alphaTest = "if (c.a == 0.0) discard; \n";
|
||||
alphaTest2 = "if (c.a == 0.0) discard; \n";
|
||||
}
|
||||
}
|
||||
|
||||
if (cycle == RDP_CYCLE_TYPE_COPY) {
|
||||
sprintf(
|
||||
src,
|
||||
"uniform sampler2D texture0; \n"
|
||||
" \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" vec4 c = texture2D(texture0, vec2(gl_TexCoord[0])); \n"
|
||||
" %s"
|
||||
" %s\n"
|
||||
"} \n",
|
||||
alphaTest2,
|
||||
write
|
||||
);
|
||||
c->shader = rglCreateShader(
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_FrontColor = gl_Color; \n"
|
||||
" gl_BackColor = gl_Color; \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
"} \n"
|
||||
,
|
||||
src
|
||||
);
|
||||
#ifdef RDP_DEBUG
|
||||
chunk.shader = c->shader;
|
||||
#endif
|
||||
rglUseShader(c->shader);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
|
||||
p = src;
|
||||
p +=
|
||||
sprintf(p,
|
||||
"uniform sampler2D texture0; \n"
|
||||
"uniform sampler2D texture2; \n"
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
"uniform sampler2D texture1; \n"
|
||||
#endif
|
||||
" \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
"vec4 c = vec4(0,0,0,0);\n"
|
||||
"vec4 e = gl_TextureEnvColor[0];\n"
|
||||
"float k5 = gl_TextureEnvColor[1][0];\n"
|
||||
"vec4 p = gl_LightSource[0].specular;\n"
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
"vec4 f = texture2D(texture1, vec2(gl_FragCoord.x/(2048.0*gl_TexCoord[1].x), gl_FragCoord.y/(2048.0*gl_TexCoord[1].y))); \n"
|
||||
#endif
|
||||
"vec4 fog = gl_LightSource[0].diffuse; \n"
|
||||
"vec4 b = gl_LightSource[0].ambient; \n");
|
||||
|
||||
switch (format & RGL_COMB_IN0) {
|
||||
case 0:
|
||||
p +=
|
||||
sprintf(p,
|
||||
"vec4 t1 = texture2D(texture0, vec2(gl_TexCoord[0]));\n");
|
||||
break;
|
||||
case RGL_COMB_IN0_DEPTH:
|
||||
p +=
|
||||
sprintf(p,
|
||||
"vec4 t1 = vec4(texture2D(texture0, vec2(gl_TexCoord[0]))[0]);\n");
|
||||
break;
|
||||
}
|
||||
switch (format & RGL_COMB_IN1) {
|
||||
case 0:
|
||||
p +=
|
||||
sprintf(p,
|
||||
"vec4 t2 = texture2D(texture2, vec2(gl_TexCoord[2]));\n");
|
||||
break;
|
||||
case RGL_COMB_IN1_DEPTH:
|
||||
p +=
|
||||
sprintf(p,
|
||||
"vec4 t2 = vec4(texture2D(texture2, vec2(gl_TexCoord[2]))[0]);\n");
|
||||
break;
|
||||
}
|
||||
|
||||
const char * comb, * comb2;
|
||||
comb2 = 0;
|
||||
// switch (RDP_GETOM_CVG_DEST(state.otherModes))
|
||||
// {
|
||||
// case 3:
|
||||
// comb = "c = clamp(vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s), 0.0, 1.0);\n";
|
||||
// break;
|
||||
// case 2:
|
||||
// comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s);\n";
|
||||
// //comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), t1.a*((%s - %s) * %s + %s));\n";
|
||||
// break;
|
||||
// case 0:
|
||||
// //comb2 = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), t1.a);\n";
|
||||
// case 1:
|
||||
// comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s);\n";
|
||||
// break;
|
||||
// }
|
||||
comb = "c = clamp(vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s), 0.0, 1.0);\n";
|
||||
strcpy(prim_lod_frac, "0.5/*PRIM_LOD_FRAC*/");
|
||||
strcpy(t1, "t1");
|
||||
strcpy(t1a, "t1.a");
|
||||
if (format & RGL_COMB_TILE7) {
|
||||
strcpy(t2, "t1");
|
||||
strcpy(t2a, "t1.a");
|
||||
} else {
|
||||
strcpy(t2, "t2");
|
||||
strcpy(t2a, "t2.a");
|
||||
}
|
||||
p +=
|
||||
sprintf(p,
|
||||
comb
|
||||
,
|
||||
saRGB[RDP_GETCM_SUB_A_RGB0(state.combineModes)],
|
||||
saRGB[RDP_GETCM_SUB_B_RGB0(state.combineModes)],
|
||||
mRGB[RDP_GETCM_MUL_RGB0(state.combineModes)],
|
||||
aRGB[RDP_GETCM_ADD_RGB0(state.combineModes)],
|
||||
saA[RDP_GETCM_SUB_A_A0(state.combineModes)],
|
||||
sbA[RDP_GETCM_SUB_B_A0(state.combineModes)],
|
||||
mA[RDP_GETCM_MUL_A0(state.combineModes)],
|
||||
aA[RDP_GETCM_ADD_A0(state.combineModes)]
|
||||
);
|
||||
|
||||
if (cycle == RDP_CYCLE_TYPE_2) {
|
||||
if (!(format & RGL_COMB_TILE7)) {
|
||||
strcpy(t1, "t2");
|
||||
strcpy(t1a, "t2.a");
|
||||
strcpy(t2, "t1");
|
||||
strcpy(t2a, "t1.a");
|
||||
}
|
||||
//strcpy(prim_lod_frac, "0.0/*PRIM_LOD_FRAC*/");
|
||||
// if (!RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes))
|
||||
// p +=
|
||||
// sprintf(p, " c.a = t1.a; \n");
|
||||
|
||||
p +=
|
||||
sprintf(p,
|
||||
comb2? comb2 : comb
|
||||
,
|
||||
saRGB[RDP_GETCM_SUB_A_RGB1(state.combineModes)],
|
||||
saRGB[RDP_GETCM_SUB_B_RGB1(state.combineModes)],
|
||||
mRGB[RDP_GETCM_MUL_RGB1(state.combineModes)],
|
||||
aRGB[RDP_GETCM_ADD_RGB1(state.combineModes)],
|
||||
saA[RDP_GETCM_SUB_A_A1(state.combineModes)],
|
||||
sbA[RDP_GETCM_SUB_B_A1(state.combineModes)],
|
||||
mA[RDP_GETCM_MUL_A1(state.combineModes)],
|
||||
aA[RDP_GETCM_ADD_A1(state.combineModes)]
|
||||
);
|
||||
}
|
||||
|
||||
// if (!RDP_GETOM_CVG_TIMES_ALPHA(state.otherModes))
|
||||
// p += sprintf(p, "c.a = t1.a; \n");
|
||||
|
||||
p += sprintf(p, "%s", alphaTest);
|
||||
|
||||
|
||||
const char * blender;
|
||||
blender = "c = vec4(float(%s)*vec3(%s) + float(%s)*vec3(%s), 1.0); \n";
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
const char * noblender = "c.a = 1.0;\n";
|
||||
#endif
|
||||
|
||||
int m1b, m1a, m2b, m2a;
|
||||
|
||||
//LOG("New combiner / blender :\n%s", rglCombiner2String(state));
|
||||
|
||||
if (cycle == RDP_CYCLE_TYPE_2) {
|
||||
if (RDP_GETOM_FORCE_BLEND(state.otherModes)) {
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
if (RDP_GETOM_BLEND_M1A_0(state.otherModes) != 1 &&
|
||||
RDP_GETOM_BLEND_M2A_0(state.otherModes) != 1) {
|
||||
#endif
|
||||
sprintf(_1ma, "(1.0 - %s)", bA[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)]);
|
||||
p +=
|
||||
sprintf(
|
||||
p,
|
||||
"c = vec4(float(%s)*vec3(%s) + float(%s)*vec3(%s), c.a); \n"
|
||||
,bA[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)],
|
||||
bRGB[RDP_GETOM_BLEND_M1A_0(state.otherModes)],
|
||||
bA[1][RDP_GETOM_BLEND_M2B_0(state.otherModes)],
|
||||
bRGB[RDP_GETOM_BLEND_M2A_0(state.otherModes)]
|
||||
);
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
} else {
|
||||
LOG("Blender error : fragment in cycle 1\n%s", rglCombiner2String(state));
|
||||
}
|
||||
#endif
|
||||
|
||||
m1b = RDP_GETOM_BLEND_M1B_1(state.otherModes);
|
||||
m1a = RDP_GETOM_BLEND_M1A_1(state.otherModes);
|
||||
m2b = RDP_GETOM_BLEND_M2B_1(state.otherModes);
|
||||
m2a = RDP_GETOM_BLEND_M2A_1(state.otherModes);
|
||||
} else {
|
||||
m1b = RDP_GETOM_BLEND_M1B_0(state.otherModes);
|
||||
m1a = RDP_GETOM_BLEND_M1A_0(state.otherModes);
|
||||
m2b = RDP_GETOM_BLEND_M2B_0(state.otherModes);
|
||||
m2a = RDP_GETOM_BLEND_M2A_0(state.otherModes);
|
||||
}
|
||||
} else {
|
||||
m1b = RDP_GETOM_BLEND_M1B_0(state.otherModes);
|
||||
m1a = RDP_GETOM_BLEND_M1A_0(state.otherModes);
|
||||
m2b = RDP_GETOM_BLEND_M2B_0(state.otherModes);
|
||||
m2a = RDP_GETOM_BLEND_M2A_0(state.otherModes);
|
||||
}
|
||||
|
||||
if (RDP_GETOM_FORCE_BLEND(state.otherModes) || cycle == RDP_CYCLE_TYPE_2) {
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
if (m1a == 1 || m2a == 1) {
|
||||
if (/*(m1a != 1 || m1b == 3) &&*/ (m2a == 1 || m2b == 3)) {
|
||||
int src = GL_ZERO, dst = GL_ONE;
|
||||
const char * alpha = "c.a";
|
||||
switch (m1b) {
|
||||
case 0: // c.a
|
||||
src = GL_SRC_ALPHA;
|
||||
break;
|
||||
case 1: // fog.a
|
||||
src = GL_SRC_ALPHA;
|
||||
alpha = "fog.a";
|
||||
// LOGERROR("Unsupported src alpha : FOG\n");
|
||||
// LOGERROR(rglCombiner2String(state));
|
||||
break;
|
||||
case 2: // shade.a
|
||||
src = GL_SRC_ALPHA;
|
||||
alpha = "gl_Color.a";
|
||||
// LOGERROR("Unsupported src alpha : SHADE\n");
|
||||
// LOGERROR(rglCombiner2String(state));
|
||||
break;
|
||||
case 3: // 0
|
||||
src = GL_ZERO;
|
||||
break;
|
||||
}
|
||||
switch (m1a) {
|
||||
case 0: // c
|
||||
if (m1b != 0 /* c.a */)
|
||||
p += sprintf(
|
||||
p, "c.a = %s; \n", alpha);
|
||||
break;
|
||||
case 1: // f
|
||||
LOGERROR("Unsupported src color : FRAG\n");
|
||||
LOGERROR("%s", rglCombiner2String(state));
|
||||
break;
|
||||
case 2: // b
|
||||
p += sprintf(
|
||||
p, "c = vec4(vec3(b), %s); \n", alpha);
|
||||
break;
|
||||
case 3: // fog
|
||||
p += sprintf(
|
||||
p, "c = vec4(vec3(fog), %s); \n", alpha);
|
||||
break;
|
||||
}
|
||||
switch (m2b) {
|
||||
case 0:
|
||||
switch (m1b) {
|
||||
case 3:
|
||||
dst = GL_ONE;
|
||||
break;
|
||||
default:
|
||||
dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
dst = GL_DST_ALPHA;
|
||||
break;
|
||||
case 2:
|
||||
dst = GL_ONE;
|
||||
break;
|
||||
case 3:
|
||||
dst = GL_ZERO;
|
||||
break;
|
||||
}
|
||||
|
||||
c->srcBlend = src;
|
||||
c->dstBlend = dst;
|
||||
} else {
|
||||
LOGERROR("Unsuported blender :\n");
|
||||
LOGERROR("%s", rglCombiner2String(state));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sprintf(_1ma, "(1.0 - %s)", bA[0][m1b]);
|
||||
p +=
|
||||
sprintf(p, blender, bA[0][m1b], bRGB[m1a], bA[1][m2b], bRGB[m2a]);
|
||||
}
|
||||
} else {
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
p +=
|
||||
sprintf(p,
|
||||
noblender
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
p +=
|
||||
sprintf(
|
||||
p,
|
||||
"%s \n"
|
||||
"} \n"
|
||||
,write
|
||||
);
|
||||
|
||||
rglAssert(p < src+sizeof(src));
|
||||
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
//printf("Creating combiner : \n%s", src);
|
||||
#endif
|
||||
|
||||
c->shader = rglCreateShader(
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = ftransform(); \n"
|
||||
" gl_FrontColor = gl_Color; \n"
|
||||
" gl_BackColor = gl_FrontColor; \n"
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
" gl_TexCoord[1] = gl_MultiTexCoord1; \n"
|
||||
#endif
|
||||
" gl_TexCoord[2] = gl_MultiTexCoord2; \n"
|
||||
"} \n"
|
||||
,
|
||||
src);
|
||||
|
||||
#ifdef RDP_DEBUG
|
||||
chunk.shader = c->shader;
|
||||
#endif
|
||||
rglUseShader(c->shader);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
int location;
|
||||
location = glGetUniformLocationARB(c->shader->prog, "texture0");
|
||||
glUniform1iARB(location, 0);
|
||||
#ifdef RGL_EXACT_BLEND
|
||||
location = glGetUniformLocationARB(c->shader->prog, "texture1");
|
||||
glUniform1iARB(location, 1);
|
||||
#endif
|
||||
location = glGetUniformLocationARB(c->shader->prog, "texture2");
|
||||
glUniform1iARB(location, 2);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
ok:;
|
||||
#ifndef RGL_EXACT_BLEND
|
||||
if ((format & RGL_COMB_FMT) == RGL_COMB_FMT_DEPTH ||
|
||||
(c->srcBlend == GL_ONE && c->dstBlend == GL_ZERO))
|
||||
glDisable(GL_BLEND);
|
||||
else {
|
||||
glEnable(GL_BLEND);
|
||||
if ((format & RGL_COMB_FMT) == RGL_COMB_FMT_RGBA)
|
||||
glBlendFuncSeparate(c->srcBlend, c->dstBlend, GL_ZERO, GL_ONE);
|
||||
else
|
||||
glBlendFunc(c->srcBlend, c->dstBlend);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
extern ptr_ConfigOpenSection ConfigOpenSection;
|
||||
extern ptr_ConfigSetParameter ConfigSetParameter;
|
||||
extern ptr_ConfigGetParameter ConfigGetParameter;
|
||||
extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp;
|
||||
extern ptr_ConfigSetDefaultInt ConfigSetDefaultInt;
|
||||
extern ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat;
|
||||
extern ptr_ConfigSetDefaultBool ConfigSetDefaultBool;
|
||||
extern ptr_ConfigSetDefaultString ConfigSetDefaultString;
|
||||
extern ptr_ConfigGetParamInt ConfigGetParamInt;
|
||||
extern ptr_ConfigGetParamFloat ConfigGetParamFloat;
|
||||
extern ptr_ConfigGetParamBool ConfigGetParamBool;
|
||||
extern ptr_ConfigGetParamString ConfigGetParamString;
|
||||
|
||||
char rgl_cwd[512];
|
||||
|
||||
int rglReadSettings()
|
||||
{
|
||||
|
||||
m64p_handle videoGeneralSection;
|
||||
m64p_handle videoZ64Section;
|
||||
if (ConfigOpenSection("Video-General", &videoGeneralSection) != M64ERR_SUCCESS ||
|
||||
ConfigOpenSection("Video-Z64", &videoZ64Section) != M64ERR_SUCCESS)
|
||||
{
|
||||
rdp_log(M64MSG_ERROR, "Could not open configuration");
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfigSetDefaultBool(videoGeneralSection, "Fullscreen", false, "Use fullscreen mode if True, or windowed mode if False");
|
||||
ConfigSetDefaultBool(videoZ64Section, "HiResFB", true, "High resolution framebuffer");
|
||||
ConfigSetDefaultBool(videoZ64Section, "FBInfo", true, "Use framebuffer info");
|
||||
ConfigSetDefaultBool(videoZ64Section, "Threaded", false, "Run RDP on thread");
|
||||
ConfigSetDefaultBool(videoZ64Section, "Async", false, "Run RDP asynchronously");
|
||||
ConfigSetDefaultBool(videoZ64Section, "NoNpotFbos", false, "Don't use NPOT FBOs (may be needed for older graphics cards)");
|
||||
|
||||
rglSettings.resX = ConfigGetParamInt(videoGeneralSection, "ScreenWidth");
|
||||
rglSettings.resY = ConfigGetParamInt(videoGeneralSection, "ScreenHeight");
|
||||
rglSettings.fsResX = ConfigGetParamInt(videoGeneralSection, "ScreenWidth");
|
||||
rglSettings.fsResY = ConfigGetParamInt(videoGeneralSection, "ScreenHeight");
|
||||
rglSettings.fullscreen = ConfigGetParamBool(videoGeneralSection, "Fullscreen");
|
||||
rglSettings.hiresFb = ConfigGetParamBool(videoZ64Section, "HiResFB");
|
||||
rglSettings.fbInfo = ConfigGetParamBool(videoZ64Section, "FBInfo");
|
||||
rglSettings.threaded = ConfigGetParamBool(videoZ64Section, "Threaded");
|
||||
rglSettings.async = ConfigGetParamBool(videoZ64Section, "Async");
|
||||
rglSettings.noNpotFbos = ConfigGetParamBool(videoZ64Section, "NoNpotFbos");
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rgl.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
rglTextureHead_t freeTextures;
|
||||
rglTextureHead_t texturesByCrc[256];
|
||||
rglTextureHead_t texturesByUsage;
|
||||
|
||||
void rglTouchTMEM()
|
||||
{
|
||||
rglTexCacheCounter++;
|
||||
if (!rglTexCacheCounter) {
|
||||
// shouldn't happen too often but let's do things correctly for the hell of it ;)
|
||||
rglResetTextureCache();
|
||||
}
|
||||
}
|
||||
|
||||
inline int crc8(uint32_t crc)
|
||||
{
|
||||
uint8_t res;
|
||||
res = crc^(crc>>8)^(crc>>16)^(crc>>24);
|
||||
return res;
|
||||
}
|
||||
|
||||
void rglDeleteTexture(rglTexture_t * tex)
|
||||
{
|
||||
//LOG("deleting texture %x\n", tex);
|
||||
glDeleteTextures(1, &tex->id);
|
||||
if (tex->zid)
|
||||
glDeleteTextures(1, &tex->zid);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
tex->id = tex->zid = 0;
|
||||
CIRCLEQ_REMOVE(&texturesByUsage, tex, byUsage);
|
||||
CIRCLEQ_REMOVE(&texturesByCrc[crc8(tex->crc)], tex, byCrc);
|
||||
CIRCLEQ_INSERT_TAIL(rglTexture_t, &freeTextures, tex, byUsage);
|
||||
}
|
||||
|
||||
rglTexture_t * rglNewTexture(uint32_t crc)
|
||||
{
|
||||
rglTexture_t * res;
|
||||
|
||||
if (CIRCLEQ_EMPTY(&freeTextures))
|
||||
rglDeleteTexture(CIRCLEQ_FIRST(&texturesByUsage));
|
||||
|
||||
res = CIRCLEQ_FIRST(&freeTextures);
|
||||
//LOG("new texture %x %x crc %x\n", res, crc, crc8(crc));
|
||||
CIRCLEQ_REMOVE(&freeTextures, res, byUsage);
|
||||
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByUsage, res, byUsage);
|
||||
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByCrc[crc8(crc)], res, byCrc);
|
||||
|
||||
res->wt = res->ws = res->filter = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void rglInitTextureCache()
|
||||
{
|
||||
int i;
|
||||
// initialize textures lists
|
||||
CIRCLEQ_INIT(rglTexture_t, &freeTextures);
|
||||
CIRCLEQ_INIT(rglTexture_t, &texturesByUsage);
|
||||
for (i=0; i<256; i++)
|
||||
CIRCLEQ_INIT(rglTexture_t, &texturesByCrc[i]);
|
||||
for (i=0; i<RGL_TEX_CACHE_SIZE; i++) {
|
||||
CIRCLEQ_INSERT_TAIL(rglTexture_t, &freeTextures, rglTextures+i, byUsage);
|
||||
}
|
||||
}
|
||||
|
||||
void rglResetTextureCache()
|
||||
{
|
||||
static int init;
|
||||
if (!init) {
|
||||
rglInitTextureCache();
|
||||
init = 1;
|
||||
}
|
||||
|
||||
memset(rglTexCache, 0, sizeof(rglTexCache));
|
||||
rglTexCacheCounter = 1;
|
||||
while (!CIRCLEQ_EMPTY(&texturesByUsage))
|
||||
rglDeleteTexture(CIRCLEQ_FIRST(&texturesByUsage));
|
||||
|
||||
rglInitTextureCache();
|
||||
}
|
||||
|
||||
void rglTile(rdpTile_t & tile, rglTile_t & rtile, int recth)
|
||||
{
|
||||
rglTexture_t * tex;
|
||||
int ws, wt;
|
||||
int line = tile.line;
|
||||
//int cs, ct;
|
||||
int clipw = ((tile.sh - tile.sl) >>2)+1;
|
||||
int cliph = ((tile.th - tile.tl) >>2)+1;
|
||||
int indirect = 1;
|
||||
uint8_t * from = rdpTmem;
|
||||
int ow, oh;
|
||||
|
||||
// if (recth && cliph == recth+1) // hack for Mario Party (not necessary if we handle filter for texrect)
|
||||
// cliph = recth;
|
||||
|
||||
// if (tile.ms && tile.mask_s && (2<<tile.mask_s)<clipw)
|
||||
// tile.ms = 0;
|
||||
// if (tile.mt && tile.mask_t && (2<<tile.mask_t)<cliph)
|
||||
// tile.mt = 0;
|
||||
// if (tile.ms) clipw /= 2;
|
||||
// if (tile.mt) cliph /= 2;
|
||||
|
||||
if (!line) line = 1;
|
||||
|
||||
//tile.format = ti_format;
|
||||
|
||||
if (tile.size == 3) line <<= 1; // why why WHY ?
|
||||
//if (tile.size == 0) clipw *= 2;
|
||||
tile.w = line << 1 >> tile.size;
|
||||
//if (tile.mask_s && (1<<tile.mask_s) < tile.w*2) // HACK
|
||||
if (tile.mask_s && (1<<tile.mask_s) < tile.w)
|
||||
tile.w = 1<<tile.mask_s;
|
||||
if (tile.cs && ((clipw+3)&~3) < tile.w) // GL wants width divisible by 4 at least ?
|
||||
tile.w = ((clipw+3)&~3);
|
||||
|
||||
tile.h = ((tile.th - tile.tl) >>2)+1; // FIXME why not cliph ???
|
||||
//tile.h = (tile.th >>2)+1;
|
||||
// if (tile.h <= 0)
|
||||
// tile.h = (tile.th >>2)+1;
|
||||
// FIXME remove test on mt ?
|
||||
if (tile.mask_t && ((1<<tile.mask_t) < tile.h || (!tile.ct && !tile.mt)))
|
||||
tile.h = 1<<tile.mask_t;
|
||||
else
|
||||
{
|
||||
// if (tile.h < 0 || (tile.h & 3)) {
|
||||
// tile.h = 1; while (tile.h<(tile.th>>2)) tile.h <<= 1;
|
||||
// }
|
||||
}
|
||||
|
||||
// if (!tile.mask_t && !tile.ct/* && !tile.mt*/)
|
||||
// tile.h = (0x1000-tile.tmem)/line;
|
||||
|
||||
// if (tile.sl && !tile.mask_s) {
|
||||
// printf("shifting sl %d\n", tile.sl);
|
||||
// tile.tmem += tile.sl << tile.format >> 1;
|
||||
// tile.tmem &= 0xfff;
|
||||
// tile.sl = 0;
|
||||
// }
|
||||
// if (tile.tl && !tile.mask_t) {
|
||||
// printf("shifting tl %d\n", tile.tl);
|
||||
// tile.tmem += tile.tl * line;
|
||||
// tile.tmem &= 0xfff;
|
||||
// tile.tl = 0;
|
||||
// }
|
||||
|
||||
if (recth && tile.h == 1)
|
||||
// +1 for yoshi
|
||||
tile.h = recth+1;
|
||||
|
||||
if (/*tile.h == 1 || */tile.w*tile.h << tile.size >> 1 > 0x1000-tile.tmem) {
|
||||
DUMP("fixing tile size from %dx%d to ", tile.w, tile.h);
|
||||
//tile.w = (line << 3) >> tile.size + 2;
|
||||
//tile.h = 1; while (tile.h<(tile.th>>2)) tile.h <<= 1;
|
||||
tile.h = (0x1000-tile.tmem)/line;
|
||||
DUMP("%dx%d\n", tile.w, tile.h);
|
||||
}
|
||||
|
||||
// this is a warkaround for a bug in pj64 rsp plugin
|
||||
// now fixed
|
||||
if (0&&recth && /*tile.line == 8 && */tile.h == 1) {
|
||||
//LOG("direct\n");
|
||||
tile.w = rdpTiWidth << rdpTiSize >> tile.size;
|
||||
tile.h = recth;
|
||||
from = gfx.RDRAM + rdpTiAddress;
|
||||
if (recth > 1 || rdpTiWidth > 1)
|
||||
line = rdpTiWidth << rdpTiSize >> 1;
|
||||
indirect = 0;
|
||||
}
|
||||
|
||||
{
|
||||
int fromLine, stop, fromFormat, fromSize;
|
||||
uint32_t address = rdpGetTmemOrigin(tile.tmem, &fromLine, &stop, &fromFormat, &fromSize);
|
||||
DUMP("tmem %x rdram %x\n", tile.tmem, address);
|
||||
if (address != (uint32_t)~0) {
|
||||
rglRenderBuffer_t * buffer;
|
||||
if (!fromLine) fromLine = line;
|
||||
if (!tile.mask_t)
|
||||
tile.h = (stop-tile.tmem)/line;
|
||||
rtile.hiresBuffer = 0;
|
||||
//while (0) {
|
||||
CIRCLEQ_FOREACH(rglRenderBuffer_t, buffer, &rBufferHead, link) {
|
||||
//if (buffer->flags & RGL_RB_DEPTH) continue;
|
||||
if (buffer->area.xh != 8192)
|
||||
buffer->addressStop = buffer->addressStart + buffer->line * ((buffer->area.yl >>2)+1);
|
||||
|
||||
// conservative
|
||||
// if (address + tile.h * line > buffer->addressStart &&
|
||||
// address < buffer->addressStop)
|
||||
if (address >= buffer->addressStart/* + buffer->line * ((buffer->area.yh >>2)+1)*/ && // oops cannot use yh, might not be initialized
|
||||
address + tile.h * line <= buffer->addressStop)
|
||||
DUMP("check %x --> %x with %x --> %x (%x %x %d %x)\n",
|
||||
address, address + tile.h * line,
|
||||
buffer->addressStart, buffer->addressStop,
|
||||
fromLine, buffer->line, tile.h, line);
|
||||
|
||||
// TODO store real address stop, it's not necessarily the same as
|
||||
// address + tile.h * line
|
||||
// conservative
|
||||
// if (address + tile.h * line > buffer->addressStart &&
|
||||
// address < buffer->addressStop &&
|
||||
// more strict (better for LEGO racer)
|
||||
// general solution would be : find all candidates, pick the one that covers
|
||||
// the biggest area
|
||||
if ((!rtile.hiresBuffer || buffer->addressStart > rtile.hiresBuffer->addressStart) &&
|
||||
address >= buffer->addressStart/* + buffer->line * ((buffer->area.yh >>2)+1)*/ && // oops cannot use yh, might not be initialized
|
||||
address + tile.h * line <= buffer->addressStop &&
|
||||
(tile.h <= 1 || fromLine == buffer->line)) {
|
||||
DUMP("texture buffer at %x %d x %d %d %d fmt %d fromfmt %d\n",
|
||||
buffer->addressStart, tile.w, tile.h,
|
||||
fromLine, buffer->line, tile.format, fromFormat);
|
||||
|
||||
rtile.hiresBuffer = buffer;
|
||||
rtile.hiresAddress = address;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtile.hiresBuffer) {
|
||||
// FIXME current buffer could be a depth buffer, in this case
|
||||
// we want the texture rendered as depth too
|
||||
rtile.hiresBuffer->flags &= ~RGL_RB_DEPTH;
|
||||
//rglRenderChunks(rtile.hiresBuffer);
|
||||
}
|
||||
|
||||
if (rglSettings.hiresFb && rtile.hiresBuffer) {
|
||||
memcpy(&rtile, &tile, sizeof(tile));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtile.hiresBuffer) {
|
||||
LOG("updating rdram %x\n", address);
|
||||
rglFramebuffer2Rdram(*rtile.hiresBuffer, address, address + tile.h * line);
|
||||
line = fromLine;
|
||||
from = gfx.RDRAM + address;
|
||||
indirect = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
rtile.hiresBuffer = 0;
|
||||
|
||||
if (tile.w > 1024) tile.w = 1024;
|
||||
if (tile.h > 1024) tile.h = 1024;
|
||||
|
||||
ow = tile.w; oh = tile.h; // save w/h before making it a power of 2
|
||||
{
|
||||
int w=1, h=1;
|
||||
while (w < tile.w) w*=2;
|
||||
while (h < tile.h) h*=2;
|
||||
tile.w = rtile.w = w;
|
||||
tile.h = rtile.h = h;
|
||||
}
|
||||
|
||||
memcpy(&rtile, &tile, sizeof(tile));
|
||||
rtile.line = line;
|
||||
|
||||
// NOTE more general solutions would involve subdividing the geometry
|
||||
// or writing clamping/mirroring in glsl
|
||||
int badmirror_s =
|
||||
tile.mask_s && tile.cs && tile.ms && (clipw/2) < (1<<tile.mask_s);
|
||||
int badmirror_t =
|
||||
tile.mask_t && tile.ct && tile.mt && (cliph/2) < (1<<tile.mask_t);
|
||||
int clipmw = clipw, clipmh = cliph;
|
||||
if (tile.ms && !badmirror_s) clipmw /= 2;
|
||||
if (tile.mt && !badmirror_t) clipmh /= 2;
|
||||
int badclamp_s =
|
||||
tile.mask_s && tile.cs && clipmw > (1<<tile.mask_s);
|
||||
int badclamp_t =
|
||||
tile.mask_t && tile.ct && clipmh > (1<<tile.mask_t);
|
||||
|
||||
int npot_s = (tile.w-1)&tile.w;
|
||||
int npot_t = (tile.h-1)&tile.h;
|
||||
|
||||
ws = GL_REPEAT;
|
||||
//ws = GL_CLAMP_TO_EDGE;
|
||||
if ((!tile.mask_s || tile.cs) && !badclamp_s) {
|
||||
// tile.tmem += (tile.sl>>2) << tile.size >> 1;
|
||||
// tile.sh -= tile.sl;
|
||||
// tile.sl = 0;
|
||||
ws = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
if (tile.ms && !badmirror_s)
|
||||
ws = ((!tile.mask_s || tile.cs) && !badclamp_s)?
|
||||
GL_MIRROR_CLAMP_TO_EDGE_EXT : GL_MIRRORED_REPEAT;
|
||||
|
||||
wt = GL_REPEAT;
|
||||
//wt = GL_CLAMP_TO_EDGE;
|
||||
if ((!tile.mask_t || tile.ct) && !badclamp_t) {
|
||||
// tile.tmem += (tile.tl>>2) * line;
|
||||
// tile.th -= tile.tl;
|
||||
// tile.tl = 0;
|
||||
wt = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
if (tile.mt && !badmirror_t)
|
||||
wt = ((!tile.mask_t || tile.ct) && !badclamp_t)?
|
||||
GL_MIRROR_CLAMP_TO_EDGE_EXT : GL_MIRRORED_REPEAT;
|
||||
|
||||
#if 1
|
||||
if ((npot_s||npot_t) && ws != GL_CLAMP_TO_EDGE) {
|
||||
//LOG("Fixup npot clamp s\n");
|
||||
ws = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
if ((npot_t||npot_s) && wt != GL_CLAMP_TO_EDGE) {
|
||||
//LOG("Fixup npot clamp t\n");
|
||||
wt = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
#else
|
||||
// ws = GL_CLAMP_TO_EDGE;
|
||||
// wt = GL_CLAMP_TO_EDGE;
|
||||
#endif
|
||||
|
||||
rtile.ws = ws;
|
||||
rtile.wt = wt;
|
||||
|
||||
rglAssert(!(tile.tmem & ~ 0xfff));
|
||||
if (rglTexCache[tile.tmem].counter == rglTexCacheCounter &&
|
||||
rglTexCache[tile.tmem].tex->fmt == tile.format &&
|
||||
rglTexCache[tile.tmem].tex->w == tile.w
|
||||
&&
|
||||
rglTexCache[tile.tmem].tex->h == tile.h
|
||||
// rglTexCache[tile.tmem].tex->h > (tile.th>>2)
|
||||
) {
|
||||
tex = rglTexCache[tile.tmem].tex;
|
||||
goto ok;
|
||||
}
|
||||
|
||||
// printf("tile #%d fmt %s sz %d w %d mask %d %dx%d (%d %d)\n", &tile-rdpTiles, rdpImageFormats[tile.format], tile.size, line, tile.mask_s, (tile.sh - tile.sl >>2)+1, (tile.th - tile.tl >>2)+1, tile.sl>>2, tile.tl>>2);
|
||||
|
||||
//rglAssert(tile.w == (tile.sh - tile.sl >>2)+1);
|
||||
|
||||
{
|
||||
int h, i, j, x, y;
|
||||
int palette = 0;
|
||||
uint32_t crc = 0;
|
||||
rglTextureHead_t * list;
|
||||
|
||||
#if 1
|
||||
if (tile.format == RDP_FORMAT_CI ||
|
||||
(tile.size <= 1 && RDP_GETOM_EN_TLUT(rdpState.otherModes))) {
|
||||
// tlut crc
|
||||
h = tile.size? 256:16;
|
||||
if (tile.size == 0) palette = (tile.palette<<4)&0xff;
|
||||
for (i=0; i<h; i++)
|
||||
crc = ((crc>>3)|(crc<<(32-3)))+(rdpTlut[(i+palette)*4]);
|
||||
}
|
||||
|
||||
for (y=0; y<oh; y++) {
|
||||
uint32_t * p = (uint32_t *) &from[(tile.tmem + y*line)/*&0x3fff*/];
|
||||
for (x=0; x<(line>>2); x++)
|
||||
crc = ((crc>>3)|(crc<<(32-3)))+(*p++);
|
||||
}
|
||||
|
||||
list = texturesByCrc + crc8(crc);
|
||||
CIRCLEQ_FOREACH(rglTexture_t, tex, list, byCrc) {
|
||||
//LOG("comparing %x with %x\n", tex->crc, crc);
|
||||
if (tex->crc == crc &&
|
||||
tex->fmt == tile.format &&
|
||||
tex->clipw >= clipw &&
|
||||
tex->cliph >= cliph &&
|
||||
tex->w == tile.w &&
|
||||
tex->h >= tile.h) {
|
||||
CIRCLEQ_REMOVE(&texturesByUsage, tex, byUsage);
|
||||
CIRCLEQ_INSERT_TAIL(rglTexture_t, &texturesByUsage, tex, byUsage);
|
||||
goto ok2;
|
||||
}
|
||||
// if (tex->crc == crc)
|
||||
// LOG("Same CRC %x !\n", crc);
|
||||
}
|
||||
#endif
|
||||
|
||||
tex = rglNewTexture(crc);
|
||||
tex->fmt = tile.format;
|
||||
tex->w = tile.w;
|
||||
tex->h = tile.h;
|
||||
tex->clipw = clipw;
|
||||
tex->cliph = cliph;
|
||||
tex->crc = crc;
|
||||
glGenTextures(1, &tex->id);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex->id);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
uint8_t * ptr;
|
||||
GLuint packed = 0;
|
||||
GLuint glfmt = 0, glpixfmt = 0;
|
||||
|
||||
ptr = rglTmpTex2;
|
||||
|
||||
#define XOR_SWAP_BYTE 3
|
||||
#define XOR_SWAP_WORD 2
|
||||
#define XOR_SWAP_DWORD 2
|
||||
// ugly but it works ...
|
||||
if (tile.cs || !tile.mask_s) ow = tile.w;
|
||||
if (tile.ct || !tile.mask_t) oh = tile.h;
|
||||
#define CLAMP \
|
||||
int ci = i; \
|
||||
int cj = j; \
|
||||
if ((tile.cs || !tile.mask_s) && ci >= clipw) ci = clipw-1; \
|
||||
if ((tile.ct || !tile.mask_t) && cj >= cliph) cj = cliph-1; \
|
||||
|
||||
switch (tile.size) {
|
||||
case 3:
|
||||
for (j=0; j<oh; j++)
|
||||
for (i=0; i<ow; i++) {
|
||||
CLAMP;
|
||||
uint32_t *tc = (uint32_t*)from;
|
||||
int taddr = ((tile.tmem/4) + ((cj) * (line/4)) + (ci)) ^ ((cj & indirect) ? XOR_SWAP_DWORD : 0);
|
||||
uint32_t a = tc[taddr/*&0xfff*/];
|
||||
//uint32_t a = *(uint32_t *)&from[j*line + i*4 + tile.tmem ^ ((j&1)<<1) ^ XOR_SWAP_DWORD];
|
||||
*(uint32_t *)&ptr[(tile.h-1-j)*tile.w*4 + (tile.w-1-i)*4] = a;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (j=0; j<oh; j++)
|
||||
for (i=0; i<ow; i++) {
|
||||
CLAMP;
|
||||
uint16_t *tc = (uint16_t*)from;
|
||||
int taddr = ((tile.tmem/2) + ((cj) * (line/2)) + (ci)) ^ ((cj & indirect) ? XOR_SWAP_WORD : 0);
|
||||
uint16_t a = tc[(taddr ^ WORD_ADDR_XOR)/*&0x1fff*/];
|
||||
// uint16_t a = *(uint16_t *)&from[j*line + i*2 + tile.tmem ^ ((j&1)<<2) ^ XOR_SWAP_WORD];
|
||||
*(uint16_t *)&ptr[(tile.h-1-j)*tile.w*2 + (tile.w-1-i)*2] = a;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (j=0; j<oh; j++)
|
||||
for (i=0; i<ow; i++) {
|
||||
CLAMP;
|
||||
uint8_t a = *(uint8_t *)&from[((cj*line + ci + tile.tmem) ^ ((cj & indirect)<<2) ^ XOR_SWAP_BYTE)/*&0xfff*/];
|
||||
*(uint8_t *)&ptr[(tile.h-1-j)*tile.w + (tile.w-1-i)] = a;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
// FIXME
|
||||
for (j=0; j<tile.h; j++)
|
||||
for (i=0; i<tile.w; i+=2) {
|
||||
CLAMP;
|
||||
uint8_t a = *(uint8_t *)&from[((cj*line + ci/2 + tile.tmem) ^ ((cj & indirect)<<2) ^ XOR_SWAP_BYTE)/*&0x3fff*/];
|
||||
*(uint8_t *)&ptr[(tile.h-1-j)*tile.w/2 + (tile.w/2-1-i/2)] = a; //(a>>4)|(a<<4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
from = ptr;
|
||||
|
||||
i = tile.format;
|
||||
|
||||
// in Tom Clancy, they do this, using I texture with TLUT enabled
|
||||
if (i != RDP_FORMAT_CI && tile.size <= 1 && RDP_GETOM_EN_TLUT(rdpState.otherModes)) {
|
||||
LOG("fixing %s-%d tile to CI\n", rdpImageFormats[i], tile.size);
|
||||
i = RDP_FORMAT_CI;
|
||||
}
|
||||
|
||||
if (tile.size <= 1 && i == RDP_FORMAT_RGBA) {
|
||||
LOG("fixing RGBA tile to I\n");
|
||||
i = RDP_FORMAT_I;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case RDP_FORMAT_CI: {
|
||||
if (!RDP_GETOM_TLUT_TYPE(rdpState.otherModes)) {
|
||||
glfmt = GL_RGBA;
|
||||
packed = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
} else {
|
||||
glfmt = GL_RGBA;
|
||||
glpixfmt = GL_LUMINANCE_ALPHA;
|
||||
//glfmt = GL_LUMINANCE_ALPHA;
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
switch (tile.size) {
|
||||
case 0:
|
||||
ptr = rglTmpTex;
|
||||
for (i=0; i<tile.w*tile.h/2; i++) {
|
||||
uint16_t a = rdpTlut[((from[i]&0xf) + palette/* ^ WORD_ADDR_XOR*/)*4];
|
||||
uint16_t b = rdpTlut[((from[i]>>4) + palette/* ^ WORD_ADDR_XOR*/)*4];
|
||||
if (RDP_GETOM_TLUT_TYPE(rdpState.otherModes)) {
|
||||
a = (a>>8)|(a<<8);
|
||||
b = (b>>8)|(b<<8);
|
||||
}
|
||||
*(uint16_t *)&ptr[i*4] = a;
|
||||
*(uint16_t *)&ptr[i*4+2] = b;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
ptr = rglTmpTex;
|
||||
//rdpTlut[palette] = 0;
|
||||
for (i=0; i<tile.w*tile.h; i++) {
|
||||
uint16_t a = rdpTlut[(from[i] + palette/* ^ WORD_ADDR_XOR*/)*4];
|
||||
if (RDP_GETOM_TLUT_TYPE(rdpState.otherModes))
|
||||
a = (a>>8)|(a<<8);
|
||||
*(uint16_t *)&ptr[i*2] = a;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RDP_FORMAT_RGBA: {
|
||||
glfmt = GL_RGBA;
|
||||
switch (tile.size) {
|
||||
case 2:
|
||||
//packed = GL_UNSIGNED_SHORT_4_4_4_4_REV;
|
||||
packed = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
case 3:
|
||||
packed = GL_UNSIGNED_INT_8_8_8_8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RDP_FORMAT_IA: {
|
||||
glfmt = GL_RGBA;
|
||||
glpixfmt = GL_LUMINANCE_ALPHA;
|
||||
//if (tile.size == 0) line *= 2;
|
||||
switch (tile.size) {
|
||||
case 0: {
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
ptr = rglTmpTex;
|
||||
for (i=0; i<tile.h*tile.w/2; i++) {
|
||||
uint32_t a = (from[i]&0xe0) >> 5;
|
||||
int8_t b = (from[i]&0x10) >> 4;
|
||||
ptr[i*4+2] = (a<<5) | (a<<2) | (a>>1);
|
||||
ptr[i*4+3] = -b;
|
||||
a = (from[i]&0xe) >> 1;
|
||||
b = (from[i]&0x1);
|
||||
ptr[i*4+0] = (a<<5) | (a<<2) | (a>>1);
|
||||
ptr[i*4+1] = -b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
ptr = rglTmpTex;
|
||||
for (i=0; i<tile.h*tile.w; i++) {
|
||||
uint32_t a = from[i]&0xF0;
|
||||
a = a | (a>>4);
|
||||
ptr[i*2] = a | (a>>4);
|
||||
a = from[i]&0x0F;
|
||||
a = a | (a<<4);
|
||||
ptr[i*2+1] = a;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
ptr = rglTmpTex;
|
||||
for (i=0; i<tile.h*tile.w*2; i+=2) {
|
||||
ptr[i] = from[i+1];
|
||||
ptr[i+1] = from[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RDP_FORMAT_I: {
|
||||
glfmt = GL_INTENSITY;
|
||||
// if (RDP_GETOM_ALPHA_CVG_SELECT(rdpState.otherModes))
|
||||
// glfmt = GL_LUMINANCE;
|
||||
glpixfmt = GL_LUMINANCE;
|
||||
switch (tile.size) {
|
||||
case 0: {
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
ptr = rglTmpTex;
|
||||
for (i=0; i<tile.h*tile.w/2; i++) {
|
||||
uint32_t a = from[i]&0xF0;
|
||||
ptr[i*2+1] = a | (a>>4);
|
||||
a = from[i]&0x0F;
|
||||
ptr[i*2] = a | (a<<4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
packed = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (packed) {
|
||||
DUMP("loading texture %dx%d fmt %s size %x (%x %x %x %p)\n", tile.w, tile.h, rdpImageFormats[tile.format], tile.size, glfmt, glpixfmt, packed, ptr);
|
||||
// printf("cycle type = %d\n", chunk.rdpState.otherModes.cycle_type);
|
||||
if (!glpixfmt)
|
||||
glpixfmt = glfmt;
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glfmt, tile.w, tile.h, 0, glpixfmt, packed,
|
||||
ptr);
|
||||
rglAssert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
|
||||
#if 0
|
||||
if (1||RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY) {
|
||||
uint32_t * pixels = (uint32_t *) malloc(tile.w*tile.h*4);
|
||||
// 0x1902 is another constant meaning GL_DEPTH_COMPONENT
|
||||
// (but isn't defined in gl's headers !!)
|
||||
if (1/*fmt != GL_DEPTH_COMPONENT && fmt != 0x1902*/) {
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
ilTexImage(tile.w, tile.h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
|
||||
} else {
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
|
||||
int i;
|
||||
for (i=0; i<tile.w*tile.h; i++)
|
||||
((unsigned char *)ptr)[i] = ((unsigned short *)pixels)[i]/256;
|
||||
ilTexImage(tile.w, tile.h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, ptr);
|
||||
}
|
||||
char name[128];
|
||||
// sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
|
||||
// system(name);
|
||||
static int num;
|
||||
sprintf(name, "dump/tex%04d-%s-%d-%d-%d.png", num++, rdpImageFormats[tile.format], tile.size, &tile - rdpTiles, tile.tmem);
|
||||
fprintf(stderr, "Writing '%s'\n", name);
|
||||
ilSaveImage(name);
|
||||
|
||||
free(pixels);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!packed) {
|
||||
LOGERROR("unsuported format %s size %d\n", rdpImageFormats[tile.format], tile.size);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
ok2:
|
||||
rglTexCache[tile.tmem].counter = rglTexCacheCounter;
|
||||
rglTexCache[tile.tmem].tex = tex;
|
||||
|
||||
ok:
|
||||
rtile.tex = tex;
|
||||
|
||||
{
|
||||
GLuint filter;
|
||||
if (recth) {
|
||||
switch (RDP_GETOM_SAMPLE_TYPE(rdpState.otherModes)) {
|
||||
case 0:
|
||||
filter = GL_NEAREST;
|
||||
break;
|
||||
default:
|
||||
filter = GL_LINEAR;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
filter = GL_LINEAR;
|
||||
|
||||
rtile.filter = filter;
|
||||
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{ global:
|
||||
PluginStartup;
|
||||
PluginShutdown;
|
||||
PluginGetVersion;
|
||||
ChangeWindow;
|
||||
InitiateGFX;
|
||||
MoveScreen;
|
||||
ProcessDList;
|
||||
ProcessRDPList;
|
||||
RomClosed;
|
||||
RomOpen;
|
||||
ShowCFB;
|
||||
UpdateScreen;
|
||||
ViStatusChanged;
|
||||
ViWidthChanged;
|
||||
ReadScreen2;
|
||||
SetRenderingCallback;
|
||||
ResizeVideoOutput;
|
||||
FBRead;
|
||||
FBWrite;
|
||||
FBGetFrameBufferInfo;
|
||||
local: *; };
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* z64
|
||||
*
|
||||
* Copyright (C) 2007 ziggy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef _Z64_H_
|
||||
#define _Z64_H_
|
||||
#include <stdint.h>
|
||||
|
||||
#define DACRATE_NTSC (48681812)
|
||||
#define DACRATE_PAL (49656530)
|
||||
#define DACRATE_MPAL (48628316)
|
||||
|
||||
#define SP_INTERRUPT 0x1
|
||||
#define SI_INTERRUPT 0x2
|
||||
#define AI_INTERRUPT 0x4
|
||||
#define VI_INTERRUPT 0x8
|
||||
#define PI_INTERRUPT 0x10
|
||||
#define DP_INTERRUPT 0x20
|
||||
|
||||
#define SP_STATUS_HALT 0x0001
|
||||
#define SP_STATUS_BROKE 0x0002
|
||||
#define SP_STATUS_DMABUSY 0x0004
|
||||
#define SP_STATUS_DMAFULL 0x0008
|
||||
#define SP_STATUS_IOFULL 0x0010
|
||||
#define SP_STATUS_SSTEP 0x0020
|
||||
#define SP_STATUS_INTR_BREAK 0x0040
|
||||
#define SP_STATUS_SIGNAL0 0x0080
|
||||
#define SP_STATUS_SIGNAL1 0x0100
|
||||
#define SP_STATUS_SIGNAL2 0x0200
|
||||
#define SP_STATUS_SIGNAL3 0x0400
|
||||
#define SP_STATUS_SIGNAL4 0x0800
|
||||
#define SP_STATUS_SIGNAL5 0x1000
|
||||
#define SP_STATUS_SIGNAL6 0x2000
|
||||
#define SP_STATUS_SIGNAL7 0x4000
|
||||
|
||||
#define DP_STATUS_XBUS_DMA 0x01
|
||||
#define DP_STATUS_FREEZE 0x02
|
||||
#define DP_STATUS_FLUSH 0x04
|
||||
#define DP_STATUS_START_GCLK 0x008
|
||||
#define DP_STATUS_TMEM_BUSY 0x010
|
||||
#define DP_STATUS_PIPE_BUSY 0x020
|
||||
#define DP_STATUS_CMD_BUSY 0x040
|
||||
#define DP_STATUS_CBUF_READY 0x080
|
||||
#define DP_STATUS_DMA_BUSY 0x100
|
||||
#define DP_STATUS_END_VALID 0x200
|
||||
#define DP_STATUS_START_VALID 0x400
|
||||
|
||||
#define R4300i_SP_Intr 1
|
||||
|
||||
|
||||
#define LSB_FIRST 1 // TODO : check for platform
|
||||
#ifdef LSB_FIRST
|
||||
#define BYTE_ADDR_XOR 3
|
||||
#define WORD_ADDR_XOR 1
|
||||
#define BYTE4_XOR_BE(a) ((a) ^ 3) /* read/write a byte to a 32-bit space */
|
||||
#else
|
||||
#define BYTE_ADDR_XOR 0
|
||||
#define WORD_ADDR_XOR 0
|
||||
#define BYTE4_XOR_BE(a) (a)
|
||||
#endif
|
||||
|
||||
|
||||
typedef uint64_t UINT64;
|
||||
typedef int64_t INT64;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int32_t INT32;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int16_t INT16;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int8_t INT8;
|
||||
typedef unsigned int offs_t;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue