Added mupen64plus-video-z64

This commit is contained in:
null_ptr 2014-07-09 23:40:12 +00:00
parent 8d0cfc60dc
commit b54fb9e6a6
27 changed files with 9032 additions and 0 deletions

View File

@ -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

View File

@ -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.

View File

@ -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>

View File

@ -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

View File

@ -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];
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -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();
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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: *; };

View File

@ -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