mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-23 09:00:24 +02:00
Integrate separately licensed D3D8 reconstruction source
This commit is contained in:
1 parent
078091c41d
commit
ea84554a0a
73 files changed
+29937
-27
No files matched your search
+32
-27
@@ -1197,36 +1197,41 @@
|
||||
{
|
||||
"name": "d3d8",
|
||||
"guid": "{A324F36C-F636-4B5F-B71E-132A221DBB16}",
|
||||
"options": {
|
||||
"cflags": [ "/O2", "/Gy" ],
|
||||
"include_dirs": [ "build/generated/d3d8", "xbox/include" ],
|
||||
"defines": [ "_XBOX", "xbox" ]
|
||||
},
|
||||
"objects": [
|
||||
{ "name": "libs/d3d8/precomp.c", "index": 4, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/block.c", "index": 533, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/buffer.c", "index": 534, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/clear.c", "index": 535, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/combiner.c", "index": 536, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/d3dbase.c", "index": 537, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/d3ddev.c", "index": 538, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/drawprim.c", "index": 539, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/dxgcreate.c", "index": 540, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/enum.c", "index": 541, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/floatmath.c", "index": 542, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/block.cpp", "index": 533, "status": "NonMatching", "options": { "cflags": [ "/O1", "/Oi", "/Gy" ] } },
|
||||
{ "name": "libs/d3d8/buffer.cpp", "index": 534, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/clear.cpp", "index": 535, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/combiner.cpp", "index": 536, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/d3dbase.cpp", "index": 537, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/d3ddev.cpp", "index": 538, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/drawprim.cpp", "index": 539, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/dxgcreate.cpp", "index": 540, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/enum.cpp", "index": 541, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/floatmath.cpp", "index": 542, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/globals.c", "index": 543, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/lazy.c", "index": 544, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/math.c", "index": 545, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/memory.c", "index": 546, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/mpcore.c", "index": 547, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/mpdac.c", "index": 548, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/mphal.c", "index": 549, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/mpintr.c", "index": 550, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/mpmode.c", "index": 551, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/pixeljar.c", "index": 552, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/present.c", "index": 553, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/pshader.c", "index": 554, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/pusher.c", "index": 555, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/resource.c", "index": 556, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/state.c", "index": 557, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/surface.c", "index": 558, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/texture.c", "index": 559, "status": "MISSING" },
|
||||
{ "name": "libs/d3d8/vshader.c", "index": 560, "status": "MISSING" }
|
||||
{ "name": "libs/d3d8/lazy.cpp", "index": 544, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/math.cpp", "index": 545, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/memory.cpp", "index": 546, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/mpcore.cpp", "index": 547, "status": "NonMatching", "options": { "cflags": [ "/O1", "/Oi", "/Gy" ] } },
|
||||
{ "name": "libs/d3d8/mpdac.cpp", "index": 548, "status": "NonMatching", "options": { "cflags": [ "/O1", "/Gy" ] } },
|
||||
{ "name": "libs/d3d8/mphal.cpp", "index": 549, "status": "NonMatching", "options": { "cflags": [ "/O1", "/Gy" ] } },
|
||||
{ "name": "libs/d3d8/mpintr.cpp", "index": 550, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/mpmode.cpp", "index": 551, "status": "NonMatching", "options": { "cflags": [ "/O1", "/Gy" ] } },
|
||||
{ "name": "libs/d3d8/pixeljar.cpp", "index": 552, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/present.cpp", "index": 553, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/pshader.cpp", "index": 554, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/pusher.cpp", "index": 555, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/resource.cpp", "index": 556, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/state.cpp", "index": 557, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/surface.cpp", "index": 558, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/texture.cpp", "index": 559, "status": "NonMatching" },
|
||||
{ "name": "libs/d3d8/vshader.cpp", "index": 560, "status": "NonMatching" }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ from tools.project_x86 import (
|
||||
is_windows,
|
||||
)
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
# arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
@@ -142,6 +144,12 @@ for build_project in build_config["projects"]:
|
||||
# build file generation
|
||||
|
||||
if args.mode == "configure":
|
||||
if any(
|
||||
obj["status"] != "MISSING" and obj["name"].startswith("libs/d3d8/")
|
||||
for project in build_config["projects"]
|
||||
for obj in project["objects"]
|
||||
):
|
||||
subprocess.run([sys.executable, "libs/d3d8/generate_sdk_overlay.py"], check=True)
|
||||
# Write build.ninja and objdiff.json
|
||||
generate_build(sln)
|
||||
elif args.mode == "progress":
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# D3D8 continuation 010 intake (2026-09-23)
|
||||
|
||||
## Scope and license
|
||||
|
||||
Source archive: `d3d8_continuation_010_full.zip`, SHA-256
|
||||
`4a3595e5bf7ab82e489960013159258ed1e8eaa24673dc6222ac83f30aab5724`.
|
||||
The source was reviewed outside the canonical checkout. Its 2,839 payload
|
||||
checksums all passed `VERIFY_HANDOFF.py`; the original archive was not edited.
|
||||
|
||||
The 27 C++ translation units and accompanying headers live in
|
||||
`libs/d3d8/`, a **separately GPL-3.0-or-later licensed subtree**. The
|
||||
repository-root CC0 notice does not relicense this code. `LICENSE.GPL-3.0`,
|
||||
`PROVENANCE.md`, the source-reference notes, and the necessary source-level
|
||||
research evidence are retained in the subtree. No EXE, XBE, PDB, compiler,
|
||||
SDK archive, generated object, or original game asset is published. The
|
||||
remaining `precomp` and `globals` objects stay `MISSING`.
|
||||
|
||||
## Independent reproduction and scoring
|
||||
|
||||
All 29 archived target objects were checked against the canonical target
|
||||
objects. Their only byte differences were the two path-separator bytes in
|
||||
COFF auxiliary FILE metadata, not code. The archive's saved candidate
|
||||
objects and a fresh native VC7 build of all 27 TUs agree on **606/606 code
|
||||
sections** under the unchanged COFF code-and-relocation comparator. The
|
||||
source file comments were subsequently adjusted only to point to provenance
|
||||
files in this subtree.
|
||||
|
||||
The archive itself reports **356 raw/named-pair comparator passes / 45,107
|
||||
padded bytes** (347 same-name plus nine authenticated entry-name pairs).
|
||||
Its separately verified combiner view adds **24 PDB-identity-and-original-image
|
||||
proofs / 4,000 padded bytes**. The latter are *not* raw comparator or
|
||||
canonical matching credit. Independent `verify_wave10_combiner.py` passed
|
||||
30 combiner sections and 396 negative controls. No archive count has been
|
||||
copied into the canonical ledger by fiat.
|
||||
|
||||
After canonical configuration and a full build, the canonical board credits
|
||||
**354 D3D8 functions / 43,039 meaningful code bytes of 73,886**. These are
|
||||
canonical scoring units, not directly comparable to the archive's padded
|
||||
totals. Data credit is 40 of 19,620 bytes; **zero of 29 objects** is marked
|
||||
whole-object matching. All 27 compiled objects remain `NonMatching`. Halo-owned
|
||||
code remained at 1,524,233 of 1,770,166 meaningful bytes; the integration
|
||||
introduces no Halo-owned exact-function regression.
|
||||
|
||||
The archive's end-to-end replay is not presently clean: its patch verifier
|
||||
compares an 008-to-009 patch against 010 source, and its final verifier expects
|
||||
old report field names (`name` rather than `symbol`). The archive also omitted
|
||||
three final evidence outputs. These defects were not bypassed to claim a clean
|
||||
14-stage replay. Checksum, direct native compilation, section comparison,
|
||||
combiner proof, canonical build, and canonical regression checks were run
|
||||
independently as described above.
|
||||
|
||||
## Build integration and limits
|
||||
|
||||
`config/config.json` enables the 27 TUs and retains `precomp` and `globals`
|
||||
as missing. Five TU-specific `/O1` and `/Oi` combinations are measured
|
||||
output hypotheses, not claimed original commands. `configure.py` generates
|
||||
an ignored SDK overlay from the user's existing SDK header; the overlay
|
||||
script checks the SDK SHA-256 and applies five declaration/wrapper edits.
|
||||
The original SDK is neither modified nor committed.
|
||||
|
||||
Full `ninja` passed for 833 units. The stable function diff against the
|
||||
pre-intake snapshot lost **zero** previously exact Halo functions. The park
|
||||
check found 124 active, zero stale, zero invalid entries. The tools test suite
|
||||
reported **1,152 passed, five skipped, 26 subtests**. `git diff --check`
|
||||
passed. The only fake-match scan leads are two inherited, disclosed inline
|
||||
assembly sites (PixelJar BSF and pusher SFENCE); neither was added for this
|
||||
intake. No new address-shaped `code_` or `bss_` names were found.
|
||||
|
||||
This source is reconstruction evidence, not a certified functional graphics
|
||||
driver. In particular, the target-authenticated `resource.cpp` private-data
|
||||
loop can fail to advance on a nonmatching head; `combiner.cpp` deliberately
|
||||
keeps a bounded, nonexact alpha-premodulate implementation instead of
|
||||
reproducing an out-of-bounds target access. Such nonexact work receives zero
|
||||
matching credit. The nine candidate private-symbol renames remain in the
|
||||
research evidence rather than being silently applied to `symbols.json`.
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. 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
|
||||
them 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 prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. 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.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
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
|
||||
state 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program 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, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU 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. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,46 @@
|
||||
# RXDK source-reference provenance — D3D8 20k checkpoint
|
||||
|
||||
The source reconstruction consulted and adapted Team Resurgent's RXDK-Libs
|
||||
(2026), under GPL-3.0-or-later, pinned at:
|
||||
|
||||
29e018674a3443f9df5b5cb4478bb9c54d8a2a3a
|
||||
|
||||
Inspected paths in that repository, all under `libs/libd3d8/se/`:
|
||||
`pixeljar.cpp`, `pixeljar.hpp`, `state.cpp`, `resource.cpp`, `vshader.cpp`,
|
||||
`pshader.cpp`, `enum.cpp`, and `d3dbase.cpp`.
|
||||
|
||||
Repository source URL:
|
||||
https://github.com/Team-Resurgent/RXDK-Libs/tree/29e018674a3443f9df5b5cb4478bb9c54d8a2a3a/libs/libd3d8/se
|
||||
|
||||
The license text is retained as `libs/d3d8/LICENSE.GPL-3.0`. Adapted production files retain
|
||||
source attribution. This packet is not asserted to be an independent clean-room
|
||||
reconstruction, and the older Halo repository's CC0 notice must not be treated
|
||||
as relicensing these adaptations. Third-party reference text was read through the authorized GitHub
|
||||
connector, not from a later local binary substituted for the January target.
|
||||
|
||||
The user-supplied January Halo EXE/PDB, pinned split configuration, instructions,
|
||||
data references, and ABI are the authority for target behavior. The RXDK revision
|
||||
is later and differs in layouts and behavior: APIs, sizes, flags and field owners
|
||||
were reconciled against the target. Agreement with reference source alone never
|
||||
awards code credit. Build flags remain a hypothesis until original commands are
|
||||
recovered; exactness here is measured output, not a claimed recovered build recipe.
|
||||
|
||||
Only the authored/adapted source and reviewable tooling patches are included
|
||||
in this repository. User-supplied EXE, XBE, PDB, compiler and SDK archives are
|
||||
not included.
|
||||
|
||||
|
||||
## Continuation 005 additions
|
||||
|
||||
The same pinned RXDK revision was additionally consulted/adapted for
|
||||
`mphal.cpp` (graphics-context bank layout, 3D initialization and PLL sequencing)
|
||||
and `mpcore.cpp` (shutdown drain order and tile creation/destruction).
|
||||
Relevant Git blob IDs: mphal `9b5ffa9697cf38d8cd0e77dc2be8332aaa6b230d`,
|
||||
mpcore `fbc477fe8f299ad60fa1f7ec2094be14a2b2ec49`.
|
||||
The generated context-bank names/counts are additionally documented by the
|
||||
January target write sequence in `libs/d3d8/research/wave5/grctx3d_schema.json`.
|
||||
|
||||
Kernel declaration corroboration uses XboxDev/nxdk `lib/xboxkrnl/xboxkrnl.h`
|
||||
at `58427c078b4ccb0121f359b6b6c536b3b2914976`; it is not a replacement SDK.
|
||||
Only the necessary ABI declarations were used. See
|
||||
`libs/d3d8/research/wave5/kernel_import_contracts.json` for declarations and limitations.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Xbox D3D8 reconstruction
|
||||
|
||||
This subtree is separately licensed under **GPL-3.0-or-later**; the
|
||||
repository-root CC0 notice does not relicense it. See
|
||||
`LICENSE.GPL-3.0` and `PROVENANCE.md`. Parts of the source adapt the
|
||||
GPL-licensed RXDK-Libs reference; original Xbox executables, PDBs, SDK
|
||||
archives, and compiler binaries are not included in this subtree.
|
||||
This is decompilation research, not a functional or memory-safe graphics
|
||||
driver. Some target-authenticated behavior includes original defects;
|
||||
nonexact safety corrections are explicitly uncredited.
|
||||
|
||||
The 27 C++ translation units here reconstruct portions of 27 of January's
|
||||
29 D3D8 objects. `precomp` and `globals` remain missing. Each object is
|
||||
intentionally `NonMatching`: exact individual functions do not imply exact
|
||||
owned data, COFF ownership, linking, or a working graphics driver.
|
||||
|
||||
The build uses the repository's existing VC7 and Xbox SDK. Configure
|
||||
generates `build/generated/d3d8/d3d8.h` from the existing SDK header using
|
||||
`generate_sdk_overlay.py`, which makes five PDB-supported declaration and
|
||||
wrapper corrections without editing the original SDK. The five per-object
|
||||
`/O1` and `/Oi` choices in `config/config.json` are output-tested compiler
|
||||
hypotheses, not recovered original build commands.
|
||||
|
||||
The 2026-09-23 intake is documented in
|
||||
`docs/object_matching_logs/d3d8_continuation_010_intake_20260923.md`.
|
||||
@@ -0,0 +1,718 @@
|
||||
/* January state-block reconstruction; target PDB and COFF are authoritative.
|
||||
* Related RXDK block implementation: Copyright (C) 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later. See retained reference provenance. */
|
||||
#include "block_internal.h"
|
||||
#include "vshader_internal.h"
|
||||
#include "memory_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
#pragma const_seg("D3D_RD")
|
||||
extern "C"
|
||||
{
|
||||
BYTE D3D__StateBlockDirty[(D3DSBD_MAX + 3) & ~3];
|
||||
}
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI ClearStateBlockFlags(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
ZeroMemory(D3D__StateBlockDirty, sizeof(D3D__StateBlockDirty));
|
||||
Light *light = device->m_pLights;
|
||||
for (DWORD i = 0; i < device->m_LightCount; ++i, ++light)
|
||||
{
|
||||
light->Flags &= ~(LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_BeginStateBlock(
|
||||
void)
|
||||
{
|
||||
g_pDevice->m_StateFlags |= STATE_RECORDBLOCK;
|
||||
ClearStateBlockFlags();
|
||||
return;
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_Suspend(
|
||||
void)
|
||||
{
|
||||
g_pDevice->SetStateVB(0);
|
||||
return;
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_ApplyStateBlock(
|
||||
DWORD token)
|
||||
{
|
||||
DWORD i;
|
||||
CDevice *device = g_pDevice;
|
||||
StateBlock *block = (StateBlock *)token;
|
||||
DWORD *data = StateBlockData(block);
|
||||
for (i = 0; i < block->D0_Textures; ++i)
|
||||
{
|
||||
device->SetTexture(data[0], (D3DBaseTexture *)data[1]);
|
||||
data += 2;
|
||||
}
|
||||
if (block->D1_PixelShader)
|
||||
{
|
||||
device->SetPixelShader(data[0]);
|
||||
++data;
|
||||
}
|
||||
if (block->D2_VertexShader)
|
||||
{
|
||||
device->SetVertexShader(data[0]);
|
||||
++data;
|
||||
}
|
||||
if (block->D3_Index)
|
||||
{
|
||||
device->SetIndices((D3DIndexBuffer *)data[1], data[0]);
|
||||
data += 2;
|
||||
}
|
||||
for (i = 0; i < block->D4_Streams; ++i)
|
||||
{
|
||||
device->SetStreamSource(data[0], (D3DVertexBuffer *)data[2], data[1]);
|
||||
data += 3;
|
||||
}
|
||||
for (i = 0; i < block->D6_PixelShaderConstants; ++i)
|
||||
{
|
||||
device->SetPixelShaderConstant(data[0], data + 1, 1);
|
||||
data += 5;
|
||||
}
|
||||
for (i = 0; i < block->D7_VertexShaderConstants; ++i)
|
||||
{
|
||||
device->SetVertexShaderConstant(data[0] - 96, data + 1, 1);
|
||||
data += 5;
|
||||
}
|
||||
for (i = 0; i < block->D8_RenderStates; ++i)
|
||||
{
|
||||
DWORD state = data[0];
|
||||
DWORD value = data[1];
|
||||
if (D3D__RenderState[state] != value)
|
||||
{
|
||||
device->SetRenderStateNotInline((D3DRENDERSTATETYPE)state, value);
|
||||
}
|
||||
data += 2;
|
||||
}
|
||||
for (i = 0; i < block->D9_TextureStates; ++i)
|
||||
{
|
||||
DWORD stage = data[0];
|
||||
DWORD state = data[1];
|
||||
DWORD value = data[2];
|
||||
if (D3D__TextureState[stage][state] != value)
|
||||
{
|
||||
device->SetTextureStageStateNotInline(stage, (D3DTEXTURESTAGESTATETYPE)state, value);
|
||||
}
|
||||
data += 3;
|
||||
}
|
||||
for (i = 0; i < block->D10_Transforms; ++i)
|
||||
{
|
||||
device->SetTransform((D3DTRANSFORMSTATETYPE)data[0], (const D3DMATRIX *)(data + 1));
|
||||
data += 1 + sizeof(D3DMATRIX) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D11_Viewport)
|
||||
{
|
||||
device->SetViewport((const D3DVIEWPORT8 *)data);
|
||||
data += sizeof(D3DVIEWPORT8) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D12_Material)
|
||||
{
|
||||
device->SetMaterial((const D3DMATERIAL8 *)data);
|
||||
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D13_BackMaterial)
|
||||
{
|
||||
device->SetBackMaterial((const D3DMATERIAL8 *)data);
|
||||
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
||||
}
|
||||
for (i = 0; i < block->D14_Lights; ++i)
|
||||
{
|
||||
device->SetLight(data[0], (const D3DLIGHT8 *)(data + 1));
|
||||
data += 1 + sizeof(D3DLIGHT8) / sizeof(DWORD);
|
||||
}
|
||||
for (i = 0; i < block->D15_LightEnables; ++i)
|
||||
{
|
||||
device->LightEnable(data[0], data[1]);
|
||||
data += 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_DeleteStateBlock(
|
||||
DWORD token)
|
||||
{
|
||||
DWORD i;
|
||||
StateBlock *block = (StateBlock *)token;
|
||||
DWORD *data = StateBlockData(block);
|
||||
for (i = 0; i < block->D0_Textures; ++i)
|
||||
{
|
||||
D3DBaseTexture *texture = (D3DBaseTexture *)data[1];
|
||||
data += 2;
|
||||
if (texture != NULL)
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
}
|
||||
if (block->D1_PixelShader)
|
||||
{
|
||||
DWORD handle = *data++;
|
||||
if (handle != 0)
|
||||
{
|
||||
D3DDevice::DeletePixelShader(handle);
|
||||
}
|
||||
}
|
||||
if (block->D2_VertexShader)
|
||||
{
|
||||
DWORD handle = *data++;
|
||||
if (handle & D3DFVF_RESERVED0)
|
||||
{
|
||||
D3DDevice::DeleteVertexShader(handle);
|
||||
}
|
||||
}
|
||||
if (block->D3_Index)
|
||||
{
|
||||
D3DIndexBuffer *indexBuffer = (D3DIndexBuffer *)data[1];
|
||||
data += 2;
|
||||
if (indexBuffer != NULL)
|
||||
{
|
||||
indexBuffer->Release();
|
||||
}
|
||||
}
|
||||
for (i = 0; i < block->D4_Streams; ++i)
|
||||
{
|
||||
D3DVertexBuffer *vertexBuffer = (D3DVertexBuffer *)data[2];
|
||||
data += 3;
|
||||
if (vertexBuffer != NULL)
|
||||
{
|
||||
vertexBuffer->Release();
|
||||
}
|
||||
}
|
||||
LocalFree(block);
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" void WINAPI D3DDevice_CaptureStateBlock(
|
||||
DWORD token)
|
||||
{
|
||||
DWORD i;
|
||||
CDevice *device = g_pDevice;
|
||||
StateBlock *block = (StateBlock *)token;
|
||||
DWORD *data = StateBlockData(block);
|
||||
for (i = 0; i < block->D0_Textures; ++i)
|
||||
{
|
||||
DWORD stage = data[0];
|
||||
D3DBaseTexture *texture = (D3DBaseTexture *)data[1];
|
||||
if (texture) texture->Release();
|
||||
texture = device->m_Textures[stage];
|
||||
if (texture) texture->AddRef();
|
||||
data[1] = (DWORD)texture;
|
||||
data += 2;
|
||||
}
|
||||
if (block->D1_PixelShader)
|
||||
{
|
||||
DWORD handle = data[0];
|
||||
if (handle) device->DeletePixelShader(handle);
|
||||
handle = (DWORD)device->m_pPixelShader;
|
||||
if (handle) ++device->m_pPixelShader->RefCount;
|
||||
data[0] = handle;
|
||||
++data;
|
||||
}
|
||||
if (block->D2_VertexShader)
|
||||
{
|
||||
DWORD handle = data[0];
|
||||
if (handle & D3DFVF_RESERVED0) device->DeleteVertexShader(handle);
|
||||
handle = device->m_VertexShaderHandle;
|
||||
if (handle & D3DFVF_RESERVED0) ++device->m_pVertexShader->RefCount;
|
||||
data[0] = handle;
|
||||
++data;
|
||||
}
|
||||
if (block->D3_Index)
|
||||
{
|
||||
D3DIndexBuffer *indexBuffer = (D3DIndexBuffer *)data[1];
|
||||
if (indexBuffer) indexBuffer->Release();
|
||||
indexBuffer = device->m_pIndexBuffer;
|
||||
if (indexBuffer) indexBuffer->AddRef();
|
||||
data[0] = device->m_IndexBase;
|
||||
data[1] = (DWORD)indexBuffer;
|
||||
data += 2;
|
||||
}
|
||||
for (i = 0; i < block->D4_Streams; ++i)
|
||||
{
|
||||
DWORD index = data[0];
|
||||
D3DVertexBuffer *vertexBuffer = (D3DVertexBuffer *)data[2];
|
||||
if (vertexBuffer) vertexBuffer->Release();
|
||||
vertexBuffer = g_Stream[index].pVertexBuffer;
|
||||
if (vertexBuffer) vertexBuffer->AddRef();
|
||||
data[1] = g_Stream[index].Stride;
|
||||
data[2] = (DWORD)vertexBuffer;
|
||||
data += 3;
|
||||
}
|
||||
for (i = 0; i < block->D6_PixelShaderConstants; ++i)
|
||||
{
|
||||
DWORD index = data[0];
|
||||
void *constantData = data + 1;
|
||||
memcpy(constantData, device->m_PixelShaderConstants[index], 4 * sizeof(FLOAT));
|
||||
data += 5;
|
||||
}
|
||||
for (i = 0; i < block->D7_VertexShaderConstants; ++i)
|
||||
{
|
||||
DWORD index = data[0];
|
||||
void *constantData = data + 1;
|
||||
memcpy(constantData, device->m_VertexShaderConstants[index], 4 * sizeof(FLOAT));
|
||||
data += 5;
|
||||
}
|
||||
for (i = 0; i < block->D8_RenderStates; ++i)
|
||||
{
|
||||
DWORD state = data[0];
|
||||
data[1] = D3D__RenderState[state];
|
||||
data += 2;
|
||||
}
|
||||
for (i = 0; i < block->D9_TextureStates; ++i)
|
||||
{
|
||||
DWORD stage = data[0];
|
||||
DWORD state = data[1];
|
||||
data[2] = D3D__TextureState[stage][state];
|
||||
data += 3;
|
||||
}
|
||||
for (i = 0; i < block->D10_Transforms; ++i)
|
||||
{
|
||||
DWORD state = data[0];
|
||||
memcpy((void *)(data + 1), &device->m_Transform[state], sizeof(device->m_Transform[state]));
|
||||
data += 1 + sizeof(D3DMATRIX) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D11_Viewport)
|
||||
{
|
||||
memcpy(data, &device->m_Viewport, sizeof(D3DVIEWPORT8));
|
||||
data += sizeof(D3DVIEWPORT8) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D12_Material)
|
||||
{
|
||||
memcpy(data, &device->m_Material, sizeof(D3DMATERIAL8));
|
||||
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
||||
}
|
||||
if (block->D13_BackMaterial)
|
||||
{
|
||||
memcpy(data, &device->m_BackMaterial, sizeof(D3DMATERIAL8));
|
||||
data += sizeof(D3DMATERIAL8) / sizeof(DWORD);
|
||||
}
|
||||
for (i = 0; i < block->D14_Lights; ++i)
|
||||
{
|
||||
DWORD index = data[0];
|
||||
memcpy(data + 1, &device->m_pLights[index].Light8, sizeof(D3DLIGHT8));
|
||||
data += 1 + sizeof(D3DLIGHT8) / sizeof(DWORD);
|
||||
}
|
||||
for (i = 0; i < block->D15_LightEnables; ++i)
|
||||
{
|
||||
device->GetLightEnable(data[0], (BOOL *)(data + 1));
|
||||
data += 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cursor is a byte count during sizing and an allocated address during writing.
|
||||
* Using ULONG_PTR avoids the historical NULL-based member/pointer arithmetic.
|
||||
* Each conversion to a writable record occurs only after allocation succeeded.
|
||||
* The dirty set and device state must not change concurrently between passes. */
|
||||
HRESULT WINAPI RecordStateBlock(
|
||||
DWORD *token)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD j;
|
||||
BYTE *dirty;
|
||||
StateBlock *block = NULL;
|
||||
ULONG_PTR cursor = offsetof(StateBlock, Data);
|
||||
CDevice *device = g_pDevice;
|
||||
Light *lights = device->m_pLights;
|
||||
*token = 0;
|
||||
for (;;)
|
||||
{
|
||||
dirty = D3D__StateBlockDirty;
|
||||
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
||||
{
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
D3DBaseTexture *texture = device->m_Textures[i];
|
||||
++block->D0_Textures;
|
||||
data[0] = i;
|
||||
data[1] = (DWORD)texture;
|
||||
if (texture) texture->AddRef();
|
||||
}
|
||||
cursor += 2 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
PixelShader *shader = device->m_pPixelShader;
|
||||
block->D1_PixelShader = TRUE;
|
||||
*(DWORD *)cursor = (DWORD)shader;
|
||||
if (shader) ++shader->RefCount;
|
||||
}
|
||||
cursor += sizeof(DWORD);
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD handle = device->m_VertexShaderHandle;
|
||||
block->D2_VertexShader = TRUE;
|
||||
*(DWORD *)cursor = handle;
|
||||
if (handle & D3DFVF_RESERVED0) ++device->m_pVertexShader->RefCount;
|
||||
}
|
||||
cursor += sizeof(DWORD);
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
D3DIndexBuffer *indexBuffer = device->m_pIndexBuffer;
|
||||
block->D3_Index = TRUE;
|
||||
data[0] = device->m_IndexBase;
|
||||
data[1] = (DWORD)indexBuffer;
|
||||
if (indexBuffer) indexBuffer->AddRef();
|
||||
}
|
||||
cursor += 2 * sizeof(DWORD);
|
||||
}
|
||||
for (i = 0; i < D3DVS_STREAMS_MAX_V1_0; ++i)
|
||||
{
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
D3DVertexBuffer *vertexBuffer = g_Stream[i].pVertexBuffer;
|
||||
++block->D4_Streams;
|
||||
data[0] = i;
|
||||
data[1] = g_Stream[i].Stride;
|
||||
data[2] = (DWORD)vertexBuffer;
|
||||
if (vertexBuffer) vertexBuffer->AddRef();
|
||||
}
|
||||
cursor += 3 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < D3DPS_CONSTREG_MAX_DX8; ++i)
|
||||
{
|
||||
if (*dirty++ && device->m_pPixelShader)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D6_PixelShaderConstants;
|
||||
data[0] = i;
|
||||
memcpy(data + 1, device->m_PixelShaderConstants[i], 4 * sizeof(FLOAT));
|
||||
}
|
||||
cursor += 5 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < D3DVS_CONSTREG_COUNT_XBOX; ++i)
|
||||
{
|
||||
if (*dirty++ && i >= 96)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D7_VertexShaderConstants;
|
||||
data[0] = i;
|
||||
memcpy(data + 1, device->m_VertexShaderConstants[i], 4 * sizeof(FLOAT));
|
||||
}
|
||||
cursor += 5 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < D3DRS_MAX; ++i)
|
||||
{
|
||||
if (*dirty++)
|
||||
{
|
||||
if (device->m_pPixelShader || i < D3DRS_PSALPHAINPUTS0 ||
|
||||
(i > D3DRS_PSINPUTTEXTURE && i != D3DRS_PSTEXTUREMODES))
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D8_RenderStates;
|
||||
data[0] = i;
|
||||
data[1] = D3D__RenderState[i];
|
||||
}
|
||||
cursor += 2 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < D3DTSS_MAX; ++j)
|
||||
{
|
||||
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
||||
{
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D9_TextureStates;
|
||||
data[0] = i;
|
||||
data[1] = j;
|
||||
data[2] = D3D__TextureState[i][j];
|
||||
}
|
||||
cursor += 3 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < D3DTS_MAX; ++i)
|
||||
{
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D10_Transforms;
|
||||
data[0] = i;
|
||||
memcpy(data + 1, &device->m_Transform[i], sizeof(D3DMATRIX));
|
||||
}
|
||||
cursor += sizeof(DWORD) + sizeof(D3DMATRIX);
|
||||
}
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
block->D11_Viewport = TRUE;
|
||||
memcpy((void *)cursor, &device->m_Viewport, sizeof(D3DVIEWPORT8));
|
||||
}
|
||||
cursor += sizeof(D3DVIEWPORT8);
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
block->D12_Material = TRUE;
|
||||
memcpy((void *)cursor, &device->m_Material, sizeof(D3DMATERIAL8));
|
||||
}
|
||||
cursor += sizeof(D3DMATERIAL8);
|
||||
}
|
||||
if (*dirty++)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
block->D13_BackMaterial = TRUE;
|
||||
memcpy((void *)cursor, &device->m_BackMaterial, sizeof(D3DMATERIAL8));
|
||||
}
|
||||
cursor += sizeof(D3DMATERIAL8);
|
||||
}
|
||||
for (i = 0; i < device->m_LightCount; ++i)
|
||||
{
|
||||
if (lights[i].Flags & LIGHT_STATEBLOCK_SET)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D14_Lights;
|
||||
data[0] = i;
|
||||
/* Original record path copies Light8 from the first light,
|
||||
* whereas CaptureStateBlock uses the indexed light. Preserve
|
||||
* this observed distinction; do not call it a corrected API. */
|
||||
memcpy(data + 1, &lights->Light8, sizeof(D3DLIGHT8));
|
||||
}
|
||||
cursor += sizeof(DWORD) + sizeof(D3DLIGHT8);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < device->m_LightCount; ++i)
|
||||
{
|
||||
if (lights[i].Flags & LIGHT_STATEBLOCK_ENABLED)
|
||||
{
|
||||
if (block)
|
||||
{
|
||||
DWORD *data = (DWORD *)cursor;
|
||||
++block->D15_LightEnables;
|
||||
data[0] = i;
|
||||
device->GetLightEnable(i, (BOOL *)(data + 1));
|
||||
}
|
||||
cursor += 2 * sizeof(DWORD);
|
||||
}
|
||||
}
|
||||
if (block)
|
||||
{
|
||||
*token = (DWORD)block;
|
||||
return S_OK;
|
||||
}
|
||||
block = (StateBlock *)LocalAlloc(LMEM_FIXED, cursor);
|
||||
if (!block) return E_OUTOFMEMORY;
|
||||
ZeroMemory(block, offsetof(StateBlock, Data));
|
||||
cursor = (ULONG_PTR)StateBlockData(block);
|
||||
}
|
||||
}
|
||||
|
||||
const BYTE g_PixelRenderStates[] =
|
||||
{
|
||||
D3DRS_ZENABLE,
|
||||
D3DRS_FILLMODE,
|
||||
D3DRS_SHADEMODE,
|
||||
D3DRS_ZWRITEENABLE,
|
||||
D3DRS_ALPHATESTENABLE,
|
||||
D3DRS_SRCBLEND,
|
||||
D3DRS_DESTBLEND,
|
||||
D3DRS_ZFUNC,
|
||||
D3DRS_ALPHAREF,
|
||||
D3DRS_ALPHAFUNC,
|
||||
D3DRS_DITHERENABLE,
|
||||
D3DRS_FOGSTART,
|
||||
D3DRS_FOGEND,
|
||||
D3DRS_FOGDENSITY,
|
||||
D3DRS_EDGEANTIALIAS,
|
||||
D3DRS_ALPHABLENDENABLE,
|
||||
D3DRS_ZBIAS,
|
||||
D3DRS_STENCILENABLE,
|
||||
D3DRS_STENCILFAIL,
|
||||
D3DRS_STENCILZFAIL,
|
||||
D3DRS_STENCILPASS,
|
||||
D3DRS_STENCILFUNC,
|
||||
D3DRS_STENCILREF,
|
||||
D3DRS_STENCILMASK,
|
||||
D3DRS_STENCILWRITEMASK,
|
||||
D3DRS_TEXTUREFACTOR,
|
||||
D3DRS_WRAP0,
|
||||
D3DRS_WRAP1,
|
||||
D3DRS_WRAP2,
|
||||
D3DRS_WRAP3,
|
||||
D3DRS_COLORWRITEENABLE,
|
||||
D3DRS_BLENDOP,
|
||||
};
|
||||
|
||||
const BYTE g_PixelTextureStates[] =
|
||||
{
|
||||
D3DTSS_COLOROP,
|
||||
D3DTSS_COLORARG1,
|
||||
D3DTSS_COLORARG2,
|
||||
D3DTSS_ALPHAOP,
|
||||
D3DTSS_ALPHAARG1,
|
||||
D3DTSS_ALPHAARG2,
|
||||
D3DTSS_BUMPENVMAT00,
|
||||
D3DTSS_BUMPENVMAT01,
|
||||
D3DTSS_BUMPENVMAT10,
|
||||
D3DTSS_BUMPENVMAT11,
|
||||
D3DTSS_TEXCOORDINDEX,
|
||||
D3DTSS_ADDRESSU,
|
||||
D3DTSS_ADDRESSV,
|
||||
D3DTSS_BORDERCOLOR,
|
||||
D3DTSS_MAGFILTER,
|
||||
D3DTSS_MINFILTER,
|
||||
D3DTSS_MIPFILTER,
|
||||
D3DTSS_MIPMAPLODBIAS,
|
||||
D3DTSS_MAXMIPLEVEL,
|
||||
D3DTSS_MAXANISOTROPY,
|
||||
D3DTSS_BUMPENVLSCALE,
|
||||
D3DTSS_BUMPENVLOFFSET,
|
||||
D3DTSS_TEXTURETRANSFORMFLAGS,
|
||||
D3DTSS_ADDRESSW,
|
||||
D3DTSS_COLORARG0,
|
||||
D3DTSS_ALPHAARG0,
|
||||
D3DTSS_RESULTARG,
|
||||
};
|
||||
|
||||
const BYTE g_VertexRenderStates[] =
|
||||
{
|
||||
D3DRS_SHADEMODE,
|
||||
D3DRS_SPECULARENABLE,
|
||||
D3DRS_CULLMODE,
|
||||
D3DRS_FOGENABLE,
|
||||
D3DRS_FOGCOLOR,
|
||||
D3DRS_FOGTABLEMODE,
|
||||
D3DRS_FOGSTART,
|
||||
D3DRS_FOGEND,
|
||||
D3DRS_FOGDENSITY,
|
||||
D3DRS_RANGEFOGENABLE,
|
||||
D3DRS_AMBIENT,
|
||||
D3DRS_COLORVERTEX,
|
||||
D3DRS_LIGHTING,
|
||||
D3DRS_NORMALIZENORMALS,
|
||||
D3DRS_LOCALVIEWER,
|
||||
D3DRS_EMISSIVEMATERIALSOURCE,
|
||||
D3DRS_AMBIENTMATERIALSOURCE,
|
||||
D3DRS_DIFFUSEMATERIALSOURCE,
|
||||
D3DRS_SPECULARMATERIALSOURCE,
|
||||
D3DRS_VERTEXBLEND,
|
||||
D3DRS_POINTSIZE,
|
||||
D3DRS_POINTSIZE_MIN,
|
||||
D3DRS_POINTSPRITEENABLE,
|
||||
D3DRS_POINTSCALEENABLE,
|
||||
D3DRS_POINTSCALE_A,
|
||||
D3DRS_POINTSCALE_B,
|
||||
D3DRS_POINTSCALE_C,
|
||||
D3DRS_MULTISAMPLEANTIALIAS,
|
||||
D3DRS_MULTISAMPLEMASK,
|
||||
D3DRS_PATCHEDGESTYLE,
|
||||
D3DRS_PATCHSEGMENTS,
|
||||
D3DRS_POINTSIZE_MAX,
|
||||
};
|
||||
|
||||
const BYTE g_VertexTextureStates[] =
|
||||
{
|
||||
D3DTSS_TEXCOORDINDEX,
|
||||
D3DTSS_TEXTURETRANSFORMFLAGS,
|
||||
};
|
||||
|
||||
extern "C" HRESULT WINAPI D3DDevice_CreateStateBlock(
|
||||
D3DSTATEBLOCKTYPE type,
|
||||
DWORD *token)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD j;
|
||||
CDevice *device = g_pDevice;
|
||||
if (type == D3DSBT_ALL)
|
||||
{
|
||||
memset(D3D__StateBlockDirty, 0xff, sizeof(D3D__StateBlockDirty));
|
||||
Light *lights = device->m_pLights;
|
||||
for (i = 0; i < device->m_LightCount; ++i)
|
||||
{
|
||||
if (lights[i].Flags & LIGHT_SET)
|
||||
lights[i].Flags |= LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearStateBlockFlags();
|
||||
if (type == D3DSBT_PIXELSTATE)
|
||||
{
|
||||
D3D__StateBlockDirty[D3DSBD_PIXELSHADER] = TRUE;
|
||||
memset(D3D__StateBlockDirty + D3DSBD_PIXELSHADERCONSTANTS, 0xff, D3DPS_CONSTREG_MAX_DX8);
|
||||
for (i = 0; i < sizeof(g_PixelRenderStates); ++i)
|
||||
D3D__StateBlockDirty[D3DSBD_RENDERSTATES + g_PixelRenderStates[i]] = TRUE;
|
||||
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
||||
for (j = 0; j < sizeof(g_PixelTextureStates); ++j)
|
||||
D3D__StateBlockDirty[D3DSBD_TEXTURESTATES + g_PixelTextureStates[j] * D3DTSS_MAXSTAGES + i] = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D__StateBlockDirty[D3DSBD_VERTEXSHADER] = TRUE;
|
||||
memset(D3D__StateBlockDirty + D3DSBD_VERTEXSHADERCONSTANTS, 0xff, D3DVS_CONSTREG_COUNT_XBOX);
|
||||
for (i = 0; i < sizeof(g_VertexRenderStates); ++i)
|
||||
D3D__StateBlockDirty[D3DSBD_RENDERSTATES + g_VertexRenderStates[i]] = TRUE;
|
||||
for (i = 0; i < D3DTSS_MAXSTAGES; ++i)
|
||||
for (j = 0; j < sizeof(g_VertexTextureStates); ++j)
|
||||
D3D__StateBlockDirty[D3DSBD_TEXTURESTATES + g_VertexTextureStates[j] * D3DTSS_MAXSTAGES + i] = TRUE;
|
||||
Light *lights = device->m_pLights;
|
||||
for (i = 0; i < device->m_LightCount; ++i)
|
||||
{
|
||||
if (lights[i].Flags & LIGHT_SET)
|
||||
lights[i].Flags |= LIGHT_STATEBLOCK_SET | LIGHT_STATEBLOCK_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RecordStateBlock(token);
|
||||
}
|
||||
extern "C" HRESULT WINAPI D3DDevice_EndStateBlock(
|
||||
DWORD *token)
|
||||
{
|
||||
g_pDevice->m_StateFlags &= ~STATE_RECORDBLOCK;
|
||||
return RecordStateBlock(token);
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_Resume(
|
||||
BOOL reset)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
/* The original Resume path assumes state-block allocation succeeds.
|
||||
* This is not a checked recovery path for allocation failure. */
|
||||
DWORD token;
|
||||
D3DDevice_CreateStateBlock(D3DSBT_ALL, &token);
|
||||
D3DDevice_ApplyStateBlock(token);
|
||||
D3DDevice_DeleteStateBlock(token);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/* State-block record layout from the January PDB (StateBlock, 0x40 bytes).
|
||||
* Serialized records follow the 0x3c-byte counter header in one allocation. */
|
||||
#ifndef D3D8_BLOCK_INTERNAL_H
|
||||
#define D3D8_BLOCK_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
enum StateBlockFlags
|
||||
{
|
||||
STATE_RECORDBLOCK = 0x20,
|
||||
LIGHT_SET = 1,
|
||||
LIGHT_STATEBLOCK_SET = 2,
|
||||
LIGHT_STATEBLOCK_ENABLED = 4
|
||||
};
|
||||
struct StateBlock
|
||||
{
|
||||
DWORD D0_Textures;
|
||||
BOOL D1_PixelShader;
|
||||
BOOL D2_VertexShader;
|
||||
BOOL D3_Index;
|
||||
DWORD D4_Streams;
|
||||
DWORD D6_PixelShaderConstants;
|
||||
DWORD D7_VertexShaderConstants;
|
||||
DWORD D8_RenderStates;
|
||||
DWORD D9_TextureStates;
|
||||
DWORD D10_Transforms;
|
||||
BOOL D11_Viewport;
|
||||
BOOL D12_Material;
|
||||
BOOL D13_BackMaterial;
|
||||
DWORD D14_Lights;
|
||||
DWORD D15_LightEnables;
|
||||
DWORD Data[1];
|
||||
};
|
||||
typedef char StateBlock_size_check[sizeof(StateBlock) == 0x40 ? 1 : -1];
|
||||
typedef char StateBlock_data_check[offsetof(StateBlock, Data) == 0x3c ? 1 : -1];
|
||||
typedef char StateBlock_D0_Textures_offset[offsetof(StateBlock, D0_Textures) == 0 ? 1 : -1];
|
||||
typedef char StateBlock_D1_PixelShader_offset[offsetof(StateBlock, D1_PixelShader) == 4 ? 1 : -1];
|
||||
typedef char StateBlock_D2_VertexShader_offset[offsetof(StateBlock, D2_VertexShader) == 8 ? 1 : -1];
|
||||
typedef char StateBlock_D3_Index_offset[offsetof(StateBlock, D3_Index) == 12 ? 1 : -1];
|
||||
typedef char StateBlock_D4_Streams_offset[offsetof(StateBlock, D4_Streams) == 16 ? 1 : -1];
|
||||
typedef char StateBlock_D6_PixelShaderConstants_offset[offsetof(StateBlock, D6_PixelShaderConstants) == 20 ? 1 : -1];
|
||||
typedef char StateBlock_D7_VertexShaderConstants_offset[offsetof(StateBlock, D7_VertexShaderConstants) == 24 ? 1 : -1];
|
||||
typedef char StateBlock_D8_RenderStates_offset[offsetof(StateBlock, D8_RenderStates) == 28 ? 1 : -1];
|
||||
typedef char StateBlock_D9_TextureStates_offset[offsetof(StateBlock, D9_TextureStates) == 32 ? 1 : -1];
|
||||
typedef char StateBlock_D10_Transforms_offset[offsetof(StateBlock, D10_Transforms) == 36 ? 1 : -1];
|
||||
typedef char StateBlock_D11_Viewport_offset[offsetof(StateBlock, D11_Viewport) == 40 ? 1 : -1];
|
||||
typedef char StateBlock_D12_Material_offset[offsetof(StateBlock, D12_Material) == 44 ? 1 : -1];
|
||||
typedef char StateBlock_D13_BackMaterial_offset[offsetof(StateBlock, D13_BackMaterial) == 48 ? 1 : -1];
|
||||
typedef char StateBlock_D14_Lights_offset[offsetof(StateBlock, D14_Lights) == 52 ? 1 : -1];
|
||||
typedef char StateBlock_D15_LightEnables_offset[offsetof(StateBlock, D15_LightEnables) == 56 ? 1 : -1];
|
||||
/* The cursor addresses the allocation's serialized tail, rather than indexing
|
||||
* beyond the PDB's one-element placeholder array. Callers require a valid,
|
||||
* fully populated state-block allocation. Counts are not untrusted input. */
|
||||
inline DWORD *StateBlockData(
|
||||
StateBlock *block)
|
||||
{
|
||||
return (DWORD *)((BYTE *)block + offsetof(StateBlock, Data));
|
||||
}
|
||||
void WINAPI ClearStateBlockFlags(
|
||||
void);
|
||||
HRESULT WINAPI RecordStateBlock(
|
||||
DWORD *token);
|
||||
extern const BYTE g_PixelRenderStates[];
|
||||
extern const BYTE g_PixelTextureStates[];
|
||||
extern const BYTE g_VertexRenderStates[];
|
||||
extern const BYTE g_VertexTextureStates[];
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "resource_internal.h"
|
||||
#include "memory_internal.h"
|
||||
#include "kernel_memory.h"
|
||||
#include "push_internal.h"
|
||||
#include "buffer_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
void WINAPI D3DIndexBuffer_GetDesc(
|
||||
D3DIndexBuffer *buffer,
|
||||
D3DINDEXBUFFER_DESC *desc)
|
||||
{
|
||||
desc->Format = D3DFMT_INDEX16;
|
||||
desc->Type = D3DRTYPE_INDEXBUFFER;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DPalette_Lock(
|
||||
D3DPalette *palette,
|
||||
D3DCOLOR **colors,
|
||||
DWORD flags)
|
||||
{
|
||||
if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY)))
|
||||
{
|
||||
D3D::BlockOnResource(palette);
|
||||
}
|
||||
*colors = (D3DCOLOR *)D3D::GetDataFromResource(palette);
|
||||
return;
|
||||
}
|
||||
D3DPALETTESIZE WINAPI D3DPalette_GetSize(
|
||||
D3DPalette *palette)
|
||||
{
|
||||
return (D3DPALETTESIZE)(palette->Common >> 30);
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DDevice_CreateIndexBuffer(
|
||||
UINT length,
|
||||
DWORD usage,
|
||||
D3DFORMAT format,
|
||||
D3DPOOL pool,
|
||||
D3DIndexBuffer **result)
|
||||
{
|
||||
D3DIndexBuffer *buffer = (D3DIndexBuffer *)LocalAlloc(0, length + sizeof(D3DIndexBuffer));
|
||||
if (!buffer)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
buffer->Common = 0x01010001;
|
||||
buffer->Data = (DWORD)(buffer + 1);
|
||||
*result = buffer;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI D3DDevice_CreateVertexBuffer(
|
||||
UINT length,
|
||||
DWORD usage,
|
||||
DWORD fvf,
|
||||
D3DPOOL pool,
|
||||
D3DVertexBuffer **result)
|
||||
{
|
||||
D3DVertexBuffer *buffer = (D3DVertexBuffer *)LocalAlloc(LMEM_ZEROINIT, sizeof(*buffer));
|
||||
if (!buffer)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
void *memory = MmAllocateContiguousMemoryEx(length, 0, 0x03ffb000, 0,
|
||||
PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (!memory)
|
||||
{
|
||||
LocalFree(buffer);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
buffer->Data = (DWORD)memory & 0x03ffffff;
|
||||
buffer->Common = D3DCOMMON_D3DCREATED | D3DCOMMON_TYPE_VERTEXBUFFER | 1;
|
||||
*result = buffer;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI D3DDevice_CreatePalette(
|
||||
D3DPALETTESIZE size,
|
||||
D3DPalette **result)
|
||||
{
|
||||
D3DPalette *palette = (D3DPalette *)LocalAlloc(LMEM_ZEROINIT, sizeof(*palette));
|
||||
if (!palette)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
void *memory = MmAllocateContiguousMemoryEx(D3D::g_PaletteSize[size], 0,
|
||||
0x03ffb000, 0, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (!memory)
|
||||
{
|
||||
LocalFree(palette);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
DWORD paletteBits = (DWORD)size << D3DPALETTE_COMMON_PALETTESIZE_SHIFT;
|
||||
palette->Data = (DWORD)memory & 0x03ffffff;
|
||||
palette->Common = paletteBits | D3DCOMMON_D3DCREATED | D3DCOMMON_TYPE_PALETTE | 1;
|
||||
*result = palette;
|
||||
return S_OK;
|
||||
}
|
||||
void WINAPI D3DVertexBuffer_Lock(
|
||||
D3DVertexBuffer *buffer,
|
||||
UINT offset,
|
||||
UINT size,
|
||||
BYTE **data,
|
||||
DWORD flags)
|
||||
{
|
||||
if (!(flags & D3DLOCK_NOFLUSH))
|
||||
{
|
||||
D3D::CDevice *device = D3D::g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
D3D::Push1(push, D3D::NV097_INVALIDATE_VERTEX_CACHE, 0);
|
||||
device->EndPush(push + 2);
|
||||
}
|
||||
if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY)))
|
||||
{
|
||||
D3D::BlockOnResource(buffer);
|
||||
}
|
||||
*data = D3D::GetDataFromResource(buffer) + offset;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DVertexBuffer_GetDesc(
|
||||
D3DVertexBuffer *buffer,
|
||||
D3DVERTEXBUFFER_DESC *desc)
|
||||
{
|
||||
desc->Format = D3DFMT_VERTEXDATA;
|
||||
desc->Type = buffer->GetType();
|
||||
return;
|
||||
}
|
||||
void *WINAPI D3DVertexBuffer_Lock2(
|
||||
D3DVertexBuffer *buffer,
|
||||
DWORD flags)
|
||||
{
|
||||
if (!(flags & (D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY)))
|
||||
{
|
||||
D3D::BlockOnResource(buffer);
|
||||
}
|
||||
return D3D::GetDataFromResource(buffer);
|
||||
}
|
||||
|
||||
#pragma const_seg("D3D_RD")
|
||||
namespace D3D
|
||||
{
|
||||
/* Exact original buffer.obj table, not a later SDK palette-size assumption. */
|
||||
const int g_PaletteSize[] = { 256, 128, 64, 32 };
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef HALO_D3D8_BUFFER_INTERNAL_H
|
||||
#define HALO_D3D8_BUFFER_INTERNAL_H
|
||||
#include <xtl.h>
|
||||
namespace D3D
|
||||
{
|
||||
/* Original buffer.obj public constant-table owner. */
|
||||
extern const int g_PaletteSize[];
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
/* NV2A clears, reconstructed against the January target and corroborated by
|
||||
* RXDK-Libs clear.cpp (2026 Team Resurgent), GPL-3.0-or-later.
|
||||
* See libs/d3d8/PROVENANCE.md and libs/d3d8/research/wave6_matching_notes.md.
|
||||
* Valid caller domain: finite Z in [0,1], allocated rectangles and valid
|
||||
* render/depth formats, with coordinates fitting the device's clip range. */
|
||||
#include "device_layout.h"
|
||||
#include "pixeljar.h"
|
||||
#include "push_internal.h"
|
||||
#include "math_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
using namespace D3D;
|
||||
|
||||
void WINAPI D3DDevice_Clear(
|
||||
DWORD count,
|
||||
const D3DRECT *rectangles,
|
||||
DWORD flags,
|
||||
D3DCOLOR color,
|
||||
float z,
|
||||
DWORD stencil)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3DRECT rectangle;
|
||||
DWORD *push;
|
||||
D3DSurface *target = device->m_pRenderTarget;
|
||||
D3DSurface *depth = device->m_pZBuffer;
|
||||
DWORD fillDepth = 0;
|
||||
DWORD savedFormat = 0;
|
||||
|
||||
if (PixelJar::IsSwizzled(target))
|
||||
{
|
||||
savedFormat = PixelJar::GetSurfaceFormat(target, depth);
|
||||
DWORD linearFormat = (savedFormat & ~0x200UL) | 0x100UL;
|
||||
push = device->StartPush();
|
||||
Push1(push, 0x208, linearFormat);
|
||||
device->EndPush(push + 2);
|
||||
}
|
||||
|
||||
if (flags & D3DCLEAR_TARGET)
|
||||
{
|
||||
switch (PixelJar::GetFormat(target))
|
||||
{
|
||||
case D3DFMT_R5G6B5:
|
||||
case D3DFMT_LIN_R5G6B5:
|
||||
color = ((color & 0x00f80000UL) >> 8) |
|
||||
((color & 0x0000fc00UL) >> 5) |
|
||||
((color & 0x000000f8UL) >> 3);
|
||||
break;
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_LIN_X1R5G5B5:
|
||||
color = ((color & 0x00f80000UL) >> 9) |
|
||||
((color & 0x0000f800UL) >> 6) |
|
||||
((color & 0x000000f8UL) >> 3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!depth)
|
||||
{
|
||||
flags &= ~(D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL);
|
||||
if (!flags)
|
||||
{
|
||||
// Original early exit is before SavedFormat restoration. Keep
|
||||
// the behavior visible; this is not a corrected driver build.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & D3DCLEAR_ZBUFFER)
|
||||
{
|
||||
switch (PixelJar::GetFormat(depth))
|
||||
{
|
||||
case D3DFMT_D16:
|
||||
case D3DFMT_LIN_D16:
|
||||
{
|
||||
LONG value = FloatToLong(z * (float)D3DZ_MAX_D16);
|
||||
value = value > 0xffff ? 0xffff : value;
|
||||
value = value < 0 ? 0 : value;
|
||||
fillDepth = value;
|
||||
}
|
||||
break;
|
||||
case D3DFMT_D24S8:
|
||||
case D3DFMT_LIN_D24S8:
|
||||
{
|
||||
LONG value = FloatToLong(z * (float)D3DZ_MAX_D24S8);
|
||||
value = value > 0xffffff ? 0xffffff : value;
|
||||
value = value < 0 ? 0 : value;
|
||||
fillDepth = (DWORD)value << 8;
|
||||
}
|
||||
break;
|
||||
case D3DFMT_F16:
|
||||
case D3DFMT_LIN_F16:
|
||||
if (z == 0.0f)
|
||||
{
|
||||
fillDepth = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double scaled = (double)z * D3DZ_MAX_F16;
|
||||
DWORD high;
|
||||
// Decode the little-endian double representation without
|
||||
// reading through an unrelated DWORD lvalue.
|
||||
memcpy(&high, (const BYTE *)&scaled + sizeof(DWORD), sizeof(high));
|
||||
fillDepth = ((high >> 8) - 0x3f8000) & 0xffff;
|
||||
}
|
||||
break;
|
||||
case D3DFMT_F24S8:
|
||||
case D3DFMT_LIN_F24S8:
|
||||
if (z == 0.0f)
|
||||
{
|
||||
fillDepth = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double scaled = (double)z * D3DZ_MAX_F24S8;
|
||||
DWORD high;
|
||||
memcpy(&high, (const BYTE *)&scaled + sizeof(DWORD), sizeof(high));
|
||||
fillDepth = ((high - 0x38000000UL) << 4) & 0xffffff00UL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INT leftClip = device->m_Viewport.X;
|
||||
INT topClip = device->m_Viewport.Y;
|
||||
INT rightClip = device->m_Viewport.X + device->m_Viewport.Width;
|
||||
INT bottomClip = device->m_Viewport.Y + device->m_Viewport.Height;
|
||||
if (!count)
|
||||
{
|
||||
rectangle.x1 = leftClip;
|
||||
rectangle.y1 = topClip;
|
||||
rectangle.x2 = rightClip;
|
||||
rectangle.y2 = bottomClip;
|
||||
rectangles = &rectangle;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
INT left = max(rectangles->x1, leftClip);
|
||||
INT top = max(rectangles->y1, topClip);
|
||||
INT right = min(rectangles->x2, rightClip);
|
||||
INT bottom = min(rectangles->y2, bottomClip);
|
||||
if (left < right && top < bottom)
|
||||
{
|
||||
left = Round(left * device->m_SuperSampleScaleX);
|
||||
right = Round(right * device->m_SuperSampleScaleX);
|
||||
top = Round(top * device->m_SuperSampleScaleY);
|
||||
bottom = Round(bottom * device->m_SuperSampleScaleY);
|
||||
push = device->StartPush();
|
||||
PushCount(push, 0x1d98, 2);
|
||||
push[1] = (DWORD)left | ((DWORD)(right - 1) << 16);
|
||||
push[2] = (DWORD)top | ((DWORD)(bottom - 1) << 16);
|
||||
PushCount(push + 3, 0x1d8c, 3);
|
||||
push[4] = fillDepth | stencil;
|
||||
push[5] = color;
|
||||
push[6] = flags;
|
||||
device->EndPush(push + 7);
|
||||
}
|
||||
} while (++rectangles, --count != 0);
|
||||
|
||||
if (savedFormat)
|
||||
{
|
||||
push = device->StartPush();
|
||||
Push1(push, 0x208, savedFormat);
|
||||
device->EndPush(push + 2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,793 @@
|
||||
/* January fixed-function register combiners.
|
||||
* Adapted from the legacy combiner implementation in RXDK-Libs.
|
||||
* Copyright 2026 Team Resurgent. SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Reference commit 29e018674a3443f9df5b5cb4478bb9c54d8a2a3a.
|
||||
* Original cachebeta code/PDB controls per-device storage, types and semantics.
|
||||
* Valid domain: four texture stages, eight combiner stages, selectors A..D,
|
||||
* initialized device and exclusive access to its texture-stage shadow state.
|
||||
*/
|
||||
#include "combiner_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
/* Original writable shift table. Its private-data ownership remains unresolved
|
||||
* in the extracted target; keep the authentic name rather than an address. */
|
||||
static DWORD kelvinCombinerInputShift[4] = { 24, 16, 8, 0 };
|
||||
|
||||
void WINAPI nvKelvinACSetAlphaInputOne(
|
||||
CDevice *pDevice,
|
||||
kelvinCombinerInput eInput,
|
||||
DWORD dwCombinerStage,
|
||||
BOOL bNegate)
|
||||
{
|
||||
DWORD dwICW = 0;
|
||||
dwICW |= bNegate ? PS_INPUTMAPPING_EXPAND_NORMAL : PS_INPUTMAPPING_UNSIGNED_INVERT;
|
||||
pDevice->m_AlphaICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT WINAPI nvKelvinACSelectAlphaInput(
|
||||
CDevice *pDevice,
|
||||
kelvinCombinerInput eInput,
|
||||
DWORD dwCombinerStage,
|
||||
DWORD dwD3DStage,
|
||||
DWORD dwD3DTSSArg,
|
||||
BOOL bComplement,
|
||||
BOOL bExpandNormal)
|
||||
{
|
||||
DWORD dwICW = 0;
|
||||
switch (D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_SELECTMASK)
|
||||
{
|
||||
case D3DTA_CURRENT:
|
||||
if (dwCombinerStage != 0)
|
||||
{
|
||||
dwICW |= PS_REGISTER_R0;
|
||||
break;
|
||||
}
|
||||
/* Current in stage zero is incoming diffuse. */
|
||||
case D3DTA_DIFFUSE:
|
||||
dwICW |= PS_REGISTER_V0;
|
||||
break;
|
||||
case D3DTA_TEXTURE:
|
||||
if (pDevice->m_Textures[dwD3DStage] == NULL)
|
||||
return TSS_USES_NULL_TEXTURE;
|
||||
dwICW |= (PS_REGISTER_T0 + dwD3DStage) & D3DTA_SELECTMASK;
|
||||
break;
|
||||
case D3DTA_TFACTOR:
|
||||
dwICW |= PS_REGISTER_C0;
|
||||
break;
|
||||
case D3DTA_TEMP:
|
||||
dwICW |= PS_REGISTER_R1;
|
||||
break;
|
||||
case D3DTA_SPECULAR:
|
||||
dwICW |= PS_REGISTER_V1;
|
||||
pDevice->m_StateFlags |= COMBINER_NEEDS_SPECULAR;
|
||||
break;
|
||||
default:
|
||||
/* Original release behavior outside valid selectors. */
|
||||
break;
|
||||
}
|
||||
dwICW |= PS_CHANNEL_ALPHA;
|
||||
bComplement = ((D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_COMPLEMENT)
|
||||
^ (bComplement ? D3DTA_COMPLEMENT : 0)) ? TRUE : FALSE;
|
||||
if (bExpandNormal)
|
||||
dwICW |= bComplement ? PS_INPUTMAPPING_EXPAND_NEGATE : PS_INPUTMAPPING_EXPAND_NORMAL;
|
||||
else
|
||||
dwICW |= bComplement ? PS_INPUTMAPPING_UNSIGNED_INVERT : PS_INPUTMAPPING_UNSIGNED_IDENTITY;
|
||||
pDevice->m_AlphaICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACSelect1(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACSelect2(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACModulate(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACAdd(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACSub(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, TRUE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACAddSmooth(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, TRUE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACBlendAlpha(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage,
|
||||
DWORD dwType)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
DWORD dwTemp;
|
||||
if (dwType == COMBINER_PREMULTIPLIED_TEXTURE)
|
||||
{
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
dwType = D3DTA_TEXTURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwType;
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwTemp;
|
||||
}
|
||||
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1] = dwType;
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, TRUE, FALSE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1] = dwTemp;
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACPremodulate(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (dwHWStage == 0)
|
||||
{
|
||||
/* The original reads the next row without checking that it exists.
|
||||
* Point-sprite stage remapping can supply texture stage three. Retain
|
||||
* a bounded fallback rather than manufacturing that out-of-bounds read.
|
||||
* This complete defensive draft is nonexact and receives zero credit. */
|
||||
if (dwD3DStage < D3DTSS_MAXSTAGES - 1
|
||||
&& D3D__TextureState[dwD3DStage + 1][D3DTSS_ALPHAOP] != D3DTOP_DISABLE)
|
||||
{
|
||||
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
DWORD dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = D3DTA_TEXTURE;
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACMultiplyAdd(
|
||||
CDevice *pDevice,
|
||||
int dwHWStage,
|
||||
int dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, FALSE, FALSE);
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinACLerp(
|
||||
CDevice *pDevice,
|
||||
int dwHWStage,
|
||||
int dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, FALSE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, TRUE, FALSE);
|
||||
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
void WINAPI nvConstructKelvinOutputAlphaCombiners(
|
||||
CDevice *pDevice,
|
||||
BOOL bEnable,
|
||||
DWORD dwStage,
|
||||
DWORD dwD3DStage,
|
||||
BOOL bBias,
|
||||
DWORD dwShift,
|
||||
BOOL bOutTemp)
|
||||
{
|
||||
/* January does not clear ICW here, unlike the later reference. */
|
||||
if (!bEnable || D3D__TextureState[dwD3DStage][D3DTSS_COLOROP] == D3DTOP_DOTPRODUCT3)
|
||||
return;
|
||||
switch (dwShift)
|
||||
{
|
||||
case COMBINER_SHIFT_NONE:
|
||||
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_BIAS << 12) : (PS_COMBINEROUTPUT_IDENTITY << 12);
|
||||
break;
|
||||
case COMBINER_SHIFT_ONE:
|
||||
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_1 << 12);
|
||||
break;
|
||||
case COMBINER_SHIFT_TWO:
|
||||
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_2 << 12);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pDevice->m_AlphaOCW[dwStage] |= PS_REGISTER_R0 << 8;
|
||||
pDevice->m_AlphaOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI ConstructAlphaCombiners(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage,
|
||||
BOOL bStageActive)
|
||||
{
|
||||
DWORD dwShift = 0;
|
||||
BOOL bBias = FALSE;
|
||||
BOOL bEnable = TRUE;
|
||||
HRESULT hr = S_OK;
|
||||
pDevice->m_AlphaICW[dwHWStage] = 0;
|
||||
pDevice->m_AlphaOCW[dwHWStage] = 0;
|
||||
if (!bStageActive)
|
||||
{
|
||||
if (dwHWStage == 0)
|
||||
{
|
||||
pDevice->m_AlphaICW[dwHWStage] |= (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
else
|
||||
bEnable = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (D3D__TextureState[dwD3DStage][D3DTSS_ALPHAOP])
|
||||
{
|
||||
default:
|
||||
case D3DTOP_DOTPRODUCT3:
|
||||
case D3DTOP_DISABLE:
|
||||
if (dwHWStage == 0)
|
||||
{
|
||||
pDevice->m_AlphaICW[dwHWStage] |= (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
else
|
||||
bEnable = FALSE;
|
||||
break;
|
||||
case D3DTOP_SELECTARG1:
|
||||
hr = nvKelvinACSelect1(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_SELECTARG2:
|
||||
hr = nvKelvinACSelect2(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_MODULATE4X:
|
||||
dwShift++;
|
||||
/* Each fallthrough adds one scaling bit. */
|
||||
case D3DTOP_MODULATE2X:
|
||||
dwShift++;
|
||||
case D3DTOP_MODULATE:
|
||||
hr = nvKelvinACModulate(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_ADDSIGNED2X:
|
||||
dwShift = 1;
|
||||
case D3DTOP_ADDSIGNED:
|
||||
bBias = TRUE;
|
||||
case D3DTOP_ADD:
|
||||
hr = nvKelvinACAdd(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_SUBTRACT:
|
||||
hr = nvKelvinACSub(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_ADDSMOOTH:
|
||||
hr = nvKelvinACAddSmooth(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_BLENDDIFFUSEALPHA:
|
||||
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_DIFFUSE);
|
||||
break;
|
||||
case D3DTOP_BLENDTEXTUREALPHA:
|
||||
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TEXTURE);
|
||||
break;
|
||||
case D3DTOP_BLENDFACTORALPHA:
|
||||
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TFACTOR);
|
||||
break;
|
||||
case D3DTOP_BLENDTEXTUREALPHAPM:
|
||||
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, COMBINER_PREMULTIPLIED_TEXTURE);
|
||||
break;
|
||||
case D3DTOP_BLENDCURRENTALPHA:
|
||||
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_CURRENT);
|
||||
break;
|
||||
case D3DTOP_PREMODULATE:
|
||||
hr = nvKelvinACPremodulate(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_MULTIPLYADD:
|
||||
hr = nvKelvinACMultiplyAdd(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_LERP:
|
||||
hr = nvKelvinACLerp(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hr == TSS_USES_NULL_TEXTURE)
|
||||
{
|
||||
if (dwHWStage == 0)
|
||||
pDevice->m_AlphaICW[dwHWStage] = (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
|
||||
else
|
||||
pDevice->m_AlphaICW[dwHWStage] = (PS_REGISTER_R0 | PS_CHANNEL_ALPHA) << 24;
|
||||
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
nvConstructKelvinOutputAlphaCombiners(pDevice, bEnable, dwHWStage, dwD3DStage, bBias, dwShift,
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_RESULTARG] == D3DTA_TEMP);
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI nvKelvinCCSetColorInputOne(
|
||||
CDevice *pDevice,
|
||||
kelvinCombinerInput eInput,
|
||||
DWORD dwCombinerStage,
|
||||
BOOL bNegate)
|
||||
{
|
||||
DWORD dwICW = 0;
|
||||
dwICW |= bNegate ? PS_INPUTMAPPING_EXPAND_NORMAL : PS_INPUTMAPPING_UNSIGNED_INVERT;
|
||||
pDevice->m_ColorICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT WINAPI nvKelvinCCSelectColorInput(
|
||||
CDevice *pDevice,
|
||||
kelvinCombinerInput eInput,
|
||||
DWORD dwCombinerStage,
|
||||
DWORD dwD3DStage,
|
||||
DWORD dwD3DTSSArg,
|
||||
BOOL bComplement,
|
||||
BOOL bExpandNormal,
|
||||
BOOL bAlphaReplicate)
|
||||
{
|
||||
DWORD dwICW = 0;
|
||||
switch (D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_SELECTMASK)
|
||||
{
|
||||
case D3DTA_CURRENT:
|
||||
if (dwCombinerStage != 0)
|
||||
{
|
||||
dwICW |= PS_REGISTER_R0;
|
||||
break;
|
||||
}
|
||||
/* Current in stage zero is incoming diffuse. */
|
||||
case D3DTA_DIFFUSE:
|
||||
dwICW |= PS_REGISTER_V0;
|
||||
break;
|
||||
case D3DTA_TEXTURE:
|
||||
if (pDevice->m_Textures[dwD3DStage] == NULL)
|
||||
return TSS_USES_NULL_TEXTURE;
|
||||
dwICW |= (PS_REGISTER_T0 + dwD3DStage) & D3DTA_SELECTMASK;
|
||||
break;
|
||||
case D3DTA_TFACTOR:
|
||||
dwICW |= PS_REGISTER_C0;
|
||||
break;
|
||||
case D3DTA_SPECULAR:
|
||||
dwICW |= PS_REGISTER_V1;
|
||||
pDevice->m_StateFlags |= COMBINER_NEEDS_SPECULAR;
|
||||
break;
|
||||
case D3DTA_TEMP:
|
||||
dwICW |= PS_REGISTER_R1;
|
||||
break;
|
||||
default:
|
||||
/* Original release behavior outside valid selectors. */
|
||||
break;
|
||||
}
|
||||
bAlphaReplicate |= D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_ALPHAREPLICATE;
|
||||
dwICW |= bAlphaReplicate ? PS_CHANNEL_ALPHA : PS_CHANNEL_RGB;
|
||||
bComplement = ((D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_COMPLEMENT)
|
||||
^ (bComplement ? D3DTA_COMPLEMENT : 0)) ? TRUE : FALSE;
|
||||
if (bExpandNormal)
|
||||
dwICW |= bComplement ? PS_INPUTMAPPING_EXPAND_NEGATE : PS_INPUTMAPPING_EXPAND_NORMAL;
|
||||
else
|
||||
dwICW |= bComplement ? PS_INPUTMAPPING_UNSIGNED_INVERT : PS_INPUTMAPPING_UNSIGNED_IDENTITY;
|
||||
pDevice->m_ColorICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCSelect1(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCSelect2(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCModulate(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCAdd(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCSub(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, TRUE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCAddSmooth(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, TRUE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCBlendAlpha(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage,
|
||||
DWORD dwType)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
DWORD dwTemp;
|
||||
if (dwType == COMBINER_PREMULTIPLIED_TEXTURE)
|
||||
{
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
dwType = D3DTA_TEXTURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwType;
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, TRUE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwTemp;
|
||||
}
|
||||
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwType;
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, TRUE, FALSE, TRUE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwTemp;
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCPremodulate(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (dwHWStage == 0)
|
||||
{
|
||||
/* Color premodulation tests the fixed second texture row in January. */
|
||||
if (D3D__TextureState[1][D3DTSS_COLOROP] != D3DTOP_DISABLE)
|
||||
{
|
||||
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
DWORD dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = D3DTA_TEXTURE;
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCModulateAlpha(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage,
|
||||
BOOL bComplement)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, bComplement, FALSE, TRUE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCModulateColor(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage,
|
||||
BOOL bComplement)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, bComplement, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, TRUE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputD, dwHWStage, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinBumpMap(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (pDevice->m_Textures[dwD3DStage] == NULL)
|
||||
hr = TSS_USES_NULL_TEXTURE;
|
||||
else
|
||||
{
|
||||
DWORD dwArg1Cache = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1];
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = D3DTA_CURRENT;
|
||||
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwArg1Cache;
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCDotProduct(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, TRUE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, TRUE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCMultiplyAdd(
|
||||
CDevice *pDevice,
|
||||
int dwHWStage,
|
||||
int dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, FALSE, FALSE, FALSE);
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI nvKelvinCCLerp(
|
||||
CDevice *pDevice,
|
||||
int dwHWStage,
|
||||
int dwD3DStage)
|
||||
{
|
||||
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, FALSE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, TRUE, FALSE, FALSE);
|
||||
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
|
||||
return hr;
|
||||
}
|
||||
|
||||
void WINAPI nvConstructKelvinOutputColorCombiners(
|
||||
CDevice *pDevice,
|
||||
BOOL bEnable,
|
||||
DWORD dwStage,
|
||||
BOOL bBias,
|
||||
DWORD dwShift,
|
||||
BOOL bDotAB,
|
||||
BOOL bDotCD,
|
||||
BOOL bOutTemp)
|
||||
{
|
||||
if (!bEnable)
|
||||
return;
|
||||
switch (dwShift)
|
||||
{
|
||||
case COMBINER_SHIFT_NONE:
|
||||
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_BIAS << 12) : (PS_COMBINEROUTPUT_IDENTITY << 12);
|
||||
break;
|
||||
case COMBINER_SHIFT_ONE:
|
||||
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_1 << 12);
|
||||
break;
|
||||
case COMBINER_SHIFT_TWO:
|
||||
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_2 << 12);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bDotAB && bDotCD)
|
||||
{
|
||||
pDevice->m_ColorOCW[dwStage] |= (PS_COMBINEROUTPUT_AB_DOT_PRODUCT | PS_COMBINEROUTPUT_CD_DOT_PRODUCT
|
||||
| PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA | PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) << 12;
|
||||
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
|
||||
}
|
||||
else if (bDotAB)
|
||||
{
|
||||
pDevice->m_ColorOCW[dwStage] |= (PS_COMBINEROUTPUT_AB_DOT_PRODUCT | PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) << 12;
|
||||
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 4) : (PS_REGISTER_R0 << 4);
|
||||
}
|
||||
else
|
||||
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL WINAPI ConstructColorCombiners(
|
||||
CDevice *pDevice,
|
||||
DWORD dwHWStage,
|
||||
DWORD dwD3DStage)
|
||||
{
|
||||
BOOL bEnable = TRUE;
|
||||
BOOL bStageActive = TRUE;
|
||||
BOOL bDotProduct = FALSE;
|
||||
BOOL bBias = FALSE;
|
||||
DWORD dwShift = 0;
|
||||
HRESULT hr = S_OK;
|
||||
pDevice->m_ColorICW[dwHWStage] = 0;
|
||||
pDevice->m_ColorOCW[dwHWStage] = 0;
|
||||
switch (D3D__TextureState[dwD3DStage][D3DTSS_COLOROP])
|
||||
{
|
||||
default:
|
||||
case D3DTOP_DISABLE:
|
||||
if (dwHWStage == 0)
|
||||
{
|
||||
pDevice->m_ColorICW[dwHWStage] |= (PS_REGISTER_V0) << 24;
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
else
|
||||
bEnable = FALSE;
|
||||
bStageActive = FALSE;
|
||||
break;
|
||||
case D3DTOP_SELECTARG1:
|
||||
hr = nvKelvinCCSelect1(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_SELECTARG2:
|
||||
hr = nvKelvinCCSelect2(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_MODULATE4X:
|
||||
dwShift++;
|
||||
/* Each fallthrough adds one scaling bit. */
|
||||
case D3DTOP_MODULATE2X:
|
||||
dwShift++;
|
||||
case D3DTOP_MODULATE:
|
||||
hr = nvKelvinCCModulate(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_ADDSIGNED2X:
|
||||
dwShift = 1;
|
||||
case D3DTOP_ADDSIGNED:
|
||||
bBias = TRUE;
|
||||
case D3DTOP_ADD:
|
||||
hr = nvKelvinCCAdd(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_SUBTRACT:
|
||||
hr = nvKelvinCCSub(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_ADDSMOOTH:
|
||||
hr = nvKelvinCCAddSmooth(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_BLENDDIFFUSEALPHA:
|
||||
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_DIFFUSE);
|
||||
break;
|
||||
case D3DTOP_BLENDTEXTUREALPHA:
|
||||
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TEXTURE);
|
||||
break;
|
||||
case D3DTOP_BLENDFACTORALPHA:
|
||||
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TFACTOR);
|
||||
break;
|
||||
case D3DTOP_BLENDTEXTUREALPHAPM:
|
||||
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, COMBINER_PREMULTIPLIED_TEXTURE);
|
||||
break;
|
||||
case D3DTOP_BLENDCURRENTALPHA:
|
||||
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_CURRENT);
|
||||
break;
|
||||
case D3DTOP_PREMODULATE:
|
||||
hr = nvKelvinCCPremodulate(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_MODULATEALPHA_ADDCOLOR:
|
||||
hr = nvKelvinCCModulateAlpha(pDevice, dwHWStage, dwD3DStage, FALSE);
|
||||
break;
|
||||
case D3DTOP_MODULATECOLOR_ADDALPHA:
|
||||
hr = nvKelvinCCModulateColor(pDevice, dwHWStage, dwD3DStage, FALSE);
|
||||
break;
|
||||
case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
|
||||
hr = nvKelvinCCModulateAlpha(pDevice, dwHWStage, dwD3DStage, TRUE);
|
||||
break;
|
||||
case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
|
||||
hr = nvKelvinCCModulateColor(pDevice, dwHWStage, dwD3DStage, TRUE);
|
||||
break;
|
||||
case D3DTOP_BUMPENVMAP:
|
||||
case D3DTOP_BUMPENVMAPLUMINANCE:
|
||||
hr = nvKelvinBumpMap(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_DOTPRODUCT3:
|
||||
hr = nvKelvinCCDotProduct(pDevice, dwHWStage, dwD3DStage);
|
||||
bDotProduct = TRUE;
|
||||
break;
|
||||
case D3DTOP_MULTIPLYADD:
|
||||
hr = nvKelvinCCMultiplyAdd(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
case D3DTOP_LERP:
|
||||
hr = nvKelvinCCLerp(pDevice, dwHWStage, dwD3DStage);
|
||||
break;
|
||||
}
|
||||
if (hr == TSS_USES_NULL_TEXTURE)
|
||||
{
|
||||
if (dwHWStage == 0)
|
||||
pDevice->m_ColorICW[dwHWStage] = (PS_REGISTER_V0) << 24;
|
||||
else
|
||||
pDevice->m_ColorICW[dwHWStage] = (PS_REGISTER_R0) << 24;
|
||||
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
|
||||
}
|
||||
nvConstructKelvinOutputColorCombiners(pDevice, bEnable, dwHWStage, bBias, dwShift,
|
||||
bDotProduct, FALSE, D3D__TextureState[dwD3DStage][D3DTSS_RESULTARG] == D3DTA_TEMP);
|
||||
return bStageActive;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef D3D8_COMBINER_INTERNAL_H
|
||||
#define D3D8_COMBINER_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
typedef enum _kelvinCombinerInput
|
||||
{
|
||||
kelvinCombinerInputA = 0,
|
||||
kelvinCombinerInputB = 1,
|
||||
kelvinCombinerInputC = 2,
|
||||
kelvinCombinerInputD = 3
|
||||
} kelvinCombinerInput;
|
||||
enum CombinerScale
|
||||
{
|
||||
COMBINER_SHIFT_NONE = 0,
|
||||
COMBINER_SHIFT_ONE = 1,
|
||||
COMBINER_SHIFT_TWO = 2
|
||||
};
|
||||
enum
|
||||
{
|
||||
TSS_USES_NULL_TEXTURE = 1,
|
||||
COMBINER_PREMULTIPLIED_TEXTURE = 0xcafebeefUL,
|
||||
COMBINER_NEEDS_SPECULAR = 0x40
|
||||
};
|
||||
void WINAPI nvKelvinACSetAlphaInputOne(
|
||||
CDevice *device,
|
||||
kelvinCombinerInput input,
|
||||
DWORD stage,
|
||||
BOOL negate);
|
||||
HRESULT WINAPI nvKelvinACSelectAlphaInput(
|
||||
CDevice *device,
|
||||
kelvinCombinerInput input,
|
||||
DWORD stage,
|
||||
DWORD textureStage,
|
||||
DWORD argument,
|
||||
BOOL complement,
|
||||
BOOL expandNormal);
|
||||
void WINAPI nvKelvinCCSetColorInputOne(
|
||||
CDevice *device,
|
||||
kelvinCombinerInput input,
|
||||
DWORD stage,
|
||||
BOOL negate);
|
||||
HRESULT WINAPI nvKelvinCCSelectColorInput(
|
||||
CDevice *device,
|
||||
kelvinCombinerInput input,
|
||||
DWORD stage,
|
||||
DWORD textureStage,
|
||||
DWORD argument,
|
||||
BOOL complement,
|
||||
BOOL expandNormal,
|
||||
BOOL alphaReplicate);
|
||||
void WINAPI nvConstructKelvinOutputAlphaCombiners(
|
||||
CDevice *device,
|
||||
BOOL enable,
|
||||
DWORD stage,
|
||||
DWORD textureStage,
|
||||
BOOL bias,
|
||||
DWORD shift,
|
||||
BOOL outputTemp);
|
||||
void WINAPI nvConstructKelvinOutputColorCombiners(
|
||||
CDevice *device,
|
||||
BOOL enable,
|
||||
DWORD stage,
|
||||
BOOL bias,
|
||||
DWORD shift,
|
||||
BOOL dotAB,
|
||||
BOOL dotCD,
|
||||
BOOL outputTemp);
|
||||
BOOL WINAPI ConstructColorCombiners(
|
||||
CDevice *device,
|
||||
DWORD combinerStage,
|
||||
DWORD textureStage);
|
||||
void WINAPI ConstructAlphaCombiners(
|
||||
CDevice *device,
|
||||
DWORD combinerStage,
|
||||
DWORD textureStage,
|
||||
BOOL moreStages);
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,39 @@
|
||||
/* Device entry points reconstructed from the original executable/PDB. */
|
||||
#include "device_layout.h"
|
||||
#include "push_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
using namespace D3D;
|
||||
void WINAPI Direct3D_SetPushBufferSize(
|
||||
DWORD pushBufferSize,
|
||||
DWORD pushSegmentSize)
|
||||
{
|
||||
CDevice::m_PushBufferSize = pushBufferSize;
|
||||
CDevice::m_PushSegmentSize = pushSegmentSize;
|
||||
return;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_CreateDevice(
|
||||
UINT adapter,
|
||||
D3DDEVTYPE deviceType,
|
||||
void *unused,
|
||||
DWORD behaviorFlags,
|
||||
D3DPRESENT_PARAMETERS *parameters,
|
||||
D3DDevice **returnedDevice)
|
||||
{
|
||||
if (CDevice::m_PushBufferSize == 0)
|
||||
CDevice::m_PushBufferSize = 512 * 1024;
|
||||
if (CDevice::m_PushSegmentSize == 0)
|
||||
CDevice::m_PushSegmentSize = 32 * 1024;
|
||||
g_pDevice = &g_Device;
|
||||
g_pPushBuffer = &g_Device.m_Pusher;
|
||||
g_Device.m_cRefs = 1;
|
||||
g_Device.m_StateFlags |= behaviorFlags & D3DCREATE_PUREDEVICE;
|
||||
HRESULT result = g_Device.Init(parameters);
|
||||
if (FAILED(result))
|
||||
{
|
||||
g_Device.UnInit();
|
||||
return result;
|
||||
}
|
||||
if (returnedDevice)
|
||||
*returnedDevice = &g_Device;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
#ifndef HALO_D3D8_DEVICE_LAYOUT_H
|
||||
#define HALO_D3D8_DEVICE_LAYOUT_H
|
||||
/* Original field names, types and offsets are decoded from cachebeta.pdb.
|
||||
* Opaque kernel-owned records remain reserved pending their own reconstruction. */
|
||||
#include <xtl.h>
|
||||
#include <stddef.h>
|
||||
#include "kernel_records.h"
|
||||
struct _KINTERRUPT;
|
||||
struct _KDPC;
|
||||
struct _HAL_SHUTDOWN_REGISTRATION;
|
||||
struct Nv206eControl;
|
||||
struct NvNotification;
|
||||
struct _XMETAL_PushBuffer
|
||||
{
|
||||
DWORD *m_pPut;
|
||||
DWORD *m_pThreshold;
|
||||
};
|
||||
namespace D3D
|
||||
{
|
||||
class CDevice;
|
||||
struct _HWREG;
|
||||
struct FenceEncoding;
|
||||
struct VertexShader;
|
||||
struct PixelShader;
|
||||
struct Light;
|
||||
|
||||
struct Fence
|
||||
{
|
||||
unsigned long Time; /* +0x0 */
|
||||
D3D::FenceEncoding *pEncoding; /* +0x4 */
|
||||
unsigned long Distance; /* +0x8 */
|
||||
};
|
||||
struct InlineAttributeData
|
||||
{
|
||||
unsigned long UP_Count; /* +0x0 */
|
||||
unsigned long UP_Delta; /* +0x4 */
|
||||
};
|
||||
struct PixelShader
|
||||
{
|
||||
unsigned long RefCount; /* +0x0 */
|
||||
unsigned long D3DOwned; /* +0x4 */
|
||||
_D3DPixelShaderDef *pPSDef; /* +0x8 */
|
||||
};
|
||||
struct Light
|
||||
{
|
||||
_D3DLIGHT8 Light8; /* +0x0 */
|
||||
unsigned long Flags; /* +0x68 */
|
||||
_D3DVECTOR Direction; /* +0x6c */
|
||||
float Falloff_L; /* +0x78 */
|
||||
float Falloff_M; /* +0x7c */
|
||||
float Falloff_N; /* +0x80 */
|
||||
float Scale; /* +0x84 */
|
||||
float W; /* +0x88 */
|
||||
D3D::Light *pNext; /* +0x8c */
|
||||
};
|
||||
class CMiniport
|
||||
{
|
||||
public:
|
||||
struct PUSHBUFFERFIXUPINFO
|
||||
{
|
||||
unsigned long *pFixup; /* +0x0 */
|
||||
unsigned char *pStart; /* +0x4 */
|
||||
unsigned long ReturnOffset; /* +0x8 */
|
||||
unsigned long *ReturnAddress; /* +0xc */
|
||||
};
|
||||
struct VBLANKFLIPS
|
||||
{
|
||||
int Pending; /* +0x0 */
|
||||
unsigned long Offset; /* +0x4 */
|
||||
};
|
||||
struct HW_HASHENTRY
|
||||
{
|
||||
unsigned long ht_ObjectHandle; /* +0x0 */
|
||||
unsigned long ht_Context; /* +0x4 */
|
||||
};
|
||||
struct VIDEOMODETIMING
|
||||
{
|
||||
unsigned long HorizontalVisible; /* +0x0 */
|
||||
unsigned long VerticalVisible; /* +0x4 */
|
||||
unsigned long Refresh; /* +0x8 */
|
||||
unsigned long HorizontalTotal; /* +0xc */
|
||||
unsigned long HorizontalBlankStart; /* +0x10 */
|
||||
unsigned long HorizontalRetraceStart; /* +0x14 */
|
||||
unsigned long HorizontalRetraceEnd; /* +0x18 */
|
||||
unsigned long HorizontalBlankEnd; /* +0x1c */
|
||||
unsigned long VerticalTotal; /* +0x20 */
|
||||
unsigned long VerticalBlankStart; /* +0x24 */
|
||||
unsigned long VerticalRetraceStart; /* +0x28 */
|
||||
unsigned long VerticalRetraceEnd; /* +0x2c */
|
||||
unsigned long VerticalBlankEnd; /* +0x30 */
|
||||
unsigned long PixelClock; /* +0x34 */
|
||||
unsigned long HorizontalSyncPolarity; /* +0x38 */
|
||||
unsigned long VerticalSyncPolarity; /* +0x3c */
|
||||
};
|
||||
struct HALINFO
|
||||
{
|
||||
long FifoChID; /* +0x0 */
|
||||
unsigned long FifoMode; /* +0x4 */
|
||||
int FifoInUse; /* +0x8 */
|
||||
unsigned long FifoInstance; /* +0xc */
|
||||
unsigned long FifoAllocCount; /* +0x10 */
|
||||
long FifoCacheDepth; /* +0x14 */
|
||||
unsigned long FifoObjectCount; /* +0x18 */
|
||||
unsigned long FifoIntrEn0; /* +0x1c */
|
||||
unsigned long FifoRetryCount; /* +0x20 */
|
||||
unsigned long FifoUserBase; /* +0x24 */
|
||||
unsigned long FifoContextAddr1; /* +0x28 */
|
||||
unsigned long FifoContextAddr2; /* +0x2c */
|
||||
unsigned long HashTableAddr; /* +0x30 */
|
||||
unsigned long GrChID; /* +0x34 */
|
||||
unsigned long GrCtxTable[2]; /* +0x38 */
|
||||
unsigned long GrCtxTableBase; /* +0x40 */
|
||||
unsigned long GrCurrentObjects3d[2]; /* +0x44 */
|
||||
unsigned long FbSave0; /* +0x4c */
|
||||
unsigned long FbSave1; /* +0x50 */
|
||||
unsigned long McSave; /* +0x54 */
|
||||
unsigned long McSaveIntrEn0; /* +0x58 */
|
||||
};
|
||||
struct DACINFO
|
||||
{
|
||||
unsigned long MClk; /* +0x0 */
|
||||
unsigned long VClk; /* +0x4 */
|
||||
unsigned long NVClk; /* +0x8 */
|
||||
unsigned long MPllM; /* +0xc */
|
||||
unsigned long MPllN; /* +0x10 */
|
||||
unsigned long MPllO; /* +0x14 */
|
||||
unsigned long MPllP; /* +0x18 */
|
||||
unsigned long VPllM; /* +0x1c */
|
||||
unsigned long VPllN; /* +0x20 */
|
||||
unsigned long VPllO; /* +0x24 */
|
||||
unsigned long VPllP; /* +0x28 */
|
||||
unsigned long NVPllM; /* +0x2c */
|
||||
unsigned long NVPllN; /* +0x30 */
|
||||
unsigned long NVPllO; /* +0x34 */
|
||||
unsigned long NVPllP; /* +0x38 */
|
||||
};
|
||||
struct GENERALINFO
|
||||
{
|
||||
unsigned long ChipId; /* +0x0 */
|
||||
unsigned long VideoRamSize; /* +0x4 */
|
||||
unsigned long VideoRamType; /* +0x8 */
|
||||
unsigned long ChipIntrEn0; /* +0xc */
|
||||
unsigned long MpVIPSlavePresent; /* +0x10 */
|
||||
unsigned long CrystalFreq; /* +0x14 */
|
||||
unsigned long MaskRevision; /* +0x18 */
|
||||
};
|
||||
struct OBJECTINFO
|
||||
{
|
||||
DWORD Handle;
|
||||
WORD SubChannel;
|
||||
WORD Engine;
|
||||
DWORD ClassNum;
|
||||
DWORD Instance;
|
||||
void Init(
|
||||
void)
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
return;
|
||||
}
|
||||
};
|
||||
void *m_RegisterBase; /* +0x0 */
|
||||
unsigned long m_PresentationInterval; /* +0x4 */
|
||||
unsigned long m_SurfacePitch; /* +0x8 */
|
||||
unsigned long m_DisplayMode; /* +0xc */
|
||||
unsigned long m_Format; /* +0x10 */
|
||||
void *m_InstMem; /* +0x14 */
|
||||
_KINTERRUPT m_InterruptObject; /* +0x18 */
|
||||
_KDPC m_Dpc; /* +0x88 */
|
||||
int m_InterruptsEnabled; /* +0xa4 */
|
||||
D3D::CMiniport::GENERALINFO m_GenInfo; /* +0xa8 */
|
||||
D3D::CMiniport::DACINFO m_DacInfo; /* +0xc4 */
|
||||
D3D::CMiniport::HALINFO m_HalInfo; /* +0x100 */
|
||||
D3D::CMiniport::VIDEOMODETIMING m_VideoModeTiming; /* +0x15c */
|
||||
unsigned long m_VideoModeDepth; /* +0x19c */
|
||||
unsigned long m_FreeInstAddr; /* +0x1a0 */
|
||||
_HAL_SHUTDOWN_REGISTRATION m_ShutdownRegistration; /* +0x1a4 */
|
||||
D3D::CMiniport::VBLANKFLIPS m_VBlankFlips[5]; /* +0x1b4 */
|
||||
unsigned long m_VBlankFlipNext; /* +0x1dc */
|
||||
unsigned long m_VBlankQueueNext; /* +0x1e0 */
|
||||
D3DCALLBACK m_pVerticalBlankCallback; /* +0x1e4 */
|
||||
_KEVENT m_VerticalBlankEvent; /* +0x1e8 */
|
||||
_KEVENT m_BusyBlockEvent; /* +0x1f8 */
|
||||
unsigned long m_CurrentAvInfo; /* +0x208 */
|
||||
int m_FirstFlip; /* +0x20c */
|
||||
volatile unsigned long m_VBlankFlipCount; /* +0x210 */
|
||||
_D3DGAMMARAMP m_GammaRamp[2]; /* +0x214 */
|
||||
int m_GammaUpdated[2]; /* +0x814 */
|
||||
unsigned long m_GammaCurrentIndex; /* +0x81c */
|
||||
volatile unsigned long m_VBlankCount; /* +0x820 */
|
||||
unsigned long m_OverlayVBlank; /* +0x824 */
|
||||
unsigned long m_DebugRegister[11]; /* +0x828 */
|
||||
unsigned long m_PusherGetRunSize; /* +0x854 */
|
||||
|
||||
static unsigned long WINAPI GetPresentFlagsFromAvInfo(
|
||||
unsigned long avInfo);
|
||||
|
||||
static unsigned long WINAPI GetDisplayCapabilities(
|
||||
void);
|
||||
|
||||
void SetVideoMode(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2,
|
||||
unsigned long arg3,
|
||||
_D3DFORMAT arg4,
|
||||
unsigned long arg5,
|
||||
unsigned long arg6);
|
||||
|
||||
void DacProgramGammaRamp(
|
||||
_D3DGAMMARAMP *arg0);
|
||||
|
||||
unsigned long GetRefreshRate(
|
||||
void);
|
||||
|
||||
int IsOddField(
|
||||
void);
|
||||
int IsFlipPending(
|
||||
void);
|
||||
/* Additional original-PDB method declarations. */
|
||||
public:
|
||||
void DacProgramVideoStart(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
int MapRegisters(
|
||||
void);
|
||||
private:
|
||||
void InitGammaRamp(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
unsigned long ReserveInstMem(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
void TmrDelay(
|
||||
unsigned long arg0);
|
||||
/* Remaining methods decoded from the supplied January PDB. */
|
||||
public:
|
||||
int InitHardware(
|
||||
void);
|
||||
public:
|
||||
int InitDMAChannel(
|
||||
unsigned long arg0,
|
||||
D3D::CMiniport::OBJECTINFO *arg1,
|
||||
D3D::CMiniport::OBJECTINFO *arg2,
|
||||
unsigned long arg3,
|
||||
void **arg4);
|
||||
public:
|
||||
int BindToChannel(
|
||||
D3D::CMiniport::OBJECTINFO *arg0);
|
||||
public:
|
||||
int CreateGrObject(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
D3D::CMiniport::OBJECTINFO *arg2);
|
||||
public:
|
||||
int CreateCtxDmaObject(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
void *arg2,
|
||||
unsigned long arg3,
|
||||
D3D::CMiniport::OBJECTINFO *arg4);
|
||||
public:
|
||||
unsigned long SetDmaRange(
|
||||
unsigned long arg0,
|
||||
D3DSurface *arg1);
|
||||
public:
|
||||
int CreateTile(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2,
|
||||
unsigned long arg3,
|
||||
unsigned long arg4,
|
||||
unsigned long arg5,
|
||||
unsigned long arg6);
|
||||
public:
|
||||
int DestroyTile(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1);
|
||||
public:
|
||||
void ShutdownEngines(
|
||||
void);
|
||||
public:
|
||||
void DisableInterrupts(
|
||||
void);
|
||||
public:
|
||||
void EnableInterrupts(
|
||||
void);
|
||||
public:
|
||||
static unsigned char WINAPI Isr(
|
||||
_KINTERRUPT *arg0,
|
||||
void *arg1);
|
||||
public:
|
||||
static void WINAPI Dpc(
|
||||
_KDPC *arg0,
|
||||
void *arg1,
|
||||
void *arg2,
|
||||
void *arg3);
|
||||
public:
|
||||
static void WINAPI ShutdownNotification(
|
||||
_HAL_SHUTDOWN_REGISTRATION *arg0);
|
||||
public:
|
||||
void TilingUpdateIdle(
|
||||
unsigned long *arg0);
|
||||
public:
|
||||
void FixupPushBuffer(
|
||||
D3D::CMiniport::PUSHBUFFERFIXUPINFO *arg0,
|
||||
unsigned long arg1);
|
||||
private:
|
||||
int InitEngines(
|
||||
void);
|
||||
private:
|
||||
int LoadEngines(
|
||||
void);
|
||||
private:
|
||||
int GetGeneralInfo(
|
||||
void);
|
||||
private:
|
||||
void SoftwareMethod(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1);
|
||||
private:
|
||||
void SetupPaletteAndGamma(
|
||||
void);
|
||||
private:
|
||||
void GetAddressInfo(
|
||||
void *arg0,
|
||||
void **arg1,
|
||||
unsigned long *arg2,
|
||||
int arg3);
|
||||
private:
|
||||
unsigned long ServiceGrInterrupt(
|
||||
void);
|
||||
private:
|
||||
unsigned long VBlank(
|
||||
void);
|
||||
private:
|
||||
unsigned long ServiceFifoInterrupt(
|
||||
void);
|
||||
private:
|
||||
unsigned long ServiceMediaPortInterrupt(
|
||||
void);
|
||||
private:
|
||||
unsigned long ServiceVideoInterrupt(
|
||||
void);
|
||||
private:
|
||||
void HalMcControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalFbControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalVideoControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalMpControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalGrControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalGrControlLoad(
|
||||
void);
|
||||
private:
|
||||
void HalGrIdle(
|
||||
void);
|
||||
private:
|
||||
void HalGrLoadChannelContext(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
void HalGrUnloadChannelContext(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
void HalGrInitObjectContext(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1);
|
||||
private:
|
||||
void HalGrInit3d(
|
||||
void);
|
||||
private:
|
||||
void HalFifoControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalFifoControlLoad(
|
||||
void);
|
||||
private:
|
||||
void HalFifoContextSwitch(
|
||||
unsigned long arg0);
|
||||
private:
|
||||
void HalFifoAllocDMA(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2,
|
||||
D3D::CMiniport::OBJECTINFO *arg3);
|
||||
private:
|
||||
void HalFifoHashAdd(
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2,
|
||||
unsigned long arg3,
|
||||
unsigned long arg4);
|
||||
private:
|
||||
void HalDacControlInit(
|
||||
void);
|
||||
private:
|
||||
void HalDacLoad(
|
||||
void);
|
||||
private:
|
||||
void HalDacUnload(
|
||||
void);
|
||||
private:
|
||||
void HalDacProgramMClk(
|
||||
void);
|
||||
private:
|
||||
void HalDacProgramNVClk(
|
||||
void);
|
||||
private:
|
||||
void HalDacProgramPClk(
|
||||
void);
|
||||
private:
|
||||
void DumpClocks(
|
||||
void);
|
||||
private:
|
||||
void GrDone(
|
||||
void);
|
||||
private:
|
||||
unsigned char UnlockCRTC(
|
||||
void);
|
||||
private:
|
||||
void RestoreCRTCLock(
|
||||
unsigned char arg0);
|
||||
private:
|
||||
unsigned char ReadCRTCLock(
|
||||
void);
|
||||
};
|
||||
class CDevice : public D3DDevice
|
||||
{
|
||||
public:
|
||||
static DWORD m_PushBufferSize;
|
||||
static DWORD m_PushSegmentSize;
|
||||
_XMETAL_PushBuffer m_Pusher; /* +0x0 */
|
||||
unsigned long m_DirtyFlags; /* +0x8 */
|
||||
unsigned long m_StateFlags; /* +0xc */
|
||||
unsigned long *m_pPushBase; /* +0x10 */
|
||||
unsigned long *m_pPushLimit; /* +0x14 */
|
||||
unsigned long *m_pKickOff; /* +0x18 */
|
||||
unsigned long m_CpuTime; /* +0x1c */
|
||||
unsigned long m_PusherLastSegment; /* +0x20 */
|
||||
D3D::Fence m_PusherSegment[16]; /* +0x24 */
|
||||
D3D::Fence m_PusherFence[64]; /* +0xe4 */
|
||||
unsigned long m_PusherPutRunSize; /* +0x3e4 */
|
||||
unsigned long m_PusherLastSize; /* +0x3e8 */
|
||||
unsigned long m_LastRunPushBufferTime; /* +0x3ec */
|
||||
volatile unsigned long *m_pGpuTime; /* +0x3f0 */
|
||||
D3DPushBuffer *m_pPushBufferRecordResource; /* +0x3f4 */
|
||||
unsigned long m_PushBufferRecordWrapSize; /* +0x3f8 */
|
||||
unsigned long *m_pPushBufferRecordSavedThreshold; /* +0x3fc */
|
||||
unsigned long *m_pPushBufferRecordSavedPut; /* +0x400 */
|
||||
D3D::_HWREG *m_NvBase; /* +0x404 */
|
||||
unsigned long m_cRefs; /* +0x408 */
|
||||
D3DSurface *m_pRenderTarget; /* +0x40c */
|
||||
D3DSurface *m_pZBuffer; /* +0x410 */
|
||||
D3D::PixelShader *m_pPixelShader; /* +0x414 */
|
||||
unsigned long m_ShaderUsesSpecFog; /* +0x418 */
|
||||
unsigned long m_ShaderAdjustsTexMode; /* +0x41c */
|
||||
unsigned long m_PSShaderStageProgram; /* +0x420 */
|
||||
unsigned long m_pPixelShaderConstants[16]; /* +0x424 */
|
||||
D3D::PixelShader m_UserPixelShader; /* +0x464 */
|
||||
D3D::VertexShader *m_pVertexShader; /* +0x470 */
|
||||
unsigned long m_VertexShaderHandle; /* +0x474 */
|
||||
unsigned int m_IndexBase; /* +0x478 */
|
||||
D3DIndexBuffer *m_pIndexBuffer; /* +0x47c */
|
||||
D3D::Light *m_pLights; /* +0x480 */
|
||||
unsigned long m_LightCount; /* +0x484 */
|
||||
D3D::Light *m_pActiveLights; /* +0x488 */
|
||||
void *m_ReportAllocations[16]; /* +0x48c */
|
||||
unsigned long m_TextureControl0Enabled[4]; /* +0x4cc */
|
||||
unsigned long m_TextureCubemapAndDimension[4]; /* +0x4dc */
|
||||
float m_WNear; /* +0x4ec */
|
||||
float m_WFar; /* +0x4f0 */
|
||||
float m_InverseWFar; /* +0x4f4 */
|
||||
float m_ZScale; /* +0x4f8 */
|
||||
unsigned long m_TexGenInverseNeeded; /* +0x4fc */
|
||||
float m_SuperSampleScaleX; /* +0x500 */
|
||||
float m_SuperSampleScaleY; /* +0x504 */
|
||||
float m_SuperSampleScale; /* +0x508 */
|
||||
float m_SuperSampleLODBias; /* +0x50c */
|
||||
unsigned long m_AlphaICW[8]; /* +0x510 */
|
||||
unsigned long m_AlphaOCW[8]; /* +0x530 */
|
||||
unsigned long m_ColorICW[8]; /* +0x550 */
|
||||
unsigned long m_ColorOCW[8]; /* +0x570 */
|
||||
unsigned long m_CombinerFlags; /* +0x590 */
|
||||
unsigned long m_ActiveCombinerStagesCount; /* +0x594 */
|
||||
unsigned long m_CachedIndexBase; /* +0x598 */
|
||||
BYTE reserved_059c[4]; /* Original layout gap. */
|
||||
_D3DMATRIX m_ProjectionViewportTransform; /* +0x5a0 */
|
||||
_D3DMATRIX m_ModelViewTransform[4]; /* +0x5e0 */
|
||||
_D3DMATRIX m_ProjectionViewport; /* +0x6e0 */
|
||||
unsigned long m_VertexShaderInputHandle; /* +0x720 */
|
||||
unsigned long m_VertexShaderInputCount; /* +0x724 */
|
||||
_D3DSTREAM_INPUT m_VertexShaderInputStream[16]; /* +0x728 */
|
||||
unsigned long m_InlineVertexDwords; /* +0x7e8 */
|
||||
unsigned long m_InlineStartOffset; /* +0x7ec */
|
||||
unsigned long m_InlineDelta; /* +0x7f0 */
|
||||
D3D::InlineAttributeData m_InlineAttributeData[16]; /* +0x7f4 */
|
||||
unsigned long m_InlineAttributeCount; /* +0x874 */
|
||||
BYTE reserved_0878[8]; /* Original layout gap. */
|
||||
_D3DMATRIX m_Transform[10]; /* +0x880 */
|
||||
_D3DVIEWPORT8 m_Viewport; /* +0xb00 */
|
||||
_D3DMATERIAL8 m_Material; /* +0xb18 */
|
||||
_D3DMATERIAL8 m_BackMaterial; /* +0xb5c */
|
||||
D3DBaseTexture *m_Textures[4]; /* +0xba0 */
|
||||
D3DPalette *m_Palettes[4]; /* +0xbb0 */
|
||||
float m_PixelShaderConstants[16][4]; /* +0xbc0 */
|
||||
float m_VertexShaderConstants[192][4]; /* +0xcc0 */
|
||||
unsigned long m_VertexShaderProgramSlots[136][4]; /* +0x18c0 */
|
||||
unsigned long m_ConstantMode; /* +0x2140 */
|
||||
void *m_pFrameBufferBase; /* +0x2144 */
|
||||
void *m_pAntiAliasBufferBase; /* +0x2148 */
|
||||
unsigned long m_FrameBufferCount; /* +0x214c */
|
||||
D3DSurface m_FrameBufferSurfaces[3]; /* +0x2150 */
|
||||
void *m_pAutoDepthBuffer; /* +0x2198 */
|
||||
D3DSurface m_AutoDepthSurface; /* +0x219c */
|
||||
unsigned long m_DisplayWidth; /* +0x21b4 */
|
||||
unsigned long m_DisplayHeight; /* +0x21b8 */
|
||||
_D3DTILE m_Tile[8]; /* +0x21bc */
|
||||
_D3DRECT m_ScissorsRects[8]; /* +0x227c */
|
||||
unsigned long m_ScissorsCount; /* +0x22fc */
|
||||
int m_ScissorsExclusive; /* +0x2300 */
|
||||
volatile Nv206eControl *m_pControlDma; /* +0x2304 */
|
||||
D3D::CMiniport m_Miniport; /* +0x2308 */
|
||||
unsigned long m_PresentCount; /* +0x2b60 */
|
||||
unsigned long m_PresentationInterval; /* +0x2b64 */
|
||||
unsigned long m_dwOpcode; /* +0x2b68 */
|
||||
unsigned long m_dwSnapshot; /* +0x2b6c */
|
||||
unsigned long *m_pShaderCaptureBuffer; /* +0x2b70 */
|
||||
unsigned long *m_pShaderCapturePtr; /* +0x2b74 */
|
||||
unsigned long m_ColorContextDmaInstance; /* +0x2b78 */
|
||||
unsigned long m_ZetaContextDmaInstance; /* +0x2b7c */
|
||||
unsigned long m_CopyContextDmaInstance; /* +0x2b80 */
|
||||
unsigned char *m_pCachedContiguousMemoryBase; /* +0x2b84 */
|
||||
volatile NvNotification *m_pMemCopyNotifiers; /* +0x2b88 */
|
||||
volatile NvNotification *m_pKelvinNotifiers; /* +0x2b8c */
|
||||
long Init(
|
||||
_D3DPRESENT_PARAMETERS_ *arg0);
|
||||
void UnInit(
|
||||
void);
|
||||
long InitializeFrameBuffers(
|
||||
_D3DPRESENT_PARAMETERS_ *arg0);
|
||||
void FreeFrameBuffers(
|
||||
void);
|
||||
void SetStateUP(
|
||||
void);
|
||||
void SetStateVB(
|
||||
unsigned long arg0);
|
||||
unsigned long *StartPush(
|
||||
unsigned long arg0);
|
||||
unsigned long *StartPush(
|
||||
void);
|
||||
void StartBeginEndBracket(
|
||||
void);
|
||||
void EndBeginEndBracket(
|
||||
void);
|
||||
void EndPush(
|
||||
unsigned long *arg0);
|
||||
void KickOff(
|
||||
void);
|
||||
void InitializePushBuffer(
|
||||
void);
|
||||
unsigned long *MakeSpace(
|
||||
void);
|
||||
void HwPut(
|
||||
unsigned long *arg0);
|
||||
unsigned long *HwGet(
|
||||
void);
|
||||
unsigned long *GpuGet(
|
||||
void);
|
||||
unsigned long GpuTime(
|
||||
void);
|
||||
unsigned long Age(
|
||||
unsigned long arg0);
|
||||
int IsTimePending(
|
||||
unsigned long arg0);
|
||||
void RecordResourceReadPush(
|
||||
D3DResource *arg0);
|
||||
void RecordSurfaceWritePush(
|
||||
D3DResource *arg0);
|
||||
};
|
||||
extern CDevice *g_pDevice;
|
||||
extern CDevice g_Device;
|
||||
extern const D3DCAPS8 g_DeviceCaps;
|
||||
extern const D3DADAPTER_IDENTIFIER8 g_AdapterIdentifier;
|
||||
}
|
||||
typedef char D3D_CDevice_size_check[sizeof(D3D::CDevice) == 11152 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Pusher_offset_check[offsetof(D3D::CDevice, m_Pusher) == 0x0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_DirtyFlags_offset_check[offsetof(D3D::CDevice, m_DirtyFlags) == 0x8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_StateFlags_offset_check[offsetof(D3D::CDevice, m_StateFlags) == 0xc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPushBase_offset_check[offsetof(D3D::CDevice, m_pPushBase) == 0x10 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPushLimit_offset_check[offsetof(D3D::CDevice, m_pPushLimit) == 0x14 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pKickOff_offset_check[offsetof(D3D::CDevice, m_pKickOff) == 0x18 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_CpuTime_offset_check[offsetof(D3D::CDevice, m_CpuTime) == 0x1c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PusherLastSegment_offset_check[offsetof(D3D::CDevice, m_PusherLastSegment) == 0x20 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PusherSegment_offset_check[offsetof(D3D::CDevice, m_PusherSegment) == 0x24 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PusherFence_offset_check[offsetof(D3D::CDevice, m_PusherFence) == 0xe4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PusherPutRunSize_offset_check[offsetof(D3D::CDevice, m_PusherPutRunSize) == 0x3e4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PusherLastSize_offset_check[offsetof(D3D::CDevice, m_PusherLastSize) == 0x3e8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_LastRunPushBufferTime_offset_check[offsetof(D3D::CDevice, m_LastRunPushBufferTime) == 0x3ec ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pGpuTime_offset_check[offsetof(D3D::CDevice, m_pGpuTime) == 0x3f0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPushBufferRecordResource_offset_check[offsetof(D3D::CDevice, m_pPushBufferRecordResource) == 0x3f4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PushBufferRecordWrapSize_offset_check[offsetof(D3D::CDevice, m_PushBufferRecordWrapSize) == 0x3f8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPushBufferRecordSavedThreshold_offset_check[offsetof(D3D::CDevice, m_pPushBufferRecordSavedThreshold) == 0x3fc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPushBufferRecordSavedPut_offset_check[offsetof(D3D::CDevice, m_pPushBufferRecordSavedPut) == 0x400 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_NvBase_offset_check[offsetof(D3D::CDevice, m_NvBase) == 0x404 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_cRefs_offset_check[offsetof(D3D::CDevice, m_cRefs) == 0x408 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pRenderTarget_offset_check[offsetof(D3D::CDevice, m_pRenderTarget) == 0x40c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pZBuffer_offset_check[offsetof(D3D::CDevice, m_pZBuffer) == 0x410 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPixelShader_offset_check[offsetof(D3D::CDevice, m_pPixelShader) == 0x414 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ShaderUsesSpecFog_offset_check[offsetof(D3D::CDevice, m_ShaderUsesSpecFog) == 0x418 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ShaderAdjustsTexMode_offset_check[offsetof(D3D::CDevice, m_ShaderAdjustsTexMode) == 0x41c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PSShaderStageProgram_offset_check[offsetof(D3D::CDevice, m_PSShaderStageProgram) == 0x420 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pPixelShaderConstants_offset_check[offsetof(D3D::CDevice, m_pPixelShaderConstants) == 0x424 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_UserPixelShader_offset_check[offsetof(D3D::CDevice, m_UserPixelShader) == 0x464 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pVertexShader_offset_check[offsetof(D3D::CDevice, m_pVertexShader) == 0x470 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderHandle_offset_check[offsetof(D3D::CDevice, m_VertexShaderHandle) == 0x474 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_IndexBase_offset_check[offsetof(D3D::CDevice, m_IndexBase) == 0x478 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pIndexBuffer_offset_check[offsetof(D3D::CDevice, m_pIndexBuffer) == 0x47c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pLights_offset_check[offsetof(D3D::CDevice, m_pLights) == 0x480 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_LightCount_offset_check[offsetof(D3D::CDevice, m_LightCount) == 0x484 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pActiveLights_offset_check[offsetof(D3D::CDevice, m_pActiveLights) == 0x488 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ReportAllocations_offset_check[offsetof(D3D::CDevice, m_ReportAllocations) == 0x48c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_TextureControl0Enabled_offset_check[offsetof(D3D::CDevice, m_TextureControl0Enabled) == 0x4cc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_TextureCubemapAndDimension_offset_check[offsetof(D3D::CDevice, m_TextureCubemapAndDimension) == 0x4dc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_WNear_offset_check[offsetof(D3D::CDevice, m_WNear) == 0x4ec ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_WFar_offset_check[offsetof(D3D::CDevice, m_WFar) == 0x4f0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InverseWFar_offset_check[offsetof(D3D::CDevice, m_InverseWFar) == 0x4f4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ZScale_offset_check[offsetof(D3D::CDevice, m_ZScale) == 0x4f8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_TexGenInverseNeeded_offset_check[offsetof(D3D::CDevice, m_TexGenInverseNeeded) == 0x4fc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_SuperSampleScaleX_offset_check[offsetof(D3D::CDevice, m_SuperSampleScaleX) == 0x500 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_SuperSampleScaleY_offset_check[offsetof(D3D::CDevice, m_SuperSampleScaleY) == 0x504 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_SuperSampleScale_offset_check[offsetof(D3D::CDevice, m_SuperSampleScale) == 0x508 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_SuperSampleLODBias_offset_check[offsetof(D3D::CDevice, m_SuperSampleLODBias) == 0x50c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_AlphaICW_offset_check[offsetof(D3D::CDevice, m_AlphaICW) == 0x510 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_AlphaOCW_offset_check[offsetof(D3D::CDevice, m_AlphaOCW) == 0x530 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ColorICW_offset_check[offsetof(D3D::CDevice, m_ColorICW) == 0x550 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ColorOCW_offset_check[offsetof(D3D::CDevice, m_ColorOCW) == 0x570 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_CombinerFlags_offset_check[offsetof(D3D::CDevice, m_CombinerFlags) == 0x590 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ActiveCombinerStagesCount_offset_check[offsetof(D3D::CDevice, m_ActiveCombinerStagesCount) == 0x594 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_CachedIndexBase_offset_check[offsetof(D3D::CDevice, m_CachedIndexBase) == 0x598 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ProjectionViewportTransform_offset_check[offsetof(D3D::CDevice, m_ProjectionViewportTransform) == 0x5a0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ModelViewTransform_offset_check[offsetof(D3D::CDevice, m_ModelViewTransform) == 0x5e0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ProjectionViewport_offset_check[offsetof(D3D::CDevice, m_ProjectionViewport) == 0x6e0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderInputHandle_offset_check[offsetof(D3D::CDevice, m_VertexShaderInputHandle) == 0x720 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderInputCount_offset_check[offsetof(D3D::CDevice, m_VertexShaderInputCount) == 0x724 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderInputStream_offset_check[offsetof(D3D::CDevice, m_VertexShaderInputStream) == 0x728 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InlineVertexDwords_offset_check[offsetof(D3D::CDevice, m_InlineVertexDwords) == 0x7e8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InlineStartOffset_offset_check[offsetof(D3D::CDevice, m_InlineStartOffset) == 0x7ec ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InlineDelta_offset_check[offsetof(D3D::CDevice, m_InlineDelta) == 0x7f0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InlineAttributeData_offset_check[offsetof(D3D::CDevice, m_InlineAttributeData) == 0x7f4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_InlineAttributeCount_offset_check[offsetof(D3D::CDevice, m_InlineAttributeCount) == 0x874 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Transform_offset_check[offsetof(D3D::CDevice, m_Transform) == 0x880 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Viewport_offset_check[offsetof(D3D::CDevice, m_Viewport) == 0xb00 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Material_offset_check[offsetof(D3D::CDevice, m_Material) == 0xb18 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_BackMaterial_offset_check[offsetof(D3D::CDevice, m_BackMaterial) == 0xb5c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Textures_offset_check[offsetof(D3D::CDevice, m_Textures) == 0xba0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Palettes_offset_check[offsetof(D3D::CDevice, m_Palettes) == 0xbb0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PixelShaderConstants_offset_check[offsetof(D3D::CDevice, m_PixelShaderConstants) == 0xbc0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderConstants_offset_check[offsetof(D3D::CDevice, m_VertexShaderConstants) == 0xcc0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_VertexShaderProgramSlots_offset_check[offsetof(D3D::CDevice, m_VertexShaderProgramSlots) == 0x18c0 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ConstantMode_offset_check[offsetof(D3D::CDevice, m_ConstantMode) == 0x2140 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pFrameBufferBase_offset_check[offsetof(D3D::CDevice, m_pFrameBufferBase) == 0x2144 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pAntiAliasBufferBase_offset_check[offsetof(D3D::CDevice, m_pAntiAliasBufferBase) == 0x2148 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_FrameBufferCount_offset_check[offsetof(D3D::CDevice, m_FrameBufferCount) == 0x214c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_FrameBufferSurfaces_offset_check[offsetof(D3D::CDevice, m_FrameBufferSurfaces) == 0x2150 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pAutoDepthBuffer_offset_check[offsetof(D3D::CDevice, m_pAutoDepthBuffer) == 0x2198 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_AutoDepthSurface_offset_check[offsetof(D3D::CDevice, m_AutoDepthSurface) == 0x219c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_DisplayWidth_offset_check[offsetof(D3D::CDevice, m_DisplayWidth) == 0x21b4 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_DisplayHeight_offset_check[offsetof(D3D::CDevice, m_DisplayHeight) == 0x21b8 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Tile_offset_check[offsetof(D3D::CDevice, m_Tile) == 0x21bc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ScissorsRects_offset_check[offsetof(D3D::CDevice, m_ScissorsRects) == 0x227c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ScissorsCount_offset_check[offsetof(D3D::CDevice, m_ScissorsCount) == 0x22fc ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ScissorsExclusive_offset_check[offsetof(D3D::CDevice, m_ScissorsExclusive) == 0x2300 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pControlDma_offset_check[offsetof(D3D::CDevice, m_pControlDma) == 0x2304 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_Miniport_offset_check[offsetof(D3D::CDevice, m_Miniport) == 0x2308 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PresentCount_offset_check[offsetof(D3D::CDevice, m_PresentCount) == 0x2b60 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_PresentationInterval_offset_check[offsetof(D3D::CDevice, m_PresentationInterval) == 0x2b64 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_dwOpcode_offset_check[offsetof(D3D::CDevice, m_dwOpcode) == 0x2b68 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_dwSnapshot_offset_check[offsetof(D3D::CDevice, m_dwSnapshot) == 0x2b6c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pShaderCaptureBuffer_offset_check[offsetof(D3D::CDevice, m_pShaderCaptureBuffer) == 0x2b70 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pShaderCapturePtr_offset_check[offsetof(D3D::CDevice, m_pShaderCapturePtr) == 0x2b74 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ColorContextDmaInstance_offset_check[offsetof(D3D::CDevice, m_ColorContextDmaInstance) == 0x2b78 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_ZetaContextDmaInstance_offset_check[offsetof(D3D::CDevice, m_ZetaContextDmaInstance) == 0x2b7c ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_CopyContextDmaInstance_offset_check[offsetof(D3D::CDevice, m_CopyContextDmaInstance) == 0x2b80 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pCachedContiguousMemoryBase_offset_check[offsetof(D3D::CDevice, m_pCachedContiguousMemoryBase) == 0x2b84 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pMemCopyNotifiers_offset_check[offsetof(D3D::CDevice, m_pMemCopyNotifiers) == 0x2b88 ? 1 : -1];
|
||||
typedef char D3D_CDevice_m_pKelvinNotifiers_offset_check[offsetof(D3D::CDevice, m_pKelvinNotifiers) == 0x2b8c ? 1 : -1];
|
||||
typedef char D3D_CMiniport_size_check[sizeof(D3D::CMiniport) == 2136 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_RegisterBase_offset_check[offsetof(D3D::CMiniport, m_RegisterBase) == 0x0 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_PresentationInterval_offset_check[offsetof(D3D::CMiniport, m_PresentationInterval) == 0x4 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_SurfacePitch_offset_check[offsetof(D3D::CMiniport, m_SurfacePitch) == 0x8 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_DisplayMode_offset_check[offsetof(D3D::CMiniport, m_DisplayMode) == 0xc ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_Format_offset_check[offsetof(D3D::CMiniport, m_Format) == 0x10 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_InstMem_offset_check[offsetof(D3D::CMiniport, m_InstMem) == 0x14 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_InterruptsEnabled_offset_check[offsetof(D3D::CMiniport, m_InterruptsEnabled) == 0xa4 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_GenInfo_offset_check[offsetof(D3D::CMiniport, m_GenInfo) == 0xa8 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_DacInfo_offset_check[offsetof(D3D::CMiniport, m_DacInfo) == 0xc4 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_HalInfo_offset_check[offsetof(D3D::CMiniport, m_HalInfo) == 0x100 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VideoModeTiming_offset_check[offsetof(D3D::CMiniport, m_VideoModeTiming) == 0x15c ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VideoModeDepth_offset_check[offsetof(D3D::CMiniport, m_VideoModeDepth) == 0x19c ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_FreeInstAddr_offset_check[offsetof(D3D::CMiniport, m_FreeInstAddr) == 0x1a0 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VBlankFlips_offset_check[offsetof(D3D::CMiniport, m_VBlankFlips) == 0x1b4 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VBlankFlipNext_offset_check[offsetof(D3D::CMiniport, m_VBlankFlipNext) == 0x1dc ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VBlankQueueNext_offset_check[offsetof(D3D::CMiniport, m_VBlankQueueNext) == 0x1e0 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_pVerticalBlankCallback_offset_check[offsetof(D3D::CMiniport, m_pVerticalBlankCallback) == 0x1e4 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_CurrentAvInfo_offset_check[offsetof(D3D::CMiniport, m_CurrentAvInfo) == 0x208 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_FirstFlip_offset_check[offsetof(D3D::CMiniport, m_FirstFlip) == 0x20c ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VBlankFlipCount_offset_check[offsetof(D3D::CMiniport, m_VBlankFlipCount) == 0x210 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_GammaRamp_offset_check[offsetof(D3D::CMiniport, m_GammaRamp) == 0x214 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_GammaUpdated_offset_check[offsetof(D3D::CMiniport, m_GammaUpdated) == 0x814 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_GammaCurrentIndex_offset_check[offsetof(D3D::CMiniport, m_GammaCurrentIndex) == 0x81c ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_VBlankCount_offset_check[offsetof(D3D::CMiniport, m_VBlankCount) == 0x820 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_OverlayVBlank_offset_check[offsetof(D3D::CMiniport, m_OverlayVBlank) == 0x824 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_DebugRegister_offset_check[offsetof(D3D::CMiniport, m_DebugRegister) == 0x828 ? 1 : -1];
|
||||
typedef char D3D_CMiniport_m_PusherGetRunSize_offset_check[offsetof(D3D::CMiniport, m_PusherGetRunSize) == 0x854 ? 1 : -1];
|
||||
typedef char D3D_Light_size_check[sizeof(D3D::Light) == 144 ? 1 : -1];
|
||||
typedef char D3D_Light_Light8_offset_check[offsetof(D3D::Light, Light8) == 0x0 ? 1 : -1];
|
||||
typedef char D3D_Light_Flags_offset_check[offsetof(D3D::Light, Flags) == 0x68 ? 1 : -1];
|
||||
typedef char D3D_Light_Direction_offset_check[offsetof(D3D::Light, Direction) == 0x6c ? 1 : -1];
|
||||
typedef char D3D_Light_Falloff_L_offset_check[offsetof(D3D::Light, Falloff_L) == 0x78 ? 1 : -1];
|
||||
typedef char D3D_Light_Falloff_M_offset_check[offsetof(D3D::Light, Falloff_M) == 0x7c ? 1 : -1];
|
||||
typedef char D3D_Light_Falloff_N_offset_check[offsetof(D3D::Light, Falloff_N) == 0x80 ? 1 : -1];
|
||||
typedef char D3D_Light_Scale_offset_check[offsetof(D3D::Light, Scale) == 0x84 ? 1 : -1];
|
||||
typedef char D3D_Light_W_offset_check[offsetof(D3D::Light, W) == 0x88 ? 1 : -1];
|
||||
typedef char D3D_Light_pNext_offset_check[offsetof(D3D::Light, pNext) == 0x8c ? 1 : -1];
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef D3D8_DISPLAY_INTERNAL_H
|
||||
#define D3D8_DISPLAY_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
#include <conio.h>
|
||||
#pragma intrinsic(_inp)
|
||||
extern "C" DWORD D3D__AvInfo;
|
||||
extern "C" __declspec(dllimport) void *WINAPI AvGetSavedDataAddress(
|
||||
void);
|
||||
extern "C" __declspec(dllimport) void WINAPI AvSendTVEncoderOption(
|
||||
void *registerBase,
|
||||
DWORD option,
|
||||
DWORD parameter,
|
||||
DWORD *result);
|
||||
extern "C" __declspec(dllimport) DWORD WINAPI AvSetDisplayMode(
|
||||
void *registerBase,
|
||||
DWORD step,
|
||||
DWORD displayMode,
|
||||
DWORD sourceColorFormat,
|
||||
DWORD pitch,
|
||||
DWORD frameBuffer);
|
||||
extern "C" __declspec(dllimport) void WINAPI AvSetSavedDataAddress(
|
||||
void *address);
|
||||
namespace D3D
|
||||
{
|
||||
/* Field widths and stride from the original PDB. AV masks are independently
|
||||
* corroborated by the target enumeration instructions. */
|
||||
struct DISPLAYMODE
|
||||
{
|
||||
DWORD AvInfo;
|
||||
WORD Width;
|
||||
WORD Height;
|
||||
DWORD DisplayMode;
|
||||
};
|
||||
typedef char DisplayModeSize[sizeof(DISPLAYMODE) == 12 ? 1 : -1];
|
||||
const DISPLAYMODE *WINAPI GetTableForCurrentAvInfo(
|
||||
void);
|
||||
extern const D3DADAPTER_IDENTIFIER8 g_AdapterIdentifier;
|
||||
extern const DISPLAYMODE g_DisplayModes[191];
|
||||
extern const DWORD g_DisplayModeCount;
|
||||
__inline DWORD CMiniport::GetRefreshRate(
|
||||
void)
|
||||
{
|
||||
return (m_CurrentAvInfo & 0x400000) ? 60 : 50;
|
||||
}
|
||||
/* The January odd-field GPIO reports the inverse of bit 5. This method is
|
||||
* shared by actual ISR and vblank callers; no artificial emission anchor. */
|
||||
__inline int CMiniport::IsOddField(
|
||||
void)
|
||||
{
|
||||
return (~((DWORD)_inp(0x80c0) >> 5)) & 1;
|
||||
}
|
||||
enum
|
||||
{
|
||||
AV_OPTION_BLANK_SCREEN = 9,
|
||||
AV_OPTION_FLICKER_FILTER = 11,
|
||||
AV_OPTION_SOFT_DISPLAY_FILTER = 14,
|
||||
AV_PACK_MASK = 0xff,
|
||||
AV_PACK_NONE = 0,
|
||||
AV_STANDARD_MASK = 0xff00,
|
||||
AV_FLAGS_INTERLACED = 0x00200000,
|
||||
AV_FLAGS_FIELD = 0x01000000,
|
||||
AV_FLAGS_10x11PAR = 0x02000000,
|
||||
AV_FLAGS_50Hz = 0x00800000,
|
||||
AV_PACK_HDTV = 4,
|
||||
AV_FLAGS_WIDESCREEN = 0x10000,
|
||||
AV_FLAGS_HDTV_720p = 0x20000,
|
||||
AV_FLAGS_HDTV_1080i = 0x40000,
|
||||
AV_HDTV_MODE_MASK = 0xe0000,
|
||||
AV_REFRESH_MASK = 0xc00000,
|
||||
AV_FLAGS_60Hz = 0x400000
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
/* Original January display-mode data: {AvInfo, Width, Height, DisplayMode}.
|
||||
* These 191 records are configuration data, not native instructions. */
|
||||
{0x00400105UL, 640, 480, 0x88070701UL}, /* 0 */
|
||||
{0x00400105UL, 720, 480, 0x88080801UL}, /* 1 */
|
||||
{0x00400105UL, 1280, 720, 0x880b0a02UL}, /* 2 */
|
||||
{0x00400105UL, 1920, 1080, 0x880e0c03UL}, /* 3 */
|
||||
{0x00480104UL, 640, 480, 0x88070701UL}, /* 4 */
|
||||
{0x00490104UL, 640, 480, 0x88070701UL}, /* 5 */
|
||||
{0x00480104UL, 720, 480, 0x88080801UL}, /* 6 */
|
||||
{0x00490104UL, 720, 480, 0x88080801UL}, /* 7 */
|
||||
{0x02480104UL, 640, 480, 0x88110f01UL}, /* 8 */
|
||||
{0x02490104UL, 640, 480, 0x88110f01UL}, /* 9 */
|
||||
{0x00430104UL, 1280, 720, 0x880b0a02UL}, /* 10 */
|
||||
{0x00600104UL, 640, 480, 0x0801010dUL}, /* 11 */
|
||||
{0x00610104UL, 640, 480, 0x1801010dUL}, /* 12 */
|
||||
{0x00600104UL, 720, 480, 0x0802020eUL}, /* 13 */
|
||||
{0x00610104UL, 720, 480, 0x1802020eUL}, /* 14 */
|
||||
{0x01400104UL, 640, 240, 0x0801010dUL}, /* 15 */
|
||||
{0x01410104UL, 640, 240, 0x1801010dUL}, /* 16 */
|
||||
{0x01400104UL, 720, 240, 0x0802020eUL}, /* 17 */
|
||||
{0x01410104UL, 720, 240, 0x1802020eUL}, /* 18 */
|
||||
{0x02600104UL, 640, 480, 0x080f0d12UL}, /* 19 */
|
||||
{0x02610104UL, 640, 480, 0x180f0d12UL}, /* 20 */
|
||||
{0x03400104UL, 640, 240, 0x080f0d12UL}, /* 21 */
|
||||
{0x03410104UL, 640, 240, 0x180f0d12UL}, /* 22 */
|
||||
{0x00650104UL, 1920, 1080, 0x880e0c03UL}, /* 23 */
|
||||
{0x01450104UL, 1920, 540, 0x880e0c03UL}, /* 24 */
|
||||
{0x00600103UL, 640, 480, 0x20010101UL}, /* 25 */
|
||||
{0x00610103UL, 640, 480, 0x30010101UL}, /* 26 */
|
||||
{0x00600103UL, 720, 480, 0x20020202UL}, /* 27 */
|
||||
{0x00610103UL, 720, 480, 0x30020202UL}, /* 28 */
|
||||
{0x01400103UL, 640, 240, 0x20010101UL}, /* 29 */
|
||||
{0x01410103UL, 640, 240, 0x30010101UL}, /* 30 */
|
||||
{0x01400103UL, 720, 240, 0x20020202UL}, /* 31 */
|
||||
{0x01410103UL, 720, 240, 0x30020202UL}, /* 32 */
|
||||
{0x02600103UL, 640, 480, 0x200f0d0fUL}, /* 33 */
|
||||
{0x02610103UL, 640, 480, 0x300f0d0fUL}, /* 34 */
|
||||
{0x03400103UL, 640, 240, 0x200f0d0fUL}, /* 35 */
|
||||
{0x03410103UL, 640, 240, 0x300f0d0fUL}, /* 36 */
|
||||
{0x00600100UL, 640, 480, 0x04010101UL}, /* 37 */
|
||||
{0x00610100UL, 640, 480, 0x14010101UL}, /* 38 */
|
||||
{0x00600100UL, 720, 480, 0x04020202UL}, /* 39 */
|
||||
{0x00610100UL, 720, 480, 0x14020202UL}, /* 40 */
|
||||
{0x01400100UL, 640, 240, 0x04010101UL}, /* 41 */
|
||||
{0x01410100UL, 640, 240, 0x14010101UL}, /* 42 */
|
||||
{0x01400100UL, 720, 240, 0x04020202UL}, /* 43 */
|
||||
{0x01410100UL, 720, 240, 0x14020202UL}, /* 44 */
|
||||
{0x02600100UL, 640, 480, 0x040f0d0fUL}, /* 45 */
|
||||
{0x02610100UL, 640, 480, 0x140f0d0fUL}, /* 46 */
|
||||
{0x03400100UL, 640, 240, 0x040f0d0fUL}, /* 47 */
|
||||
{0x03410100UL, 640, 240, 0x140f0d0fUL}, /* 48 */
|
||||
{0x00400205UL, 640, 480, 0x88070701UL}, /* 49 */
|
||||
{0x00400205UL, 720, 480, 0x88080801UL}, /* 50 */
|
||||
{0x00400205UL, 1280, 720, 0x880b0a02UL}, /* 51 */
|
||||
{0x00400205UL, 1920, 1080, 0x880e0c03UL}, /* 52 */
|
||||
{0x00480204UL, 640, 480, 0x88070701UL}, /* 53 */
|
||||
{0x00490204UL, 640, 480, 0x88070701UL}, /* 54 */
|
||||
{0x00480204UL, 720, 480, 0x88080801UL}, /* 55 */
|
||||
{0x00490204UL, 720, 480, 0x88080801UL}, /* 56 */
|
||||
{0x00430204UL, 1280, 720, 0x880b0a02UL}, /* 57 */
|
||||
{0x00600204UL, 640, 480, 0x0801010dUL}, /* 58 */
|
||||
{0x00610204UL, 640, 480, 0x1801010dUL}, /* 59 */
|
||||
{0x00600204UL, 720, 480, 0x0802020eUL}, /* 60 */
|
||||
{0x00610204UL, 720, 480, 0x1802020eUL}, /* 61 */
|
||||
{0x01400204UL, 640, 240, 0x0801010dUL}, /* 62 */
|
||||
{0x01410204UL, 640, 240, 0x1801010dUL}, /* 63 */
|
||||
{0x01400204UL, 720, 240, 0x0802020eUL}, /* 64 */
|
||||
{0x01410204UL, 720, 240, 0x1802020eUL}, /* 65 */
|
||||
{0x02600204UL, 640, 480, 0x080f0d12UL}, /* 66 */
|
||||
{0x02610204UL, 640, 480, 0x180f0d12UL}, /* 67 */
|
||||
{0x03400204UL, 640, 240, 0x080f0d12UL}, /* 68 */
|
||||
{0x03410204UL, 640, 240, 0x180f0d12UL}, /* 69 */
|
||||
{0x00650204UL, 1920, 1080, 0x880e0c03UL}, /* 70 */
|
||||
{0x01450204UL, 1920, 540, 0x880e0c03UL}, /* 71 */
|
||||
{0x00600203UL, 640, 480, 0x20010103UL}, /* 72 */
|
||||
{0x00610203UL, 640, 480, 0x30010103UL}, /* 73 */
|
||||
{0x00600203UL, 720, 480, 0x20020204UL}, /* 74 */
|
||||
{0x00610203UL, 720, 480, 0x30020204UL}, /* 75 */
|
||||
{0x01400203UL, 640, 240, 0x20010103UL}, /* 76 */
|
||||
{0x01410203UL, 640, 240, 0x30010103UL}, /* 77 */
|
||||
{0x01400203UL, 720, 240, 0x20020204UL}, /* 78 */
|
||||
{0x01410203UL, 720, 240, 0x30020204UL}, /* 79 */
|
||||
{0x02600203UL, 640, 480, 0x200f0d10UL}, /* 80 */
|
||||
{0x02610203UL, 640, 480, 0x300f0d10UL}, /* 81 */
|
||||
{0x03400203UL, 640, 240, 0x200f0d10UL}, /* 82 */
|
||||
{0x03410203UL, 640, 240, 0x300f0d10UL}, /* 83 */
|
||||
{0x00600200UL, 640, 480, 0x04010103UL}, /* 84 */
|
||||
{0x00610200UL, 640, 480, 0x14010103UL}, /* 85 */
|
||||
{0x00600200UL, 720, 480, 0x04020204UL}, /* 86 */
|
||||
{0x00610200UL, 720, 480, 0x14020204UL}, /* 87 */
|
||||
{0x01400200UL, 640, 240, 0x04010103UL}, /* 88 */
|
||||
{0x01410200UL, 640, 240, 0x14010103UL}, /* 89 */
|
||||
{0x01400200UL, 720, 240, 0x04020204UL}, /* 90 */
|
||||
{0x01410200UL, 720, 240, 0x14020204UL}, /* 91 */
|
||||
{0x02600200UL, 640, 480, 0x040f0d10UL}, /* 92 */
|
||||
{0x02610200UL, 640, 480, 0x140f0d10UL}, /* 93 */
|
||||
{0x03400200UL, 640, 240, 0x040f0d10UL}, /* 94 */
|
||||
{0x03410200UL, 640, 240, 0x140f0d10UL}, /* 95 */
|
||||
{0x00400305UL, 640, 480, 0x88070701UL}, /* 96 */
|
||||
{0x00400305UL, 720, 480, 0x88080801UL}, /* 97 */
|
||||
{0x00400305UL, 1280, 720, 0x880b0a02UL}, /* 98 */
|
||||
{0x00400305UL, 1920, 1080, 0x880e0c03UL}, /* 99 */
|
||||
{0x00a00304UL, 640, 480, 0x48030314UL}, /* 100 */
|
||||
{0x00a10304UL, 640, 480, 0x58030314UL}, /* 101 */
|
||||
{0x00a00304UL, 720, 480, 0x48040415UL}, /* 102 */
|
||||
{0x00a10304UL, 720, 480, 0x58040415UL}, /* 103 */
|
||||
{0x00a00304UL, 640, 576, 0x48050516UL}, /* 104 */
|
||||
{0x00a10304UL, 640, 576, 0x58050516UL}, /* 105 */
|
||||
{0x00a00304UL, 720, 576, 0x48060617UL}, /* 106 */
|
||||
{0x00a10304UL, 720, 576, 0x58060617UL}, /* 107 */
|
||||
{0x01800304UL, 640, 288, 0x48050516UL}, /* 108 */
|
||||
{0x01810304UL, 640, 288, 0x58050516UL}, /* 109 */
|
||||
{0x01800304UL, 720, 288, 0x48060617UL}, /* 110 */
|
||||
{0x01810304UL, 720, 288, 0x58060617UL}, /* 111 */
|
||||
{0x02a00304UL, 640, 480, 0x48100e18UL}, /* 112 */
|
||||
{0x02a10304UL, 640, 480, 0x58100e18UL}, /* 113 */
|
||||
{0x02a00304UL, 640, 576, 0x4812101dUL}, /* 114 */
|
||||
{0x02a10304UL, 640, 576, 0x5812101dUL}, /* 115 */
|
||||
{0x03800304UL, 640, 288, 0x4812101dUL}, /* 116 */
|
||||
{0x03810304UL, 640, 288, 0x5812101dUL}, /* 117 */
|
||||
{0x00600304UL, 640, 480, 0x08010119UL}, /* 118 */
|
||||
{0x00610304UL, 640, 480, 0x18010119UL}, /* 119 */
|
||||
{0x00600304UL, 720, 480, 0x0802021aUL}, /* 120 */
|
||||
{0x00610304UL, 720, 480, 0x1802021aUL}, /* 121 */
|
||||
{0x01400304UL, 640, 240, 0x08010119UL}, /* 122 */
|
||||
{0x01410304UL, 640, 240, 0x18010119UL}, /* 123 */
|
||||
{0x01400304UL, 720, 240, 0x0802021aUL}, /* 124 */
|
||||
{0x01410304UL, 720, 240, 0x1802021aUL}, /* 125 */
|
||||
{0x02600304UL, 640, 480, 0x080f0d1bUL}, /* 126 */
|
||||
{0x02610304UL, 640, 480, 0x180f0d1bUL}, /* 127 */
|
||||
{0x03400304UL, 640, 240, 0x080f0d1bUL}, /* 128 */
|
||||
{0x03410304UL, 640, 240, 0x180f0d1bUL}, /* 129 */
|
||||
{0x00a00303UL, 640, 480, 0x60030307UL}, /* 130 */
|
||||
{0x00a10303UL, 640, 480, 0x70030307UL}, /* 131 */
|
||||
{0x00a00303UL, 720, 480, 0x60040408UL}, /* 132 */
|
||||
{0x00a10303UL, 720, 480, 0x70040408UL}, /* 133 */
|
||||
{0x00a00303UL, 640, 576, 0x60050509UL}, /* 134 */
|
||||
{0x00a10303UL, 640, 576, 0x70050509UL}, /* 135 */
|
||||
{0x00a00303UL, 720, 576, 0x6006060aUL}, /* 136 */
|
||||
{0x00a10303UL, 720, 576, 0x7006060aUL}, /* 137 */
|
||||
{0x01800303UL, 640, 288, 0x60050509UL}, /* 138 */
|
||||
{0x01810303UL, 640, 288, 0x70050509UL}, /* 139 */
|
||||
{0x01800303UL, 720, 288, 0x6006060aUL}, /* 140 */
|
||||
{0x01810303UL, 720, 288, 0x7006060aUL}, /* 141 */
|
||||
{0x02a00303UL, 640, 480, 0x60100e13UL}, /* 142 */
|
||||
{0x02a10303UL, 640, 480, 0x70100e13UL}, /* 143 */
|
||||
{0x02a00303UL, 640, 576, 0x6012101cUL}, /* 144 */
|
||||
{0x02a10303UL, 640, 576, 0x7012101cUL}, /* 145 */
|
||||
{0x03800303UL, 640, 288, 0x6012101cUL}, /* 146 */
|
||||
{0x03810303UL, 640, 288, 0x7012101cUL}, /* 147 */
|
||||
{0x00600303UL, 640, 480, 0x2001010bUL}, /* 148 */
|
||||
{0x00610303UL, 640, 480, 0x3001010bUL}, /* 149 */
|
||||
{0x00600303UL, 720, 480, 0x2002020cUL}, /* 150 */
|
||||
{0x00610303UL, 720, 480, 0x3002020cUL}, /* 151 */
|
||||
{0x01400303UL, 640, 240, 0x2001010bUL}, /* 152 */
|
||||
{0x01410303UL, 640, 240, 0x3001010bUL}, /* 153 */
|
||||
{0x01400303UL, 720, 240, 0x2002020cUL}, /* 154 */
|
||||
{0x01410303UL, 720, 240, 0x3002020cUL}, /* 155 */
|
||||
{0x02600303UL, 640, 480, 0x200f0d11UL}, /* 156 */
|
||||
{0x02610303UL, 640, 480, 0x300f0d11UL}, /* 157 */
|
||||
{0x03400303UL, 640, 240, 0x200f0d11UL}, /* 158 */
|
||||
{0x03410303UL, 640, 240, 0x300f0d11UL}, /* 159 */
|
||||
{0x00a00300UL, 640, 480, 0x44030307UL}, /* 160 */
|
||||
{0x00a10300UL, 640, 480, 0x54030307UL}, /* 161 */
|
||||
{0x00a00300UL, 720, 480, 0x44040408UL}, /* 162 */
|
||||
{0x00a10300UL, 720, 480, 0x54040408UL}, /* 163 */
|
||||
{0x00a00300UL, 640, 576, 0x44050509UL}, /* 164 */
|
||||
{0x00a10300UL, 640, 576, 0x54050509UL}, /* 165 */
|
||||
{0x00a00300UL, 720, 576, 0x4406060aUL}, /* 166 */
|
||||
{0x00a10300UL, 720, 576, 0x5406060aUL}, /* 167 */
|
||||
{0x01800300UL, 640, 288, 0x44050509UL}, /* 168 */
|
||||
{0x01810300UL, 640, 288, 0x54050509UL}, /* 169 */
|
||||
{0x01800300UL, 720, 288, 0x4406060aUL}, /* 170 */
|
||||
{0x01810300UL, 720, 288, 0x5406060aUL}, /* 171 */
|
||||
{0x02a00300UL, 640, 480, 0x44100e13UL}, /* 172 */
|
||||
{0x02a10300UL, 640, 480, 0x54100e13UL}, /* 173 */
|
||||
{0x02a00300UL, 640, 576, 0x4412101cUL}, /* 174 */
|
||||
{0x02a10300UL, 640, 576, 0x5412101cUL}, /* 175 */
|
||||
{0x03800300UL, 640, 288, 0x4412101cUL}, /* 176 */
|
||||
{0x03810300UL, 640, 288, 0x5412101cUL}, /* 177 */
|
||||
{0x00600300UL, 640, 480, 0x0401010bUL}, /* 178 */
|
||||
{0x00610300UL, 640, 480, 0x1401010bUL}, /* 179 */
|
||||
{0x00600300UL, 720, 480, 0x0402020cUL}, /* 180 */
|
||||
{0x00610300UL, 720, 480, 0x1402020cUL}, /* 181 */
|
||||
{0x01400300UL, 640, 240, 0x0401010bUL}, /* 182 */
|
||||
{0x01410300UL, 640, 240, 0x1401010bUL}, /* 183 */
|
||||
{0x01400300UL, 720, 240, 0x0402020cUL}, /* 184 */
|
||||
{0x01410300UL, 720, 240, 0x1402020cUL}, /* 185 */
|
||||
{0x02600300UL, 640, 480, 0x040f0d11UL}, /* 186 */
|
||||
{0x02610300UL, 640, 480, 0x140f0d11UL}, /* 187 */
|
||||
{0x03400300UL, 640, 240, 0x040f0d11UL}, /* 188 */
|
||||
{0x03410300UL, 640, 240, 0x140f0d11UL}, /* 189 */
|
||||
{0xffffffffUL, 0, 0, 0x00000000UL}, /* 190 */
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef D3D8_DRAW_INTERNAL_H
|
||||
#define D3D8_DRAW_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
extern int g_CurrentPrimitiveType;
|
||||
void WINAPI SetState(
|
||||
void);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/* Reconstructed from January 2002 target code and genuine SDK declarations.
|
||||
* NV2A method payloads are GPU commands, not native instruction emission. */
|
||||
#include "draw_internal.h"
|
||||
#include "push_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
using namespace D3D;
|
||||
void WINAPI D3DDevice_SetVertexData2f(
|
||||
int reg,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x1880 + reg * 8, 2);
|
||||
memcpy(push + 1, &x, sizeof(x));
|
||||
memcpy(push + 2, &y, sizeof(y));
|
||||
device->EndPush(push + 3);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexData4f(
|
||||
int reg,
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
float w)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
DWORD method = reg == -1 ? 0x1518 : 0x1a00 + reg * 16;
|
||||
PushCount(push, method, 4);
|
||||
memcpy(push + 1, &x, sizeof(x));
|
||||
memcpy(push + 2, &y, sizeof(y));
|
||||
memcpy(push + 3, &z, sizeof(z));
|
||||
memcpy(push + 4, &w, sizeof(w));
|
||||
device->EndPush(push + 5);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexData2s(
|
||||
int reg,
|
||||
short x,
|
||||
short y)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1900 + reg * 4, (WORD)x | ((DWORD)y << 16));
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexData4s(
|
||||
int reg,
|
||||
short x,
|
||||
short y,
|
||||
short z,
|
||||
short w)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push2(push, 0x1980 + reg * 8, (WORD)x | ((DWORD)y << 16),
|
||||
(WORD)z | ((DWORD)w << 16));
|
||||
device->EndPush(push + 3);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexData4ub(
|
||||
int reg,
|
||||
BYTE x,
|
||||
BYTE y,
|
||||
BYTE z,
|
||||
BYTE w)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1940 + reg * 4, (((((DWORD)w << 8) | z) << 8) | y) << 8 | x);
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexDataColor(
|
||||
int reg,
|
||||
D3DCOLOR color)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1940 + reg * 4, SwapRgb(color));
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_Begin(
|
||||
D3DPRIMITIVETYPE primitiveType)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
g_CurrentPrimitiveType = primitiveType;
|
||||
SetState();
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x17fc, primitiveType);
|
||||
device->EndPush(push + 2);
|
||||
device->m_StateFlags |= 0x800;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_End(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
g_CurrentPrimitiveType = 0;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x17fc, 0);
|
||||
device->EndPush(push + 2);
|
||||
if (device->m_StateFlags & 0x1000)
|
||||
SetFence(1);
|
||||
device->m_StateFlags &= ~0x1800;
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI D3DDevice_DrawVertices(
|
||||
D3DPRIMITIVETYPE primitiveType,
|
||||
UINT startVertex,
|
||||
UINT vertexCount)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->SetStateVB(0);
|
||||
DWORD batchCount = ((vertexCount - 1) >> 8) + 1;
|
||||
DWORD *push = device->StartPush(batchCount + 5);
|
||||
Push1(push, 0x17fc, primitiveType);
|
||||
PushCount(push + 2, 0x40001810, batchCount);
|
||||
while (vertexCount > 256)
|
||||
{
|
||||
push[3] = startVertex | 0xff000000;
|
||||
push++;
|
||||
startVertex += 256;
|
||||
vertexCount -= 256;
|
||||
}
|
||||
push[3] = startVertex | ((vertexCount - 1) << 24);
|
||||
Push1(push + 4, 0x17fc, 0);
|
||||
device->EndPush(push + 6);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_PrimeVertexCache(
|
||||
UINT vertexCount,
|
||||
const WORD *indexData)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->SetStateVB(device->m_IndexBase);
|
||||
DWORD dwordCount = vertexCount >> 1;
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x40001800, dwordCount);
|
||||
DWORD size = dwordCount * sizeof(DWORD);
|
||||
memcpy(push + 1, indexData, size);
|
||||
push += dwordCount + 1;
|
||||
if (vertexCount & 1)
|
||||
{
|
||||
Push1(push, 0x1808, indexData[dwordCount * 2]);
|
||||
push += 2;
|
||||
}
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
/* Device initialization adapted from RXDK-Libs, 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* The original January code/PDB determines context handles, layouts and order.
|
||||
*/
|
||||
#include "dxgcreate_internal.h"
|
||||
#include "push_internal.h"
|
||||
#include "lazy_internal.h"
|
||||
#include "math_internal.h"
|
||||
#include "resource_internal.h"
|
||||
#include "kernel_memory.h"
|
||||
#include "display_internal.h"
|
||||
#include "pusher_state.h"
|
||||
#include "miniport_constants.h"
|
||||
#include "vshader_internal.h"
|
||||
#include "surface_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
#include "initial_states.inc"
|
||||
DWORD CDevice::m_PushBufferSize;
|
||||
DWORD CDevice::m_PushSegmentSize;
|
||||
void WINAPI InitializeKelvin(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x180, 3);
|
||||
push[1] = NV_DD_DMA_PUSHER_SYNC_NOTIFIER_CONTEXT_DMA_TO_MEMORY;
|
||||
push[2] = NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
push[3] = NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
PushCount(push + 4, 0x190, 6);
|
||||
push[5] = NV_DD_DMA_CONTEXT_DMA_TO_VIDEO_MEMORY;
|
||||
push[6] = D3D_COLOR_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
push[7] = D3D_ZETA_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
push[8] = NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
push[9] = NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY;
|
||||
push[10] = D3D_SEMAPHORE_CONTEXT_DMA_IN_MEMORY;
|
||||
PushCount(push + 11, 0x1a8, 1);
|
||||
push[12] = D3D_CONTEXT_IN_CACHED_MEMORY;
|
||||
Push1(push + 13, 0x1d6c, 0);
|
||||
device->EndPush(push + 15);
|
||||
push = device->StartPush();
|
||||
Push1(push, 0x9fc, 1);
|
||||
PushCount(push + 2, 0xa50, 4);
|
||||
push[3] = NV_FLOAT_ZERO;
|
||||
push[4] = NV_FLOAT_ZERO;
|
||||
push[5] = NV_FLOAT_ZERO;
|
||||
push[6] = NV_FLOAT_ONE;
|
||||
Push1(push + 7, 0x16bc, TRUE);
|
||||
Push1(push + 9, 0x1e78, 0x210000);
|
||||
Push1(push + 11, 0x1d80, TRUE);
|
||||
Push1(push + 13, 0x1e68, NV_FLOAT_POSITIVE_INFINITY);
|
||||
Push1(push + 15, 0x1d78, TRUE);
|
||||
device->EndPush(push + 17);
|
||||
device->SetShaderConstantMode(D3DSCM_96CONSTANTS);
|
||||
return;
|
||||
}
|
||||
void WINAPI InitializeHardware(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x4000, D3D_MEMORY_TO_MEMORY_COPY);
|
||||
Push1(push + 2, 0x6000, D3D_RECTANGLE_COPY);
|
||||
Push1(push + 4, 0x8000, D3D_RECTANGLE_COPY_SURFACES);
|
||||
Push1(push + 6, 0x0000, D3D_KELVIN_PRIMITIVE);
|
||||
push += 8;
|
||||
Push1(push, 0x4180, D3D_MEMCOPY_NOTIFIER_CONTEXT_DMA_TO_MEMORY);
|
||||
Push1(push + 2, 0x619c, D3D_RECTANGLE_COPY_SURFACES);
|
||||
Push1(push + 4, 0x62fc, 3); /* SRCCOPY operation. */
|
||||
Push2(push + 6, 0x8184, NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY,
|
||||
D3D_COPY_CONTEXT_DMA_IN_VIDEO_MEMORY);
|
||||
device->EndPush(push + 9);
|
||||
InitializeKelvin();
|
||||
return;
|
||||
}
|
||||
void WINAPI InitializeD3dState(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD i;
|
||||
for (i = 0; i < D3DTS_MAX; i++)
|
||||
device->SetTransform((D3DTRANSFORMSTATETYPE)i, &g_IdentityMatrix);
|
||||
for (i = D3DRS_PS_MAX; i < D3DRS_MAX; i++)
|
||||
{
|
||||
if (i != D3DRS_MULTISAMPLETYPE)
|
||||
device->SetRenderStateNotInline((D3DRENDERSTATETYPE)i,
|
||||
g_InitialRenderStates[i - D3DRS_PS_MAX]);
|
||||
}
|
||||
device->SetRenderStateNotInline(D3DRS_ZENABLE, device->m_pAutoDepthBuffer != NULL);
|
||||
for (DWORD stage = 0; stage < D3DTSS_MAXSTAGES; stage++)
|
||||
{
|
||||
for (i = 0; i < D3DTSS_MAX; i++)
|
||||
device->SetTextureStageStateNotInline(stage, (D3DTEXTURESTAGESTATETYPE)i,
|
||||
g_InitialTextureStates[i]);
|
||||
device->SetTextureStageStateNotInline(stage, D3DTSS_TEXCOORDINDEX, stage);
|
||||
}
|
||||
device->SetTextureStageStateNotInline(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageStateNotInline(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
return;
|
||||
}
|
||||
void CDevice::FreeFrameBuffers(
|
||||
void)
|
||||
{
|
||||
if (AvGetSavedDataAddress() == NULL)
|
||||
AvSendTVEncoderOption(m_Miniport.m_RegisterBase, AV_OPTION_BLANK_SCREEN, TRUE, NULL);
|
||||
if (m_pRenderTarget != NULL)
|
||||
{
|
||||
RecordSurfaceWritePush(m_pRenderTarget);
|
||||
InternalReleaseSurface(m_pRenderTarget);
|
||||
m_pRenderTarget = NULL;
|
||||
}
|
||||
if (m_pZBuffer != NULL)
|
||||
{
|
||||
RecordSurfaceWritePush(m_pZBuffer);
|
||||
InternalReleaseSurface(m_pZBuffer);
|
||||
m_pZBuffer = NULL;
|
||||
}
|
||||
if (m_pAutoDepthBuffer != NULL)
|
||||
{
|
||||
SetTile(1, NULL);
|
||||
MmFreeContiguousMemory(m_pAutoDepthBuffer);
|
||||
m_pAutoDepthBuffer = NULL;
|
||||
ZeroMemory(&m_AutoDepthSurface, sizeof(m_AutoDepthSurface));
|
||||
}
|
||||
if (m_pFrameBufferBase != NULL)
|
||||
{
|
||||
SetTile(0, NULL);
|
||||
MmFreeContiguousMemory(m_pFrameBufferBase);
|
||||
m_pFrameBufferBase = NULL;
|
||||
ZeroMemory(m_FrameBufferSurfaces, sizeof(m_FrameBufferSurfaces));
|
||||
}
|
||||
if (m_pAntiAliasBufferBase != NULL)
|
||||
{
|
||||
MmFreeContiguousMemory(m_pAntiAliasBufferBase);
|
||||
m_pAntiAliasBufferBase = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT WINAPI PresentationParametersParameterCheck(
|
||||
D3DPRESENT_PARAMETERS *parameters)
|
||||
{
|
||||
DWORD sampleType = parameters->MultiSampleType;
|
||||
if (sampleType != D3DMULTISAMPLE_NONE && sampleType != 0)
|
||||
{
|
||||
if ((sampleType & 0x000f0000UL) > D3DMULTISAMPLE_PREFILTER_FORMAT_A8R8G8B8)
|
||||
return D3DERR_INVALIDCALL;
|
||||
if (((sampleType >> 4) & 15) < 1 || (sampleType & 15) < 1
|
||||
|| ((sampleType >> 4) & 15) > 3 || (sampleType & 15) > 3)
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
DWORD interval = parameters->FullScreen_PresentationInterval;
|
||||
if (interval > D3DPRESENT_INTERVAL_TWO && interval != D3DPRESENT_INTERVAL_IMMEDIATE)
|
||||
return D3DERR_INVALIDCALL;
|
||||
D3DSWAPEFFECT effect = parameters->SwapEffect;
|
||||
if (effect != D3DSWAPEFFECT_DISCARD && effect != D3DSWAPEFFECT_FLIP && effect != 0)
|
||||
return D3DERR_INVALIDCALL;
|
||||
if (parameters->BackBufferCount > 2)
|
||||
return D3DERR_INVALIDCALL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* The January owner frees the push allocation directly. It does not use the
|
||||
* later SDK's UninitializePushBuffer path. Completion requires GPU progress. */
|
||||
void CDevice::UnInit(
|
||||
void)
|
||||
{
|
||||
DWORD i;
|
||||
if (m_Pusher.m_pPut != NULL)
|
||||
{
|
||||
KickOffAndWaitForIdle();
|
||||
*m_Pusher.m_pPut = ((DWORD)m_pPushBase & 0x0fffffffUL) + 1;
|
||||
m_Pusher.m_pPut = m_pPushBase;
|
||||
KickOff();
|
||||
while (((DWORD)HwGet() & 0x0fffffffUL)
|
||||
!= ((DWORD)m_pPushBase & 0x0fffffffUL))
|
||||
{
|
||||
BusyLoop();
|
||||
}
|
||||
}
|
||||
while (m_Miniport.IsFlipPending()) { }
|
||||
FreeFrameBuffers();
|
||||
if (m_pIndexBuffer != NULL)
|
||||
InternalRelease(m_pIndexBuffer);
|
||||
for (i = 0; i < D3DTSS_MAXSTAGES; i++)
|
||||
{
|
||||
if (m_Textures[i] != NULL)
|
||||
InternalRelease(m_Textures[i]);
|
||||
if (m_Palettes[i] != NULL)
|
||||
InternalRelease(m_Palettes[i]);
|
||||
}
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (g_Stream[i].pVertexBuffer != NULL)
|
||||
InternalRelease(g_Stream[i].pVertexBuffer);
|
||||
}
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (m_ReportAllocations[i] != NULL)
|
||||
MmFreeContiguousMemory(m_ReportAllocations[i]);
|
||||
}
|
||||
if (m_pCachedContiguousMemoryBase != NULL)
|
||||
MmFreeContiguousMemory(m_pCachedContiguousMemoryBase);
|
||||
if (m_pPushBase != NULL)
|
||||
MmFreeContiguousMemory(m_pPushBase);
|
||||
if (m_pLights != NULL)
|
||||
LocalFree(m_pLights);
|
||||
if (m_Miniport.m_RegisterBase != NULL)
|
||||
{
|
||||
m_Miniport.DisableInterrupts();
|
||||
m_Miniport.ShutdownEngines();
|
||||
}
|
||||
ZeroMemory(g_Stream, sizeof(g_Stream));
|
||||
return;
|
||||
}
|
||||
|
||||
/* January stores surface headers inside CDevice and allocates the pixel planes
|
||||
* separately. Creation/Reset own cleanup of any partial allocations on failure.
|
||||
* Width/height/counts and multisample encodings must be valid checked API values. */
|
||||
HRESULT CDevice::InitializeFrameBuffers(
|
||||
D3DPRESENT_PARAMETERS *parameters)
|
||||
{
|
||||
DWORD format;
|
||||
DWORD size;
|
||||
D3DTILE tile;
|
||||
DWORD i;
|
||||
DWORD backBufferCount = max(1, parameters->BackBufferCount);
|
||||
D3DFORMAT postfilterFormat = MapToLinearD3DFORMAT(parameters->BackBufferFormat);
|
||||
D3DFORMAT autoDepthStencilFormat = MapToLinearD3DFORMAT(parameters->AutoDepthStencilFormat);
|
||||
DWORD backBufferWidth = parameters->BackBufferWidth;
|
||||
DWORD backBufferHeight = parameters->BackBufferHeight;
|
||||
m_PresentationInterval = parameters->FullScreen_PresentationInterval;
|
||||
m_DisplayWidth = backBufferWidth;
|
||||
m_DisplayHeight = backBufferHeight;
|
||||
DWORD frameCount = backBufferCount + 1;
|
||||
m_FrameBufferCount = frameCount;
|
||||
|
||||
/* Preserve January's low-word render-state storage. Its later prefilter
|
||||
* selector consequently has only the retained state bits available. */
|
||||
D3D__RenderState[D3DRS_MULTISAMPLETYPE] = parameters->MultiSampleType & 0xffff;
|
||||
BOOL doAntiAlias = D3D__RenderState[D3DRS_MULTISAMPLETYPE] & 0x3000;
|
||||
if (!doAntiAlias)
|
||||
D3D__RenderState[D3DRS_MULTISAMPLETYPE] = D3DMULTISAMPLE_NONE;
|
||||
D3DFORMAT prefilterFormat = postfilterFormat;
|
||||
switch (D3D__RenderState[D3DRS_MULTISAMPLETYPE] & 0xf0000)
|
||||
{
|
||||
case D3DMULTISAMPLE_PREFILTER_FORMAT_X1R5G5B5:
|
||||
prefilterFormat = D3DFMT_LIN_X1R5G5B5;
|
||||
break;
|
||||
case D3DMULTISAMPLE_PREFILTER_FORMAT_R5G6B5:
|
||||
prefilterFormat = D3DFMT_LIN_R5G6B5;
|
||||
break;
|
||||
case D3DMULTISAMPLE_PREFILTER_FORMAT_X8R8G8B8:
|
||||
prefilterFormat = D3DFMT_LIN_X8R8G8B8;
|
||||
break;
|
||||
case D3DMULTISAMPLE_PREFILTER_FORMAT_A8R8G8B8:
|
||||
prefilterFormat = D3DFMT_LIN_A8R8G8B8;
|
||||
break;
|
||||
}
|
||||
DWORD width = backBufferWidth * ((D3D__RenderState[D3DRS_MULTISAMPLETYPE] >> 4) & 15);
|
||||
DWORD height = backBufferHeight * (D3D__RenderState[D3DRS_MULTISAMPLETYPE] & 15);
|
||||
DWORD frameSize = PixelJar::EncodeFormat(width, height, 1, 1,
|
||||
prefilterFormat, CalcTilePitch(width, prefilterFormat), true, false, false,
|
||||
&format, &size);
|
||||
frameCount = doAntiAlias ? 1 : frameCount;
|
||||
DWORD allocationSize = (frameCount * frameSize + D3DTILE_ALIGNMENT - 1)
|
||||
& ~(D3DTILE_ALIGNMENT - 1);
|
||||
BYTE *memory = (BYTE *)MmAllocateContiguousMemoryEx(allocationSize, 0,
|
||||
0x03ffb000, D3DTILE_ALIGNMENT, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (memory == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
m_pFrameBufferBase = memory;
|
||||
for (i = 0; i < frameCount; i++)
|
||||
{
|
||||
InitializeSurface(&m_FrameBufferSurfaces[i], format, size, memory);
|
||||
memory += frameSize;
|
||||
}
|
||||
/* Original 1920-wide display path leaves these allocations untiled. */
|
||||
if (width != 1920)
|
||||
{
|
||||
/* Ignored depth fields are initialized as well: do not copy
|
||||
* indeterminate members through the SetTile value assignment. */
|
||||
tile.ZOffset = 0;
|
||||
tile.ZStartTag = 0;
|
||||
tile.Flags = 0;
|
||||
tile.pMemory = m_pFrameBufferBase;
|
||||
tile.Size = allocationSize;
|
||||
tile.Pitch = PixelJar::GetPitch(&m_FrameBufferSurfaces[0]);
|
||||
SetTile(0, &tile);
|
||||
}
|
||||
if (parameters->EnableAutoDepthStencil)
|
||||
{
|
||||
frameSize = PixelJar::EncodeFormat(width, height, 1, 1,
|
||||
autoDepthStencilFormat, CalcTilePitch(width, autoDepthStencilFormat),
|
||||
true, false, false, &format, &size);
|
||||
allocationSize = (frameSize + D3DTILE_ALIGNMENT - 1) & ~(D3DTILE_ALIGNMENT - 1);
|
||||
memory = (BYTE *)MmAllocateContiguousMemoryEx(allocationSize, 0,
|
||||
0x03ffb000, D3DTILE_ALIGNMENT, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (memory == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
m_pAutoDepthBuffer = memory;
|
||||
InitializeSurface(&m_AutoDepthSurface, format, size, memory);
|
||||
if (width != 1920)
|
||||
{
|
||||
tile.Flags = D3DTILE_FLAGS_ZBUFFER | D3DTILE_FLAGS_ZCOMPRESS;
|
||||
tile.pMemory = memory;
|
||||
tile.Size = allocationSize;
|
||||
tile.Pitch = PixelJar::GetPitch(&m_AutoDepthSurface);
|
||||
tile.ZOffset = 0;
|
||||
tile.ZStartTag = 0;
|
||||
if (BitsPerPixelOfD3DFORMAT(autoDepthStencilFormat) == 32)
|
||||
tile.Flags |= D3DTILE_FLAGS_Z32BITS;
|
||||
SetTile(1, &tile);
|
||||
}
|
||||
}
|
||||
if (doAntiAlias)
|
||||
{
|
||||
frameSize = PixelJar::EncodeFormat(backBufferWidth, backBufferHeight, 1, 1,
|
||||
postfilterFormat, 0, true, false, false, &format, &size);
|
||||
memory = (BYTE *)MmAllocateContiguousMemoryEx(backBufferCount * frameSize, 0,
|
||||
0x03ffb000, D3DTILE_ALIGNMENT, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (memory == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
m_pAntiAliasBufferBase = memory;
|
||||
for (i = 1; i <= backBufferCount; i++)
|
||||
{
|
||||
InitializeSurface(&m_FrameBufferSurfaces[i], format, size, memory);
|
||||
memory += frameSize;
|
||||
}
|
||||
}
|
||||
DWORD *push = StartPush();
|
||||
DWORD flipLimit = doAntiAlias ? 2 : m_FrameBufferCount;
|
||||
PushCount(push, 0x120, 3);
|
||||
push[1] = 0;
|
||||
push[2] = 1;
|
||||
push[3] = flipLimit;
|
||||
EndPush(push + 4);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef D3D8_DXGCREATE_INTERNAL_H
|
||||
#define D3D8_DXGCREATE_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
extern const DWORD g_InitialRenderStates[87];
|
||||
extern const BYTE g_InitialTextureStates[32];
|
||||
void WINAPI InitializeKelvin(
|
||||
void);
|
||||
void WINAPI InitializeHardware(
|
||||
void);
|
||||
void WINAPI InitializeD3dState(
|
||||
void);
|
||||
HRESULT WINAPI PresentationParametersParameterCheck(
|
||||
D3DPRESENT_PARAMETERS *parameters);
|
||||
/* Original static GPU context handles, distinct from class numbers/methods. */
|
||||
enum DeviceContextHandle
|
||||
{
|
||||
NV_DD_DMA_PUSHER_SYNC_NOTIFIER_CONTEXT_DMA_TO_MEMORY = 2,
|
||||
NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY = 3,
|
||||
NV_DD_DMA_CONTEXT_DMA_TO_VIDEO_MEMORY = 4,
|
||||
D3D_MEMCOPY_NOTIFIER_CONTEXT_DMA_TO_MEMORY = 7,
|
||||
D3D_SEMAPHORE_CONTEXT_DMA_IN_MEMORY = 8,
|
||||
D3D_COLOR_CONTEXT_DMA_IN_VIDEO_MEMORY = 9,
|
||||
D3D_ZETA_CONTEXT_DMA_IN_VIDEO_MEMORY = 10,
|
||||
D3D_COPY_CONTEXT_DMA_IN_VIDEO_MEMORY = 11,
|
||||
D3D_CONTEXT_IN_CACHED_MEMORY = 12,
|
||||
D3D_KELVIN_PRIMITIVE = 13,
|
||||
D3D_MEMORY_TO_MEMORY_COPY = 14,
|
||||
D3D_RECTANGLE_COPY = 16,
|
||||
D3D_RECTANGLE_COPY_SURFACES = 17
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,192 @@
|
||||
/* Adapted from RXDK-Libs (2026 Team Resurgent), GPL-3.0-or-later.
|
||||
* January PDB, original code and SDK define the target-specific layout/API.
|
||||
* See libs/d3d8/PROVENANCE.md. */
|
||||
#include "display_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
__inline BOOL CheckDisplayFormat(
|
||||
D3DFORMAT format)
|
||||
{
|
||||
return g_TextureFormat[format] & 0x80;
|
||||
}
|
||||
}
|
||||
using namespace D3D;
|
||||
Direct3D *WINAPI Direct3DCreate8(
|
||||
UINT SDKVersion)
|
||||
{
|
||||
return (Direct3D *)1;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_GetAdapterIdentifier(
|
||||
UINT Adapter,
|
||||
DWORD Flags,
|
||||
D3DADAPTER_IDENTIFIER8 *pIdentifier)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
*pIdentifier = g_AdapterIdentifier;
|
||||
return S_OK;
|
||||
}
|
||||
UINT WINAPI Direct3D_GetAdapterModeCount(
|
||||
UINT Adapter)
|
||||
{
|
||||
UINT Count = 0;
|
||||
const DISPLAYMODE *pMode = GetTableForCurrentAvInfo();
|
||||
DWORD SystemAvInfo = CMiniport::GetDisplayCapabilities();
|
||||
ULONG ModeAvPack = pMode->AvInfo & AV_PACK_MASK;
|
||||
ULONG AvPack = SystemAvInfo & AV_PACK_MASK;
|
||||
ULONG AvRefresh = SystemAvInfo & AV_REFRESH_MASK;
|
||||
ULONG AvHDTVModes = SystemAvInfo & AV_HDTV_MODE_MASK;
|
||||
for (;; pMode++)
|
||||
{
|
||||
if ((pMode->AvInfo & AV_PACK_MASK) != ModeAvPack) { break; }
|
||||
if ((AvPack != AV_PACK_HDTV || !(pMode->AvInfo & (AV_FLAGS_HDTV_720p | AV_FLAGS_HDTV_1080i)))
|
||||
&& (pMode->AvInfo & AV_FLAGS_WIDESCREEN) && !(SystemAvInfo & AV_FLAGS_WIDESCREEN)) { continue; }
|
||||
if (!(pMode->AvInfo & AvRefresh)) { continue; }
|
||||
if (AvPack == AV_PACK_HDTV && !(pMode->AvInfo & AvHDTVModes)
|
||||
&& (pMode->AvInfo & AV_HDTV_MODE_MASK) != 0) { continue; }
|
||||
Count++;
|
||||
}
|
||||
return Count * 4;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_EnumAdapterModes(
|
||||
UINT Adapter,
|
||||
UINT Mode,
|
||||
D3DDISPLAYMODE *pModeRet)
|
||||
{
|
||||
DWORD Format = Mode % 4;
|
||||
Mode /= 4;
|
||||
const DISPLAYMODE *pMode = GetTableForCurrentAvInfo();
|
||||
DWORD SystemAvInfo = CMiniport::GetDisplayCapabilities();
|
||||
ULONG ModeAvPack = pMode->AvInfo & AV_PACK_MASK;
|
||||
ULONG AvPack = SystemAvInfo & AV_PACK_MASK;
|
||||
ULONG AvRefresh = SystemAvInfo & AV_REFRESH_MASK;
|
||||
ULONG AvHDTVModes = SystemAvInfo & AV_HDTV_MODE_MASK;
|
||||
for (;; pMode++)
|
||||
{
|
||||
if ((pMode->AvInfo & AV_PACK_MASK) != ModeAvPack) { return D3DERR_INVALIDCALL; }
|
||||
if ((AvPack != AV_PACK_HDTV || !(pMode->AvInfo & (AV_FLAGS_HDTV_720p | AV_FLAGS_HDTV_1080i)))
|
||||
&& (pMode->AvInfo & AV_FLAGS_WIDESCREEN) && !(SystemAvInfo & AV_FLAGS_WIDESCREEN)) { continue; }
|
||||
if (!(pMode->AvInfo & AvRefresh)) { continue; }
|
||||
if (AvPack == AV_PACK_HDTV && !(pMode->AvInfo & AvHDTVModes)
|
||||
&& (pMode->AvInfo & AV_HDTV_MODE_MASK) != 0) { continue; }
|
||||
if (!Mode--)
|
||||
{
|
||||
pModeRet->Width = pMode->Width;
|
||||
pModeRet->Height = pMode->Height;
|
||||
pModeRet->RefreshRate = (pMode->AvInfo & AV_FLAGS_60Hz) ? 60 : 50;
|
||||
pModeRet->Flags = CMiniport::GetPresentFlagsFromAvInfo(pMode->AvInfo);
|
||||
switch (Format)
|
||||
{
|
||||
case 0: pModeRet->Format = D3DFMT_LIN_X8R8G8B8; break;
|
||||
case 1: pModeRet->Format = D3DFMT_LIN_R5G6B5; break;
|
||||
case 2: pModeRet->Format = D3DFMT_LIN_X1R5G5B5; break;
|
||||
case 3: pModeRet->Format = D3DFMT_LIN_A8R8G8B8; break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
HRESULT WINAPI Direct3D_GetAdapterDisplayMode(
|
||||
UINT Adapter,
|
||||
D3DDISPLAYMODE *pMode)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
CDevice *pDevice = g_pDevice;
|
||||
if (pDevice == NULL)
|
||||
{
|
||||
memset(pMode, 0, sizeof(*pMode));
|
||||
}
|
||||
else
|
||||
{
|
||||
pMode->Width = pDevice->m_DisplayWidth;
|
||||
pMode->Height = pDevice->m_DisplayHeight;
|
||||
pMode->RefreshRate = pDevice->m_Miniport.GetRefreshRate();
|
||||
pMode->Format = PixelJar::GetFormat(&pDevice->m_FrameBufferSurfaces[1]);
|
||||
pMode->Flags = CMiniport::GetPresentFlagsFromAvInfo(pDevice->m_Miniport.m_CurrentAvInfo);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_CheckDeviceType(
|
||||
UINT Adapter,
|
||||
D3DDEVTYPE CheckType,
|
||||
D3DFORMAT DisplayFormat,
|
||||
D3DFORMAT BackBufferFormat,
|
||||
BOOL Windowed)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
if (CheckType != D3DDEVTYPE_HAL) { return D3DERR_INVALIDDEVICE; }
|
||||
if (Windowed == TRUE) { return D3DERR_NOTAVAILABLE; }
|
||||
if (!CheckDisplayFormat(DisplayFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
if (!CheckDisplayFormat(BackBufferFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_CheckDeviceFormat(
|
||||
UINT Adapter,
|
||||
D3DDEVTYPE DeviceType,
|
||||
D3DFORMAT AdapterFormat,
|
||||
DWORD Usage,
|
||||
D3DRESOURCETYPE RType,
|
||||
D3DFORMAT CheckFormat)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
if (DeviceType != D3DDEVTYPE_HAL) { return D3DERR_INVALIDDEVICE; }
|
||||
if (!CheckDisplayFormat(AdapterFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
if (Usage & D3DUSAGE_DEPTHSTENCIL)
|
||||
{
|
||||
if (!(g_TextureFormat[CheckFormat] & 0x40)) { return D3DERR_NOTAVAILABLE; }
|
||||
}
|
||||
else if (Usage & D3DUSAGE_RENDERTARGET)
|
||||
{
|
||||
if (!CheckDisplayFormat(CheckFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BitsPerPixelOfD3DFORMAT(CheckFormat) == 0) { return D3DERR_NOTAVAILABLE; }
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_CheckDeviceMultiSampleType(
|
||||
UINT Adapter,
|
||||
D3DDEVTYPE DeviceType,
|
||||
D3DFORMAT RenderTargetFormat,
|
||||
BOOL Windowed,
|
||||
D3DMULTISAMPLE_TYPE MultiSampleType)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
if (DeviceType != D3DDEVTYPE_HAL) { return D3DERR_INVALIDDEVICE; }
|
||||
if (Windowed == TRUE) { return D3DERR_NOTAVAILABLE; }
|
||||
if (!CheckDisplayFormat(RenderTargetFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
if (MultiSampleType != D3DMULTISAMPLE_NONE && MultiSampleType != 0)
|
||||
{
|
||||
if ((MultiSampleType & 0xf0000) > D3DMULTISAMPLE_PREFILTER_FORMAT_A8R8G8B8)
|
||||
{ return D3DERR_INVALIDCALL; }
|
||||
if (((MultiSampleType >> 4) & 15) < 1 || (MultiSampleType & 15) < 1
|
||||
|| ((MultiSampleType >> 4) & 15) > 3 || (MultiSampleType & 15) > 3)
|
||||
{ return D3DERR_NOTAVAILABLE; }
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_CheckDepthStencilMatch(
|
||||
UINT Adapter,
|
||||
D3DDEVTYPE DeviceType,
|
||||
D3DFORMAT AdapterFormat,
|
||||
D3DFORMAT RenderTargetFormat,
|
||||
D3DFORMAT DepthStencilFormat)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
if (DeviceType != D3DDEVTYPE_HAL) { return D3DERR_INVALIDDEVICE; }
|
||||
if (!CheckDisplayFormat(RenderTargetFormat)) { return D3DERR_NOTAVAILABLE; }
|
||||
if (!(g_TextureFormat[DepthStencilFormat] & 0x40)) { return D3DERR_NOTAVAILABLE; }
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI Direct3D_GetDeviceCaps(
|
||||
UINT Adapter,
|
||||
D3DDEVTYPE DeviceType,
|
||||
D3DCAPS8 *pCaps)
|
||||
{
|
||||
if (Adapter != 0) { return D3DERR_INVALIDCALL; }
|
||||
if (DeviceType != D3DDEVTYPE_HAL) { return D3DERR_INVALIDDEVICE; }
|
||||
D3DDevice_GetDeviceCaps(pCaps);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <xmmintrin.h>
|
||||
#include "math_internal.h"
|
||||
#include <math.h>
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
long WINAPI FloatToLong(
|
||||
float value)
|
||||
{
|
||||
return _mm_cvtt_ss2si(_mm_load_ss(&value));
|
||||
}
|
||||
float WINAPI Cos(
|
||||
float value)
|
||||
{
|
||||
return (float)cos(value);
|
||||
}
|
||||
float WINAPI Exp(
|
||||
float value)
|
||||
{
|
||||
return (float)exp(value);
|
||||
}
|
||||
float WINAPI Log(
|
||||
float value)
|
||||
{
|
||||
return (float)log(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""Generate the January D3D8 ABI view without modifying the supplied SDK.
|
||||
|
||||
The three return types were recovered from the original PDB. The fixed SDK
|
||||
input hash and replacement counts make this fail closed for another SDK.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SOURCE = ROOT / "xbox/include/D3D8.h"
|
||||
OUTPUT = ROOT / "build/generated/d3d8/d3d8.h"
|
||||
SOURCE_SHA256 = "7f7f603e1b2fa13ef36a05923eaa36d0d7094302522edbac9855b28f0909f1a1"
|
||||
|
||||
REPLACEMENTS = (
|
||||
(
|
||||
b"void WINAPI D3DVolume_GetContainer(D3DVolume *pThis, D3DBaseTexture **ppBaseTexture);",
|
||||
b"HRESULT WINAPI D3DVolume_GetContainer(D3DVolume *pThis, D3DBaseTexture **ppBaseTexture);",
|
||||
1,
|
||||
),
|
||||
(
|
||||
b"{ D3DVolume_GetContainer(pThis, ppBaseTexture); return S_OK; }",
|
||||
b"{ return D3DVolume_GetContainer(pThis, ppBaseTexture); }",
|
||||
1,
|
||||
),
|
||||
(
|
||||
b"{ D3DVolume_GetContainer(this, ppBaseTexture); return S_OK; }",
|
||||
b"{ return D3DVolume_GetContainer(this, ppBaseTexture); }",
|
||||
1,
|
||||
),
|
||||
(
|
||||
b"void WINAPI D3DDevice_CreatePixelShader(CONST D3DPIXELSHADERDEF *pPSDef, DWORD *pHandle);",
|
||||
b"HRESULT WINAPI D3DDevice_CreatePixelShader(CONST D3DPIXELSHADERDEF *pPSDef, DWORD *pHandle);",
|
||||
1,
|
||||
),
|
||||
(
|
||||
b"{ D3DDevice_CreatePixelShader(pPSDef, pHandle); return S_OK; }",
|
||||
b"{ return D3DDevice_CreatePixelShader(pPSDef, pHandle); }",
|
||||
2,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
original = SOURCE.read_bytes()
|
||||
if hashlib.sha256(original).hexdigest() != SOURCE_SHA256:
|
||||
raise ValueError("D3D8 SDK header differs from the verified January input")
|
||||
result = original
|
||||
for before, after, count in REPLACEMENTS:
|
||||
if result.count(before) != count:
|
||||
raise ValueError("D3D8 SDK declaration does not match the verified input")
|
||||
result = result.replace(before, after)
|
||||
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not OUTPUT.exists() or OUTPUT.read_bytes() != result:
|
||||
OUTPUT.write_bytes(result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Portions adapted with reference to RXDK-Libs (2026 Team Resurgent),
|
||||
* GPL-3.0-or-later. See libs/d3d8/PROVENANCE.md and libs/d3d8/LICENSE.GPL-3.0.
|
||||
* Original January target bytes and PDB remain the matching authority. */
|
||||
#ifndef D3D8_GRAPHICS_CONTEXT_INTERNAL_H
|
||||
#define D3D8_GRAPHICS_CONTEXT_INTERNAL_H
|
||||
#include "hardware_internal.h"
|
||||
namespace D3D
|
||||
{
|
||||
/* NV2A saved graphics context layout. These lengths are fixed hardware banks;
|
||||
* January HalGrInit3d supplies the offsets, extents, write order and values.
|
||||
* Field/bank names are corroborated by the pinned RXDK-Libs mphal reference.
|
||||
* This is instance-memory initialization, not emitted CPU instruction bytes. */
|
||||
enum GraphicsContextLayout
|
||||
{
|
||||
GRCTX_COMMON_DWORDS = 0x33c / sizeof(DWORD),
|
||||
GRCTX_3D_DWORDS = 0x2f0 / sizeof(DWORD),
|
||||
IDX_FMT_COUNT = 35,
|
||||
CAS0_COUNT = 29,
|
||||
CAS1_COUNT = 29,
|
||||
CAS2_COUNT = 29,
|
||||
ASSM_STATE_COUNT = 2,
|
||||
IDX_CACHE0_COUNT = 128,
|
||||
IDX_CACHE1_COUNT = 128,
|
||||
IDX_CACHE2_COUNT = 128,
|
||||
IDX_CACHE3_COUNT = 128,
|
||||
VTX_FILE0_COUNT = 192,
|
||||
VTX_FILE1_COUNT = 480,
|
||||
XL_P_COUNT = 544,
|
||||
XL_XFCTX_COUNT = 768,
|
||||
XL_LTCTXA_COUNT = 104,
|
||||
XL_LTCTXB_COUNT = 208,
|
||||
XL_LTC0_COUNT = 4,
|
||||
XL_LTC1_COUNT = 20,
|
||||
XL_LTC2_COUNT = 15,
|
||||
XL_LTC3_COUNT = 14,
|
||||
XL_VAB_COUNT = 68,
|
||||
CRSTR_STIPP_COUNT = 32,
|
||||
FD_CTRL_COUNT = 15,
|
||||
ROP_REGS_COUNT = 1,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
#ifndef D3D8_HARDWARE_INTERNAL_H
|
||||
#define D3D8_HARDWARE_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
/* January PDB layout. Volatile register accesses describe mapped device
|
||||
* storage, rather than selecting an otherwise unnecessary instruction. */
|
||||
struct Nv206eControl
|
||||
{
|
||||
DWORD Ignored00[16];
|
||||
DWORD Put;
|
||||
DWORD Get;
|
||||
DWORD Reference;
|
||||
DWORD Ignored01[2029];
|
||||
};
|
||||
typedef char nv_control_size[sizeof(Nv206eControl) == 8192 ? 1 : -1];
|
||||
typedef char nv_control_get_offset[offsetof(Nv206eControl, Get) == 0x44 ? 1 : -1];
|
||||
/* NvNotification's field layout is decoded from the January PDB. */
|
||||
struct NvNotification
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD nanoseconds[2];
|
||||
} timeStamp;
|
||||
DWORD info32;
|
||||
WORD info16;
|
||||
WORD status;
|
||||
};
|
||||
typedef char nv_notification_size_check[sizeof(NvNotification) == 16 ? 1 : -1];
|
||||
namespace D3D
|
||||
{
|
||||
/* Original NV2A display/graphics status and framebuffer debug access. */
|
||||
enum
|
||||
{
|
||||
NV2A_RASTER_POSITION = 0x600808,
|
||||
NV2A_RASTER_POSITION_MASK = 0x7ff,
|
||||
NV2A_GRAPHICS_STATUS = 0x400700,
|
||||
NV2A_TAG_INDEX = 0x1000f0,
|
||||
NV2A_TAG_DATA = 0x100100,
|
||||
NV2A_TAG_PARTITION_SELECT = 0x130,
|
||||
NV2A_TAG_SELECT_MASK = 0x1ff,
|
||||
NV2A_TAG_ADDRESS_MASK = 0x7f
|
||||
};
|
||||
|
||||
/* Hardware RAMFC context: the 13 saved DMA/FIFO registers occupy the first
|
||||
* 52 bytes of a 64-byte channel slot. Offsets follow the January save/restore
|
||||
* and initialization routines, not an unrelated later SDK layout. */
|
||||
struct FifoChannelContext
|
||||
{
|
||||
DWORD Put;
|
||||
DWORD Get;
|
||||
DWORD Ref;
|
||||
DWORD Instance;
|
||||
DWORD State;
|
||||
DWORD Fetch;
|
||||
DWORD Engine;
|
||||
DWORD Pull;
|
||||
DWORD AcquireValue;
|
||||
DWORD AcquireTimestamp;
|
||||
DWORD AcquireTimeout;
|
||||
DWORD Semaphore;
|
||||
DWORD Subroutine;
|
||||
DWORD Reserved[3];
|
||||
};
|
||||
typedef char fifo_channel_context_size[sizeof(FifoChannelContext) == 64 ? 1 : -1];
|
||||
struct _HWREG
|
||||
{
|
||||
volatile DWORD Reg032[1];
|
||||
};
|
||||
/* Address the complete mapped MMIO region, not an out-of-bounds element of
|
||||
* the one-element marker array in the historical declaration. */
|
||||
__inline DWORD WINAPI ReadGpuRegister(
|
||||
_HWREG *base,
|
||||
DWORD offset)
|
||||
{
|
||||
return *(volatile DWORD *)((BYTE *)base + offset);
|
||||
}
|
||||
__inline void WINAPI WriteGpuRegister(
|
||||
_HWREG *base,
|
||||
DWORD offset,
|
||||
DWORD value)
|
||||
{
|
||||
*(volatile DWORD *)((BYTE *)base + offset) = value;
|
||||
return;
|
||||
}
|
||||
/* Byte-wide indexed CRTC and palette registers have distinct access widths. */
|
||||
__inline BYTE WINAPI ReadGpuRegister8(
|
||||
_HWREG *base,
|
||||
DWORD offset)
|
||||
{
|
||||
return *(volatile BYTE *)((BYTE *)base + offset);
|
||||
}
|
||||
__inline void WINAPI WriteGpuRegister8(
|
||||
_HWREG *base,
|
||||
DWORD offset,
|
||||
BYTE value)
|
||||
{
|
||||
*(volatile BYTE *)((BYTE *)base + offset) = value;
|
||||
return;
|
||||
}
|
||||
__inline void CMiniport::EnableInterrupts(
|
||||
void)
|
||||
{
|
||||
WriteGpuRegister((_HWREG *)m_RegisterBase, 0x140, m_GenInfo.ChipIntrEn0);
|
||||
return;
|
||||
}
|
||||
/* Original inline method, also present as a 16-byte target in dxgcreate. */
|
||||
__inline void CMiniport::DisableInterrupts(
|
||||
void)
|
||||
{
|
||||
WriteGpuRegister((_HWREG *)m_RegisterBase, 0x140, 0);
|
||||
return;
|
||||
}
|
||||
__inline DWORD *CDevice::HwGet(
|
||||
void)
|
||||
{
|
||||
return (DWORD *)(m_pControlDma->Get | 0x80000000UL);
|
||||
}
|
||||
__inline DWORD CDevice::GpuTime(
|
||||
void)
|
||||
{
|
||||
return *m_pGpuTime;
|
||||
}
|
||||
__inline DWORD CDevice::Age(
|
||||
DWORD time)
|
||||
{
|
||||
return m_CpuTime - time;
|
||||
}
|
||||
__inline BOOL CDevice::IsTimePending(
|
||||
DWORD time)
|
||||
{
|
||||
return Age(time) < Age(GpuTime());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
/* Original January initial-state data. Not executable CPU instructions.
|
||||
* Extracted from target/dxgcreate.obj; verified separately from code. */
|
||||
const DWORD g_InitialRenderStates[87] =
|
||||
{
|
||||
0x00000203UL, /* D3DRS_ZFUNC */
|
||||
0x00000207UL, /* D3DRS_ALPHAFUNC */
|
||||
0x00000000UL, /* D3DRS_ALPHABLENDENABLE */
|
||||
0x00000000UL, /* D3DRS_ALPHATESTENABLE */
|
||||
0x00000000UL, /* D3DRS_ALPHAREF */
|
||||
0x00000001UL, /* D3DRS_SRCBLEND */
|
||||
0x00000000UL, /* D3DRS_DESTBLEND */
|
||||
0x00000001UL, /* D3DRS_ZWRITEENABLE */
|
||||
0x00000000UL, /* D3DRS_DITHERENABLE */
|
||||
0x00001d01UL, /* D3DRS_SHADEMODE */
|
||||
0x01010101UL, /* D3DRS_COLORWRITEENABLE */
|
||||
0x00001e00UL, /* D3DRS_STENCILZFAIL */
|
||||
0x00001e00UL, /* D3DRS_STENCILPASS */
|
||||
0x00000207UL, /* D3DRS_STENCILFUNC */
|
||||
0x00000000UL, /* D3DRS_STENCILREF */
|
||||
0xffffffffUL, /* D3DRS_STENCILMASK */
|
||||
0xffffffffUL, /* D3DRS_STENCILWRITEMASK */
|
||||
0x00008006UL, /* D3DRS_BLENDOP */
|
||||
0x00000000UL, /* D3DRS_BLENDCOLOR */
|
||||
0x00000004UL, /* D3DRS_SWATHWIDTH */
|
||||
0x00000000UL, /* D3DRS_POLYGONOFFSETZSLOPESCALE */
|
||||
0x00000000UL, /* D3DRS_POLYGONOFFSETZOFFSET */
|
||||
0x00000000UL, /* D3DRS_POINTOFFSETENABLE */
|
||||
0x00000000UL, /* D3DRS_WIREFRAMEOFFSETENABLE */
|
||||
0x00000000UL, /* D3DRS_SOLIDOFFSETENABLE */
|
||||
0x00000000UL, /* D3DRS_FOGENABLE */
|
||||
0x00000000UL, /* D3DRS_FOGTABLEMODE */
|
||||
0x00000000UL, /* D3DRS_FOGSTART */
|
||||
0x3f800000UL, /* D3DRS_FOGEND */
|
||||
0x3f800000UL, /* D3DRS_FOGDENSITY */
|
||||
0x00000000UL, /* D3DRS_RANGEFOGENABLE */
|
||||
0x00000000UL, /* D3DRS_WRAP0 */
|
||||
0x00000000UL, /* D3DRS_WRAP1 */
|
||||
0x00000000UL, /* D3DRS_WRAP2 */
|
||||
0x00000000UL, /* D3DRS_WRAP3 */
|
||||
0x00000001UL, /* D3DRS_LIGHTING */
|
||||
0x00000000UL, /* D3DRS_SPECULARENABLE */
|
||||
0x00000001UL, /* D3DRS_LOCALVIEWER */
|
||||
0x00000001UL, /* D3DRS_COLORVERTEX */
|
||||
0x00000002UL, /* D3DRS_BACKSPECULARMATERIALSOURCE */
|
||||
0x00000001UL, /* D3DRS_BACKDIFFUSEMATERIALSOURCE */
|
||||
0x00000000UL, /* D3DRS_BACKAMBIENTMATERIALSOURCE */
|
||||
0x00000000UL, /* D3DRS_BACKEMISSIVEMATERIALSOURCE */
|
||||
0x00000002UL, /* D3DRS_SPECULARMATERIALSOURCE */
|
||||
0x00000001UL, /* D3DRS_DIFFUSEMATERIALSOURCE */
|
||||
0x00000000UL, /* D3DRS_AMBIENTMATERIALSOURCE */
|
||||
0x00000000UL, /* D3DRS_EMISSIVEMATERIALSOURCE */
|
||||
0x00000000UL, /* D3DRS_BACKAMBIENT */
|
||||
0x00000000UL, /* D3DRS_AMBIENT */
|
||||
0x3f800000UL, /* D3DRS_POINTSIZE */
|
||||
0x00000000UL, /* D3DRS_POINTSIZE_MIN */
|
||||
0x00000000UL, /* D3DRS_POINTSPRITEENABLE */
|
||||
0x00000000UL, /* D3DRS_POINTSCALEENABLE */
|
||||
0x3f800000UL, /* D3DRS_POINTSCALE_A */
|
||||
0x00000000UL, /* D3DRS_POINTSCALE_B */
|
||||
0x00000000UL, /* D3DRS_POINTSCALE_C */
|
||||
0x42800000UL, /* D3DRS_POINTSIZE_MAX */
|
||||
0x00000000UL, /* D3DRS_PATCHEDGESTYLE */
|
||||
0x3f800000UL, /* D3DRS_PATCHSEGMENTS */
|
||||
0x00000000UL, /* D3DRS_PSTEXTUREMODES */
|
||||
0x00000000UL, /* D3DRS_VERTEXBLEND */
|
||||
0x00000000UL, /* D3DRS_FOGCOLOR */
|
||||
0x00001b02UL, /* D3DRS_FILLMODE */
|
||||
0x00001b02UL, /* D3DRS_BACKFILLMODE */
|
||||
0x00000000UL, /* D3DRS_TWOSIDEDLIGHTING */
|
||||
0x00000000UL, /* D3DRS_NORMALIZENORMALS */
|
||||
0x00000002UL, /* D3DRS_ZENABLE */
|
||||
0x00000000UL, /* D3DRS_STENCILENABLE */
|
||||
0x00001e00UL, /* D3DRS_STENCILFAIL */
|
||||
0x00000900UL, /* D3DRS_FRONTFACE */
|
||||
0x00000901UL, /* D3DRS_CULLMODE */
|
||||
0xffffffffUL, /* D3DRS_TEXTUREFACTOR */
|
||||
0x00000000UL, /* D3DRS_ZBIAS */
|
||||
0x00000000UL, /* D3DRS_LOGICOP */
|
||||
0x00000000UL, /* D3DRS_EDGEANTIALIAS */
|
||||
0x00000001UL, /* D3DRS_MULTISAMPLEANTIALIAS */
|
||||
0xffffffffUL, /* D3DRS_MULTISAMPLEMASK */
|
||||
0xdeadbeefUL, /* D3DRS_MULTISAMPLETYPE */
|
||||
0x00000200UL, /* D3DRS_SHADOWFUNC */
|
||||
0x3f800000UL, /* D3DRS_LINEWIDTH */
|
||||
0x00000001UL, /* D3DRS_DXT1NOISEENABLE */
|
||||
0x00000000UL, /* D3DRS_YUVENABLE */
|
||||
0x00000001UL, /* D3DRS_OCCLUSIONCULLENABLE */
|
||||
0x00000001UL, /* D3DRS_STENCILCULLENABLE */
|
||||
0x00000000UL, /* D3DRS_ROPZCMPALWAYSREAD */
|
||||
0x00000000UL, /* D3DRS_ROPZREAD */
|
||||
0x00000000UL, /* D3DRS_DONOTCULLUNCOMPRESSED */
|
||||
};
|
||||
const BYTE g_InitialTextureStates[32] =
|
||||
{
|
||||
0x01, /* D3DTSS_COLOROP */
|
||||
0x01, /* D3DTSS_COLORARG0 */
|
||||
0x02, /* D3DTSS_COLORARG1 */
|
||||
0x01, /* D3DTSS_COLORARG2 */
|
||||
0x01, /* D3DTSS_ALPHAOP */
|
||||
0x01, /* D3DTSS_ALPHAARG0 */
|
||||
0x02, /* D3DTSS_ALPHAARG1 */
|
||||
0x01, /* D3DTSS_ALPHAARG2 */
|
||||
0x01, /* D3DTSS_RESULTARG */
|
||||
0x00, /* D3DTSS_TEXTURETRANSFORMFLAGS */
|
||||
0x01, /* D3DTSS_ADDRESSU */
|
||||
0x01, /* D3DTSS_ADDRESSV */
|
||||
0x01, /* D3DTSS_ADDRESSW */
|
||||
0x01, /* D3DTSS_MAGFILTER */
|
||||
0x01, /* D3DTSS_MINFILTER */
|
||||
0x00, /* D3DTSS_MIPFILTER */
|
||||
0x00, /* D3DTSS_MIPMAPLODBIAS */
|
||||
0x00, /* D3DTSS_MAXMIPLEVEL */
|
||||
0x01, /* D3DTSS_MAXANISOTROPY */
|
||||
0x00, /* D3DTSS_COLORKEYOP */
|
||||
0x00, /* D3DTSS_COLORSIGN */
|
||||
0x00, /* D3DTSS_ALPHAKILL */
|
||||
0x00, /* D3DTSS_BUMPENVMAT00 */
|
||||
0x00, /* D3DTSS_BUMPENVMAT01 */
|
||||
0x00, /* D3DTSS_BUMPENVMAT11 */
|
||||
0x00, /* D3DTSS_BUMPENVMAT10 */
|
||||
0x00, /* D3DTSS_BUMPENVLSCALE */
|
||||
0x00, /* D3DTSS_BUMPENVLOFFSET */
|
||||
0x00, /* D3DTSS_TEXCOORDINDEX */
|
||||
0x00, /* D3DTSS_BORDERCOLOR */
|
||||
0x00, /* D3DTSS_COLORKEYCOLOR */
|
||||
0x00, /* 31 */
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef D3D8_KERNEL_CLOCK_H
|
||||
#define D3D8_KERNEL_CLOCK_H
|
||||
#include "kernel_records.h"
|
||||
extern "C" __declspec(dllimport) void WINAPI KeQuerySystemTime(
|
||||
LARGE_INTEGER *time);
|
||||
extern "C" __declspec(dllimport) void WINAPI RtlTimeToTimeFields(
|
||||
LARGE_INTEGER *time,
|
||||
_TIME_FIELDS *fields);
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef D3D8_KERNEL_DEBUG_H
|
||||
#define D3D8_KERNEL_DEBUG_H
|
||||
#include <xtl.h>
|
||||
extern "C" ULONG __cdecl DbgPrint(
|
||||
const char *format,
|
||||
...);
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef D3D8_KERNEL_DISPATCHER_H
|
||||
#define D3D8_KERNEL_DISPATCHER_H
|
||||
#include "kernel_records.h"
|
||||
/* The wait/mode enumerations are taken from the January PDB, not a later SDK. */
|
||||
enum _KWAIT_REASON
|
||||
{
|
||||
Executive = 0,
|
||||
FreePage = 1,
|
||||
PageIn = 2,
|
||||
PoolAllocation = 3,
|
||||
DelayExecution = 4,
|
||||
Suspended = 5,
|
||||
UserRequest = 6,
|
||||
WrExecutive = 7,
|
||||
WrFreePage = 8,
|
||||
WrPageIn = 9,
|
||||
WrPoolAllocation = 10,
|
||||
WrDelayExecution = 11,
|
||||
WrSuspended = 12,
|
||||
WrUserRequest = 13,
|
||||
WrEventPair = 14,
|
||||
WrQueue = 15,
|
||||
WrLpcReceive = 16,
|
||||
WrLpcReply = 17,
|
||||
WrVirtualMemory = 18,
|
||||
WrPageOut = 19,
|
||||
WrRendezvous = 20,
|
||||
WrFsCacheIn = 21,
|
||||
WrFsCacheOut = 22,
|
||||
Spare4 = 23,
|
||||
Spare5 = 24,
|
||||
Spare6 = 25,
|
||||
WrKernel = 26,
|
||||
MaximumWaitReason = 27
|
||||
};
|
||||
enum _MODE
|
||||
{
|
||||
KernelMode = 0,
|
||||
UserMode = 1,
|
||||
MaximumMode = 2
|
||||
};
|
||||
typedef char WaitReasonSize[sizeof(_KWAIT_REASON) == 4 ? 1 : -1];
|
||||
typedef char ProcessorModeEnumSize[sizeof(_MODE) == 4 ? 1 : -1];
|
||||
/* Xbox NT KPROCESSOR_MODE is a signed byte; wait reason is a 32-bit enum.
|
||||
* The kernel call owns event synchronization; clearing only resets its signal. */
|
||||
extern "C" __declspec(dllimport) LONG WINAPI KeWaitForSingleObject(
|
||||
void *object,
|
||||
_KWAIT_REASON reason,
|
||||
CHAR mode,
|
||||
BYTE alertable,
|
||||
LARGE_INTEGER *timeout);
|
||||
#define KeClearEvent(event) ((event)->Header.SignalState = 0)
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef D3D8_KERNEL_GPU_H
|
||||
#define D3D8_KERNEL_GPU_H
|
||||
#include "device_layout.h"
|
||||
/* Xbox kernel imports; 32-bit stdcall contracts used by the January driver. */
|
||||
extern "C" __declspec(dllimport) void *WINAPI MmClaimGpuInstanceMemory(
|
||||
DWORD bytes,
|
||||
DWORD *paddingBytes);
|
||||
extern "C" __declspec(dllimport) void WINAPI MmSetAddressProtect(
|
||||
void *address,
|
||||
DWORD bytes,
|
||||
DWORD protection);
|
||||
extern "C" __declspec(dllimport) void WINAPI KeStallExecutionProcessor(
|
||||
DWORD microseconds);
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef D3D8_KERNEL_INTERRUPT_H
|
||||
#define D3D8_KERNEL_INTERRUPT_H
|
||||
#include "device_layout.h"
|
||||
/* Genuine Xbox kernel interrupt/shutdown interfaces. The target PDB owns record sizes
|
||||
* and containing-member offsets; event/shutdown fields are decoded, while the
|
||||
* passed-through DPC/interrupt record internals remain opaque. */
|
||||
extern "C" __declspec(dllimport) void WINAPI HalRegisterShutdownNotification(
|
||||
_HAL_SHUTDOWN_REGISTRATION *registration,
|
||||
BYTE registerNotification);
|
||||
extern "C" __declspec(dllimport) BYTE WINAPI KeDisconnectInterrupt(
|
||||
_KINTERRUPT *interrupt);
|
||||
extern "C" __declspec(dllimport) void WINAPI KeInitializeDpc(
|
||||
_KDPC *dpc,
|
||||
void (WINAPI *routine)(
|
||||
_KDPC *dpc,
|
||||
void *context,
|
||||
void *argument1,
|
||||
void *argument2),
|
||||
void *context);
|
||||
extern "C" __declspec(dllimport) BYTE WINAPI KeInsertQueueDpc(
|
||||
_KDPC *dpc,
|
||||
void *argument1,
|
||||
void *argument2);
|
||||
extern "C" __declspec(dllimport) DWORD WINAPI HalGetInterruptVector(
|
||||
DWORD busInterruptLevel,
|
||||
BYTE *irql);
|
||||
extern "C" __declspec(dllimport) void WINAPI KeInitializeInterrupt(
|
||||
_KINTERRUPT *interrupt,
|
||||
BYTE (WINAPI *routine)(
|
||||
_KINTERRUPT *interrupt,
|
||||
void *context),
|
||||
void *context,
|
||||
DWORD vector,
|
||||
BYTE irql,
|
||||
_KINTERRUPT_MODE mode,
|
||||
BYTE shareVector);
|
||||
extern "C" __declspec(dllimport) BYTE WINAPI KeConnectInterrupt(
|
||||
_KINTERRUPT *interrupt);
|
||||
extern "C" __declspec(dllimport) LONG WINAPI KeSetEvent(
|
||||
_KEVENT *event,
|
||||
LONG increment,
|
||||
BYTE wait);
|
||||
/* The period NT header exposes this operation as a macro, not a callable
|
||||
* routine. All call sites here pass a stable event address and constants.
|
||||
* Fields/size are authenticated from the January PDB. */
|
||||
#define KeInitializeEvent(event, type, state) do { \
|
||||
(event)->Header.Type = (BYTE)(type); \
|
||||
(event)->Header.Size = sizeof(_KEVENT) / sizeof(DWORD); \
|
||||
(event)->Header.SignalState = (state); \
|
||||
(event)->Header.WaitListHead.Flink = (event)->Header.WaitListHead.Blink = \
|
||||
&(event)->Header.WaitListHead; \
|
||||
} while (0)
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef D3D8_KERNEL_MEMORY_H
|
||||
#define D3D8_KERNEL_MEMORY_H
|
||||
#include <xtl.h>
|
||||
/* Original Xbox kernel import: signature and import linkage are evidenced
|
||||
* by the supplied PDB and January resource/memory relocations. */
|
||||
extern "C" __declspec(dllimport) void WINAPI MmFreeContiguousMemory(
|
||||
void *baseAddress);
|
||||
extern "C" __declspec(dllimport) void *WINAPI MmAllocateContiguousMemoryEx(
|
||||
DWORD numberOfBytes,
|
||||
DWORD lowestAddress,
|
||||
DWORD highestAddress,
|
||||
DWORD alignment,
|
||||
DWORD protection);
|
||||
extern "C" __declspec(dllimport) DWORD WINAPI MmQueryAllocationSize(
|
||||
void *baseAddress);
|
||||
extern "C" __declspec(dllimport) void WINAPI MmPersistContiguousMemory(
|
||||
void *baseAddress,
|
||||
DWORD bytes,
|
||||
BYTE persist);
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef D3D8_KERNEL_RECORDS_H
|
||||
#define D3D8_KERNEL_RECORDS_H
|
||||
/* January-PDB kernel layouts used by the miniport. No later SDK layout is
|
||||
* substituted. Interrupt/DPC internals are opaque: only size/alignment and
|
||||
* actual containing-member addresses are needed by this driver. */
|
||||
#include <xtl.h>
|
||||
#include <stddef.h>
|
||||
struct _KINTERRUPT
|
||||
{
|
||||
DWORD Opaque[28];
|
||||
};
|
||||
struct _KDPC
|
||||
{
|
||||
DWORD Opaque[7];
|
||||
};
|
||||
struct _DISPATCHER_HEADER
|
||||
{
|
||||
BYTE Type;
|
||||
BYTE Absolute;
|
||||
BYTE Size;
|
||||
BYTE Inserted;
|
||||
LONG SignalState;
|
||||
LIST_ENTRY WaitListHead;
|
||||
};
|
||||
struct _KEVENT
|
||||
{
|
||||
_DISPATCHER_HEADER Header;
|
||||
};
|
||||
struct _HAL_SHUTDOWN_REGISTRATION
|
||||
{
|
||||
void (WINAPI *NotificationRoutine)(
|
||||
_HAL_SHUTDOWN_REGISTRATION *registration);
|
||||
LONG Priority;
|
||||
LIST_ENTRY ListEntry;
|
||||
};
|
||||
struct _TIME_FIELDS
|
||||
{
|
||||
SHORT Year;
|
||||
SHORT Month;
|
||||
SHORT Day;
|
||||
SHORT Hour;
|
||||
SHORT Minute;
|
||||
SHORT Second;
|
||||
SHORT Milliseconds;
|
||||
SHORT Weekday;
|
||||
};
|
||||
enum _EVENT_TYPE
|
||||
{
|
||||
NotificationEvent,
|
||||
SynchronizationEvent
|
||||
};
|
||||
enum _KINTERRUPT_MODE
|
||||
{
|
||||
LevelSensitive,
|
||||
Latched
|
||||
};
|
||||
typedef char kernel_interrupt_size[sizeof(_KINTERRUPT) == 112 ? 1 : -1];
|
||||
typedef char kernel_dpc_size[sizeof(_KDPC) == 28 ? 1 : -1];
|
||||
typedef char kernel_event_size[sizeof(_KEVENT) == 16 ? 1 : -1];
|
||||
typedef char kernel_shutdown_size[sizeof(_HAL_SHUTDOWN_REGISTRATION) == 16 ? 1 : -1];
|
||||
typedef char kernel_time_fields_size[sizeof(_TIME_FIELDS) == 16 ? 1 : -1];
|
||||
typedef char kernel_waitlist_offset[offsetof(_DISPATCHER_HEADER, WaitListHead) == 8 ? 1 : -1];
|
||||
typedef char kernel_event_header_offset[offsetof(_KEVENT, Header) == 0 ? 1 : -1];
|
||||
typedef char kernel_signal_offset[offsetof(_DISPATCHER_HEADER, SignalState) == 4 ? 1 : -1];
|
||||
typedef char kernel_shutdown_priority_offset[offsetof(_HAL_SHUTDOWN_REGISTRATION, Priority) == 4 ? 1 : -1];
|
||||
typedef char kernel_shutdown_list_offset[offsetof(_HAL_SHUTDOWN_REGISTRATION, ListEntry) == 8 ? 1 : -1];
|
||||
typedef char kernel_time_seconds_offset[offsetof(_TIME_FIELDS, Second) == 10 ? 1 : -1];
|
||||
#endif
|
||||
+1028
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,88 @@
|
||||
#ifndef D3D8_LAZY_INTERNAL_H
|
||||
#define D3D8_LAZY_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
/* Dirty bits and NV2A method fields established by the January routines. */
|
||||
enum
|
||||
{
|
||||
LAZY_DIRTY_POINT_PARAMS = 0x00000001,
|
||||
LAZY_DIRTY_TRANSFORM = 0x00000002,
|
||||
LAZY_DIRTY_TEXTURE_TRANSFORM = 0x00000004,
|
||||
LAZY_DIRTY_COMBINERS = 0x00000008,
|
||||
LAZY_DIRTY_TEXTURE_STATE = 0x00000010,
|
||||
LAZY_DIRTY_LIGHTS = 0x00000020,
|
||||
LAZY_DIRTY_SPEC_FOG = 0x00000040,
|
||||
LAZY_DIRTY_SHADER_STAGE_PROGRAM = 0x00000400,
|
||||
LAZY_DIRTY_VERTEX_FORMAT_VB = 0x00000080,
|
||||
LAZY_DIRTY_VERTEX_FORMAT_UP = 0x00000100,
|
||||
LAZY_DIRTY_VERTEX_OFFSETS = 0x00000200,
|
||||
LAZY_DIRECT_INPUT = 0x40000000,
|
||||
LAZY_VERTEX_FORMAT_METHOD = 0x1760,
|
||||
LAZY_VERTEX_OFFSET_METHOD = 0x1720,
|
||||
LAZY_SHADER_STAGE_METHOD = 0x1e70,
|
||||
LAZY_POINT_PARAMS_METHOD = 0xa30,
|
||||
LAZY_POINT_ENABLE_METHOD = 0x318,
|
||||
LAZY_POINT_SIZE_METHOD = 0x43c
|
||||
};
|
||||
extern const D3DVECTOR g_EyeDirection;
|
||||
DWORD WINAPI GetColorMaterial(
|
||||
void);
|
||||
void WINAPI LazySetShaderStageProgram(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetPointParams(
|
||||
CDevice *device);
|
||||
void WINAPI UpdateProjectionViewportTransform(
|
||||
void);
|
||||
void WINAPI SetState(
|
||||
void);
|
||||
void WINAPI LazySetCombiners(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetTextureState(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetSpecFogCombiner(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetTextureTransform(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetLights(
|
||||
CDevice *device);
|
||||
void WINAPI LazySetTransform(
|
||||
CDevice *device);
|
||||
DWORD *WINAPI SetLightColors(
|
||||
DWORD *push,
|
||||
const Light *light,
|
||||
DWORD lightNumber,
|
||||
DWORD colorMaterial);
|
||||
DWORD *WINAPI SetSceneAmbientAndMaterialEmission(
|
||||
DWORD *push,
|
||||
DWORD colorMaterial);
|
||||
DWORD *WINAPI SetSpecularParameters(
|
||||
DWORD *push);
|
||||
enum TextureMatrixType
|
||||
{
|
||||
TEXTURE_MATRIX_220 = 0x220,
|
||||
TEXTURE_MATRIX_230 = 0x230,
|
||||
TEXTURE_MATRIX_231 = 0x231,
|
||||
TEXTURE_MATRIX_241 = 0x241,
|
||||
TEXTURE_MATRIX_320 = 0x320,
|
||||
TEXTURE_MATRIX_330 = 0x330,
|
||||
TEXTURE_MATRIX_331 = 0x331,
|
||||
TEXTURE_MATRIX_341 = 0x341
|
||||
};
|
||||
/* The stream is DWORD-backed; use representation copies, not float aliasing. */
|
||||
__inline void WINAPI StoreFloat(
|
||||
DWORD *word,
|
||||
float value)
|
||||
{
|
||||
memcpy(word, &value, sizeof(value));
|
||||
return;
|
||||
}
|
||||
__inline float WINAPI Floatify(
|
||||
DWORD word)
|
||||
{
|
||||
float value;
|
||||
memcpy(&value, &word, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <xmmintrin.h>
|
||||
#include "math_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI ScaleVector3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *v,
|
||||
float scale)
|
||||
{
|
||||
out->x = scale * v->x;
|
||||
out->y = scale * v->y;
|
||||
out->z = scale * v->z;
|
||||
return;
|
||||
}
|
||||
void WINAPI AddVectors3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *a,
|
||||
const D3DVECTOR *b)
|
||||
{
|
||||
out->x = a->x + b->x;
|
||||
out->y = a->y + b->y;
|
||||
out->z = a->z + b->z;
|
||||
return;
|
||||
}
|
||||
float WINAPI SquareMagnitude3(
|
||||
const D3DVECTOR *v)
|
||||
{
|
||||
return v->x * v->x + v->y * v->y + v->z * v->z;
|
||||
}
|
||||
void WINAPI XformBy4x3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *v,
|
||||
float w,
|
||||
const D3DMATRIX *m)
|
||||
{
|
||||
// The original uses aligned matrix row loads and unaligned vector scalars.
|
||||
__m128 result = _mm_mul_ps(_mm_set1_ps(v->x), _mm_load_ps(m->m[0]));
|
||||
result = _mm_add_ps(result, _mm_mul_ps(_mm_set1_ps(v->y), _mm_load_ps(m->m[1])));
|
||||
result = _mm_add_ps(result, _mm_mul_ps(_mm_set1_ps(v->z), _mm_load_ps(m->m[2])));
|
||||
result = _mm_add_ps(result, _mm_mul_ps(_mm_set1_ps(w), _mm_load_ps(m->m[3])));
|
||||
_mm_storel_pi((__m64 *)out, result);
|
||||
_mm_store_ss(&out->z, _mm_shuffle_ps(result, result, 2));
|
||||
return;
|
||||
}
|
||||
void WINAPI MatrixProduct4x4(
|
||||
D3DMATRIX *out,
|
||||
const D3DMATRIX *a,
|
||||
const D3DMATRIX *b)
|
||||
{
|
||||
__m128 row0 = _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[0]), _mm_load_ps(a->m[0]), 0x00), _mm_load_ps(b->m[0]));
|
||||
row0 = _mm_add_ps(row0, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[0]), _mm_load_ps(a->m[0]), 0x55), _mm_load_ps(b->m[1])));
|
||||
row0 = _mm_add_ps(row0, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[0]), _mm_load_ps(a->m[0]), 0xaa), _mm_load_ps(b->m[2])));
|
||||
row0 = _mm_add_ps(row0, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[0]), _mm_load_ps(a->m[0]), 0xff), _mm_load_ps(b->m[3])));
|
||||
__m128 row1 = _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[1]), _mm_load_ps(a->m[1]), 0x00), _mm_load_ps(b->m[0]));
|
||||
row1 = _mm_add_ps(row1, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[1]), _mm_load_ps(a->m[1]), 0x55), _mm_load_ps(b->m[1])));
|
||||
row1 = _mm_add_ps(row1, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[1]), _mm_load_ps(a->m[1]), 0xaa), _mm_load_ps(b->m[2])));
|
||||
row1 = _mm_add_ps(row1, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[1]), _mm_load_ps(a->m[1]), 0xff), _mm_load_ps(b->m[3])));
|
||||
__m128 row2 = _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[2]), _mm_load_ps(a->m[2]), 0x00), _mm_load_ps(b->m[0]));
|
||||
row2 = _mm_add_ps(row2, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[2]), _mm_load_ps(a->m[2]), 0x55), _mm_load_ps(b->m[1])));
|
||||
row2 = _mm_add_ps(row2, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[2]), _mm_load_ps(a->m[2]), 0xaa), _mm_load_ps(b->m[2])));
|
||||
row2 = _mm_add_ps(row2, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[2]), _mm_load_ps(a->m[2]), 0xff), _mm_load_ps(b->m[3])));
|
||||
__m128 row3 = _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[3]), _mm_load_ps(a->m[3]), 0x00), _mm_load_ps(b->m[0]));
|
||||
row3 = _mm_add_ps(row3, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[3]), _mm_load_ps(a->m[3]), 0x55), _mm_load_ps(b->m[1])));
|
||||
row3 = _mm_add_ps(row3, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[3]), _mm_load_ps(a->m[3]), 0xaa), _mm_load_ps(b->m[2])));
|
||||
row3 = _mm_add_ps(row3, _mm_mul_ps(_mm_shuffle_ps(_mm_load_ps(a->m[3]), _mm_load_ps(a->m[3]), 0xff), _mm_load_ps(b->m[3])));
|
||||
_mm_store_ps(out->m[0], row0);
|
||||
_mm_store_ps(out->m[1], row1);
|
||||
_mm_store_ps(out->m[2], row2);
|
||||
_mm_store_ps(out->m[3], row3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef D3D8_MATH_INTERNAL_H
|
||||
#define D3D8_MATH_INTERNAL_H
|
||||
#include <xtl.h>
|
||||
namespace D3D
|
||||
{
|
||||
extern const D3DMATRIX g_IdentityMatrix;
|
||||
void WINAPI ScaleVector3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *v,
|
||||
float scale);
|
||||
void WINAPI AddVectors3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *a,
|
||||
const D3DVECTOR *b);
|
||||
float WINAPI SquareMagnitude3(
|
||||
const D3DVECTOR *v);
|
||||
void WINAPI XformBy4x3(
|
||||
D3DVECTOR *out,
|
||||
const D3DVECTOR *v,
|
||||
float w,
|
||||
const D3DMATRIX *m);
|
||||
void WINAPI MatrixProduct4x4(
|
||||
D3DMATRIX *out,
|
||||
const D3DMATRIX *a,
|
||||
const D3DMATRIX *b);
|
||||
void WINAPI NormalizeVector3(
|
||||
D3DVECTOR *vector);
|
||||
BOOL WINAPI Inverse4x4(
|
||||
D3DMATRIX *out,
|
||||
const D3DMATRIX *matrix,
|
||||
BOOL ignoreScale);
|
||||
long WINAPI FloatToLong(
|
||||
float value);
|
||||
__inline DWORD WINAPI Round(
|
||||
float value)
|
||||
{
|
||||
return FloatToLong(
|
||||
value + 0.5f);
|
||||
}
|
||||
void WINAPI Explut(
|
||||
float power,
|
||||
float *l,
|
||||
float *m);
|
||||
float WINAPI Cos(
|
||||
float value);
|
||||
float WINAPI Exp(
|
||||
float value);
|
||||
float WINAPI Log(
|
||||
float value);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,156 @@
|
||||
/* Reconstructed from the supplied January 2002 D3D memory object. */
|
||||
#include <xtl.h>
|
||||
#pragma code_seg("D3D")
|
||||
extern "C" void *WINAPI D3D_AllocNoncontiguousMemory(
|
||||
DWORD size)
|
||||
{
|
||||
return LocalAlloc(LMEM_ZEROINIT, size);
|
||||
}
|
||||
extern "C" HLOCAL WINAPI D3D_FreeNoncontiguousMemory(
|
||||
void *memory)
|
||||
{
|
||||
return LocalFree(memory);
|
||||
}
|
||||
void *WINAPI D3D_AllocContiguousMemory(
|
||||
DWORD size,
|
||||
DWORD alignment)
|
||||
{
|
||||
return XPhysicalAlloc(size, MAXULONG_PTR, alignment, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
}
|
||||
void WINAPI D3D_FreeContiguousMemory(
|
||||
void *memory)
|
||||
{
|
||||
if (memory)
|
||||
{
|
||||
XPhysicalFree(memory);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Rectangle-copy algorithm adapted from RXDK-Libs, 2026 Team Resurgent,
|
||||
* GPL-3.0-or-later. January's routine accepts bytes-per-pixel, not a
|
||||
* hardware format code. See libs/d3d8/PROVENANCE.md. */
|
||||
#include "push_internal.h"
|
||||
#include "memory_internal.h"
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI GPUCopyVideoRectangle(
|
||||
DWORD bytesPerPixel,
|
||||
DWORD sourceOffset,
|
||||
DWORD sourcePitch,
|
||||
DWORD destinationOffset,
|
||||
DWORD destinationPitch,
|
||||
DWORD count,
|
||||
RECT *rectangles,
|
||||
POINT *points)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
DWORD format;
|
||||
switch (bytesPerPixel)
|
||||
{
|
||||
case 1: format = 1; break;
|
||||
case 2: format = 4; break;
|
||||
case 4:
|
||||
default: format = 10; break;
|
||||
}
|
||||
PushCount(push, 0x8300, 4);
|
||||
push[1] = format;
|
||||
push[2] = (sourcePitch & 0xffff) | (destinationPitch << 16);
|
||||
push[3] = sourceOffset;
|
||||
push[4] = destinationOffset;
|
||||
device->EndPush(push + 5);
|
||||
while (count--)
|
||||
{
|
||||
push = device->StartPush();
|
||||
DWORD sourcePoint = ((DWORD)rectangles->left & 0xffff) | ((DWORD)rectangles->top << 16);
|
||||
DWORD destinationPoint = ((DWORD)points->x & 0xffff) | ((DWORD)points->y << 16);
|
||||
/* Disjoint 16-bit fields; XOR is the target's combining operation. */
|
||||
DWORD size = (((DWORD)rectangles->right - (DWORD)rectangles->left) & 0xffff)
|
||||
^ (((DWORD)rectangles->bottom - (DWORD)rectangles->top) << 16);
|
||||
PushCount(push, 0x6300, 3);
|
||||
push[1] = sourcePoint;
|
||||
push[2] = destinationPoint;
|
||||
push[3] = size;
|
||||
device->EndPush(push + 4);
|
||||
rectangles++;
|
||||
points++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#include "pusher_state.h"
|
||||
#include "notification_internal.h"
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI GPUCopyMemory(
|
||||
DWORD sourceOffset,
|
||||
DWORD destinationOffset,
|
||||
DWORD size)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
volatile NvNotification *notifiers = device->m_pMemCopyNotifiers;
|
||||
unsigned __int64 notified = ReadNotificationTime(¬ifiers[0]);
|
||||
if (size)
|
||||
{
|
||||
do
|
||||
{
|
||||
DWORD width, height, remaining;
|
||||
if (size <= 8192)
|
||||
{
|
||||
width = size;
|
||||
height = 1;
|
||||
remaining = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 8192;
|
||||
height = size / 8192;
|
||||
if (height <= 2047)
|
||||
{
|
||||
remaining = size % 8192;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = 2047;
|
||||
remaining = size - width * height;
|
||||
}
|
||||
}
|
||||
DWORD *push = device->StartPush();
|
||||
if (!remaining)
|
||||
{
|
||||
Push1(push, 0x4104, 0);
|
||||
push += 2;
|
||||
}
|
||||
PushCount(push, 0x4184, 2);
|
||||
push[1] = 5;
|
||||
push[2] = 4;
|
||||
PushCount(push + 3, 0x430c, 8);
|
||||
push[4] = sourceOffset;
|
||||
push[5] = destinationOffset;
|
||||
push[6] = width;
|
||||
push[7] = width;
|
||||
push[8] = width;
|
||||
push[9] = height;
|
||||
push[10] = 0x101;
|
||||
push[11] = 0;
|
||||
device->EndPush(push + 12);
|
||||
sourceOffset += size - remaining;
|
||||
destinationOffset += size - remaining;
|
||||
size = remaining;
|
||||
} while (size);
|
||||
device->KickOff();
|
||||
while (notified == ReadNotificationTime(¬ifiers[0]))
|
||||
{
|
||||
BusyLoop();
|
||||
}
|
||||
notified = ReadNotificationTime(¬ifiers[0]);
|
||||
while (ReadNotificationTime(¬ifiers[1]) < notified)
|
||||
{
|
||||
BusyLoop();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef D3D8_MEMORY_INTERNAL_H
|
||||
#define D3D8_MEMORY_INTERNAL_H
|
||||
#include <xtl.h>
|
||||
void *WINAPI D3D_AllocContiguousMemory(
|
||||
DWORD size,
|
||||
DWORD alignment);
|
||||
void WINAPI D3D_FreeContiguousMemory(
|
||||
void *memory);
|
||||
extern "C" void *WINAPI D3D_AllocNoncontiguousMemory(
|
||||
DWORD size);
|
||||
extern "C" HLOCAL WINAPI D3D_FreeNoncontiguousMemory(
|
||||
void *memory);
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI GPUCopyMemory(
|
||||
DWORD sourceOffset,
|
||||
DWORD destinationOffset,
|
||||
DWORD size);
|
||||
void WINAPI GPUCopyVideoRectangle(
|
||||
DWORD bytesPerPixel,
|
||||
DWORD sourceOffset,
|
||||
DWORD sourcePitch,
|
||||
DWORD destinationOffset,
|
||||
DWORD destinationPitch,
|
||||
DWORD count,
|
||||
RECT *rectangles,
|
||||
POINT *points);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef HALO_D3D8_MINIPORT_CONSTANTS_H
|
||||
#define HALO_D3D8_MINIPORT_CONSTANTS_H
|
||||
namespace D3D
|
||||
{
|
||||
/* NV2A object classes and memory-space values used by the target. Values are
|
||||
* checked against the supplied binary; names follow the hardware interfaces. */
|
||||
/* PLL register offsets and lock bits, as accessed by the January miniport. */
|
||||
enum PllRegister
|
||||
{
|
||||
NV_PRAMDAC_NVPLL_COEFF = 0x680500,
|
||||
NV_PRAMDAC_MPLL_COEFF = 0x680504,
|
||||
NV_PRAMDAC_VPLL_COEFF = 0x680508,
|
||||
NV_PRAMDAC_PLL_TEST_COUNTER = 0x680514,
|
||||
NV_PFB_EMRS = 0x1002c4,
|
||||
NV_PFB_MRS = 0x1002c0,
|
||||
NV_PFB_TIMING2 = 0x100228,
|
||||
NV_PBUS_DEBUG_3 = 0x108c
|
||||
};
|
||||
enum AgpClockRate
|
||||
{
|
||||
AGP_CLOCK_66_MHZ = 66000000,
|
||||
AGP_CLOCK_73_MHZ = 73000000,
|
||||
AGP_CLOCK_80_MHZ = 80000000,
|
||||
AGP_CLOCK_87_MHZ = 87000000,
|
||||
AGP_CLOCK_94_MHZ = 94000000,
|
||||
AGP_CLOCK_100_MHZ = 100000000,
|
||||
AGP_CLOCK_106_MHZ = 106000000,
|
||||
AGP_CLOCK_113_MHZ = 113000000,
|
||||
AGP_CLOCK_120_MHZ = 120000000,
|
||||
AGP_CLOCK_126_MHZ = 126000000,
|
||||
AGP_CLOCK_133_MHZ = 133000000
|
||||
};
|
||||
/* January software-method values; names describe the original dispatch.
|
||||
* The later SDK's packed 5-bit IDs are not interchangeable with these IDs. */
|
||||
enum MiniportSoftwareMethod
|
||||
{
|
||||
SoftwareFlipImmediate = 0x300,
|
||||
SoftwareFlipQueued = 0x304,
|
||||
SoftwareRunPushBuffer = 0x308,
|
||||
SoftwareFixupPushBuffer = 0x30c,
|
||||
SoftwareFence = 0x310,
|
||||
SoftwareReadCallback = 0x314,
|
||||
SoftwareWriteCallback = 0x318,
|
||||
SoftwareDxt1NoiseEnable = 0x31c,
|
||||
SoftwareWriteRegister = 0x320,
|
||||
SoftwareSetSurfacePitchAndOffset = 0x324
|
||||
};
|
||||
enum DmaObjectClass
|
||||
{
|
||||
NV01_CONTEXT_DMA_FROM_MEMORY = 0x02,
|
||||
NV01_CONTEXT_DMA_TO_MEMORY = 0x03,
|
||||
NV01_CONTEXT_DMA_IN_MEMORY = 0x3d
|
||||
};
|
||||
enum GraphicsObjectClass
|
||||
{
|
||||
NV03_NULL = 0x30,
|
||||
NV03_MEMORY_TO_MEMORY_FORMAT = 0x39,
|
||||
NV10_CONTEXT_SURFACES_2D = 0x62,
|
||||
NV20_KELVIN_PRIMITIVE = 0x97,
|
||||
NV12_IMAGE_BLIT = 0x9f
|
||||
};
|
||||
enum DmaAddressSpace
|
||||
{
|
||||
ADDR_SYSMEM = 1,
|
||||
ADDR_FBMEM = 2,
|
||||
ADDR_AGPMEM = 3
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,564 @@
|
||||
/* Portions adapted with reference to RXDK-Libs (2026 Team Resurgent),
|
||||
* GPL-3.0-or-later. See libs/d3d8/PROVENANCE.md and libs/d3d8/LICENSE.GPL-3.0.
|
||||
* Original January target bytes and PDB remain the matching authority. */
|
||||
/* January miniport helpers. Contracts and register accesses come from the
|
||||
* supplied target/PDB, not from a later miniport implementation. */
|
||||
#include "hardware_internal.h"
|
||||
#include "miniport_constants.h"
|
||||
#include "display_internal.h"
|
||||
#include "kernel_interrupt.h"
|
||||
#include "kernel_clock.h"
|
||||
#include <conio.h>
|
||||
#pragma intrinsic(_outp)
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
DWORD CMiniport::ReserveInstMem(
|
||||
DWORD paragraphs)
|
||||
{
|
||||
DWORD address = m_FreeInstAddr;
|
||||
m_FreeInstAddr += paragraphs;
|
||||
return address;
|
||||
}
|
||||
|
||||
int CMiniport::MapRegisters(
|
||||
void)
|
||||
{
|
||||
/* NV2A fixed kernel MMIO mapping in this Xbox build. These are hardware
|
||||
* registers: volatility is required for the actual device transaction. */
|
||||
_HWREG *base = (_HWREG *)0xfd000000UL;
|
||||
m_RegisterBase = base;
|
||||
WriteGpuRegister(base, 0x1804, ReadGpuRegister(base, 0x1804) | 4);
|
||||
WriteGpuRegister(base, 0x600140, 0);
|
||||
WriteGpuRegister(base, 0x9140, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CMiniport::TmrDelay(
|
||||
DWORD nanoseconds)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
DWORD start = ReadGpuRegister(base, 0x9400);
|
||||
while (ReadGpuRegister(base, 0x9400) - start < nanoseconds)
|
||||
{
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void CMiniport::InitGammaRamp(
|
||||
DWORD bank)
|
||||
{
|
||||
D3DGAMMARAMP *ramp = &m_GammaRamp[bank];
|
||||
for (DWORD value = 0; value < 256; ++value)
|
||||
{
|
||||
ramp->red[value] = (BYTE)value;
|
||||
ramp->green[value] = (BYTE)value;
|
||||
ramp->blue[value] = (BYTE)value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
int CMiniport::GetGeneralInfo(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
m_GenInfo.ChipId = (ReadGpuRegister(base, 0x1800) >> 16) & 0xfffc;
|
||||
m_GenInfo.MaskRevision = ReadGpuRegister(base, 0x1808) & 0xff;
|
||||
m_GenInfo.VideoRamSize = ReadGpuRegister(base, 0x10020c);
|
||||
m_GenInfo.CrystalFreq = 16666666;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CMiniport::GetAddressInfo(
|
||||
void *linearAddress,
|
||||
void **address,
|
||||
DWORD *addressSpace,
|
||||
int isAlias)
|
||||
{
|
||||
if (isAlias)
|
||||
{
|
||||
*address = (void *)(((DWORD)linearAddress & 0x0fffffffUL) | 0x40000000UL);
|
||||
*addressSpace = ADDR_AGPMEM;
|
||||
}
|
||||
else if (((DWORD)linearAddress & 0xf0000000UL) != 0x80000000UL)
|
||||
{
|
||||
*address = linearAddress;
|
||||
*addressSpace = ADDR_FBMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
*address = (void *)((DWORD)linearAddress & 0x03ffffffUL);
|
||||
*addressSpace = ADDR_SYSMEM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int CMiniport::BindToChannel(
|
||||
OBJECTINFO *object)
|
||||
{
|
||||
DWORD handle = object->Handle;
|
||||
DWORD hash = (((handle >> 11) ^ handle) >> 11) ^ handle;
|
||||
HalFifoHashAdd(hash & 0x7ff, handle, m_HalInfo.FifoChID,
|
||||
object->Instance, object->Engine);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CMiniport::InitDMAChannel(
|
||||
DWORD classNumber,
|
||||
OBJECTINFO *errorContext,
|
||||
OBJECTINFO *dataContext,
|
||||
DWORD offset,
|
||||
void **channel)
|
||||
{
|
||||
/* The January routine uses fixed channel/class/offset values. The public
|
||||
* parameters remain because they are part of the recorded interface. */
|
||||
m_HalInfo.FifoChID = 0;
|
||||
m_HalInfo.FifoMode = 0;
|
||||
m_HalInfo.FifoAllocCount = 0;
|
||||
m_HalInfo.FifoObjectCount = 0;
|
||||
m_HalInfo.FifoInstance = ReserveInstMem(0x37f);
|
||||
HalFifoAllocDMA(0x80, 0x80, 8, dataContext);
|
||||
*channel = (BYTE *)m_RegisterBase + ((m_HalInfo.FifoChID + 0x80) << 16);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CMiniport::CreateGrObject(
|
||||
DWORD handle,
|
||||
DWORD classNumber,
|
||||
OBJECTINFO *object)
|
||||
{
|
||||
BOOL is3d = FALSE;
|
||||
DWORD instanceSize;
|
||||
switch (classNumber)
|
||||
{
|
||||
case NV03_NULL:
|
||||
case NV03_MEMORY_TO_MEMORY_FORMAT:
|
||||
case NV10_CONTEXT_SURFACES_2D:
|
||||
case NV12_IMAGE_BLIT:
|
||||
instanceSize = 16;
|
||||
break;
|
||||
case NV20_KELVIN_PRIMITIVE:
|
||||
instanceSize = 0x330;
|
||||
is3d = TRUE;
|
||||
break;
|
||||
default:
|
||||
instanceSize = classNumber;
|
||||
break;
|
||||
}
|
||||
DWORD instance = ReserveInstMem(instanceSize >> 4);
|
||||
if (is3d)
|
||||
{
|
||||
m_HalInfo.GrCurrentObjects3d[m_HalInfo.FifoChID] = instance;
|
||||
HalGrInit3d();
|
||||
}
|
||||
HalGrInitObjectContext(instance, classNumber);
|
||||
object->Init();
|
||||
object->Handle = handle;
|
||||
object->ClassNum = classNumber;
|
||||
object->Instance = instance;
|
||||
object->Engine = 1;
|
||||
BindToChannel(object);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CMiniport::CreateCtxDmaObject(
|
||||
DWORD handle,
|
||||
DWORD classNumber,
|
||||
void *baseAddress,
|
||||
DWORD limit,
|
||||
OBJECTINFO *object)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
void *address = NULL;
|
||||
DWORD addressSpace = 0;
|
||||
GetAddressInfo(baseAddress, &address, &addressSpace, FALSE);
|
||||
DWORD instance = ReserveInstMem(1);
|
||||
DWORD page = (DWORD)address | 3;
|
||||
DWORD flags = 0;
|
||||
switch (classNumber)
|
||||
{
|
||||
case NV01_CONTEXT_DMA_FROM_MEMORY: flags = NV01_CONTEXT_DMA_FROM_MEMORY; break;
|
||||
case NV01_CONTEXT_DMA_TO_MEMORY: flags = NV01_CONTEXT_DMA_TO_MEMORY; break;
|
||||
case NV01_CONTEXT_DMA_IN_MEMORY: flags = NV01_CONTEXT_DMA_IN_MEMORY; break;
|
||||
}
|
||||
flags |= ((DWORD)address << 20) | 0x3000;
|
||||
switch (addressSpace)
|
||||
{
|
||||
case ADDR_FBMEM: break;
|
||||
case ADDR_AGPMEM: flags |= 0x30000; break;
|
||||
case ADDR_SYSMEM: flags |= 0x20000; break;
|
||||
}
|
||||
WriteGpuRegister(base, 0x700008 + (instance << 4), page);
|
||||
WriteGpuRegister(base, 0x70000c + (instance << 4), page);
|
||||
flags |= 0x8000;
|
||||
WriteGpuRegister(base, (0x70000 + instance) << 4, flags);
|
||||
WriteGpuRegister(base, 0x700004 + (instance << 4), limit);
|
||||
object->Init();
|
||||
object->Engine = 0;
|
||||
object->Handle = handle;
|
||||
object->ClassNum = classNumber;
|
||||
object->Instance = instance;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
int CMiniport::InitEngines(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
WriteGpuRegister(base, 0x1830, 0);
|
||||
WriteGpuRegister(base, 0x180c, 0xf800);
|
||||
HalMcControlInit();
|
||||
m_GenInfo.ChipIntrEn0 = 1;
|
||||
|
||||
// Reduce the clock ratio before encoding the 16-bit timer fractions.
|
||||
// The original calculation uses signed clock intermediates and unsigned
|
||||
// range comparisons; real device clock rates are positive.
|
||||
long numerator = (long)m_DacInfo.NVClk;
|
||||
long denominator = 31250000;
|
||||
while (numerator % 2 == 0 && denominator % 2 == 0)
|
||||
{
|
||||
numerator /= 2;
|
||||
denominator /= 2;
|
||||
}
|
||||
while (numerator % 5 == 0 && denominator % 5 == 0)
|
||||
{
|
||||
numerator /= 5;
|
||||
denominator /= 5;
|
||||
}
|
||||
while ((DWORD)numerator > 0x1fffe || (DWORD)denominator > 0x1fffe)
|
||||
{
|
||||
numerator /= 2;
|
||||
denominator /= 2;
|
||||
}
|
||||
WriteGpuRegister(base, 0x9200, (numerator + 1) / 2);
|
||||
WriteGpuRegister(base, 0x9210, (denominator + 1) / 2);
|
||||
WriteGpuRegister(base, 0x9420, 0xffffffffUL);
|
||||
HalFbControlInit();
|
||||
HalDacControlInit();
|
||||
InitGammaRamp(0);
|
||||
HalVideoControlInit();
|
||||
m_HalInfo.GrChID = 2;
|
||||
HalGrControlInit();
|
||||
HalFifoControlInit();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
/* Drain the actual FIFO/graphics pipeline before modifying tile/context state.
|
||||
* Hardware status bits may change asynchronously; all polls are MMIO accesses. */
|
||||
void CMiniport::TilingUpdateIdle(
|
||||
DWORD *savedPush)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
while (!(ReadGpuRegister(base, 0x3214) & 0x10) ||
|
||||
!(ReadGpuRegister(base, 0x2400) & 0x10) ||
|
||||
(ReadGpuRegister(base, 0x3220) & 0x10))
|
||||
{
|
||||
ServiceFifoInterrupt();
|
||||
if (ReadGpuRegister(base, 0x400100))
|
||||
{
|
||||
ServiceGrInterrupt();
|
||||
}
|
||||
if (ReadGpuRegister(base, 0x100) & 0x1000000)
|
||||
{
|
||||
VBlank();
|
||||
}
|
||||
}
|
||||
*savedPush = ReadGpuRegister(base, 0x3220);
|
||||
WriteGpuRegister(base, 0x3220, 0);
|
||||
while (ReadGpuRegister(base, 0x3220) & 0x10)
|
||||
{
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void CMiniport::ShutdownEngines(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
if (!AvGetSavedDataAddress())
|
||||
{
|
||||
AvSendTVEncoderOption(base, AV_OPTION_BLANK_SCREEN, TRUE, NULL);
|
||||
}
|
||||
for (int tile = 0; tile < 8; ++tile)
|
||||
{
|
||||
DestroyTile(tile, TRUE);
|
||||
}
|
||||
WriteGpuRegister(base, 0x2044, 0);
|
||||
// Shutdown has its own drain sequence: unlike TilingUpdateIdle it does not
|
||||
// retain the DMA push register for resuming later. This separation is also
|
||||
// present in the pinned mpcore reference, not manual helper expansion.
|
||||
while (!(ReadGpuRegister(base, 0x3214) & 0x10) ||
|
||||
!(ReadGpuRegister(base, 0x2400) & 0x10) ||
|
||||
(ReadGpuRegister(base, 0x3220) & 0x10))
|
||||
{
|
||||
ServiceFifoInterrupt();
|
||||
if (ReadGpuRegister(base, 0x400100))
|
||||
{
|
||||
ServiceGrInterrupt();
|
||||
}
|
||||
if (ReadGpuRegister(base, 0x100) & 0x1000000)
|
||||
{
|
||||
VBlank();
|
||||
}
|
||||
}
|
||||
WriteGpuRegister(base, 0x3220, 0);
|
||||
while (ReadGpuRegister(base, 0x3220) & 0x10)
|
||||
{
|
||||
}
|
||||
WriteGpuRegister(base, 0x2500, 0);
|
||||
WriteGpuRegister(base, 0x3000, 0);
|
||||
WriteGpuRegister(base, 0x3050, 0);
|
||||
WriteGpuRegister(base, 0x3200, 0);
|
||||
WriteGpuRegister(base, 0x3250, 0);
|
||||
HalFifoContextSwitch(1);
|
||||
WriteGpuRegister(base, 0x3210, 0);
|
||||
WriteGpuRegister(base, 0x3270, 0);
|
||||
|
||||
DWORD fifoReassign = ReadGpuRegister(base, 0x2500);
|
||||
DWORD fifoPush = ReadGpuRegister(base, 0x3200);
|
||||
DWORD fifoPull = ReadGpuRegister(base, 0x3250);
|
||||
WriteGpuRegister(base, 0x2500, 0);
|
||||
WriteGpuRegister(base, 0x3200, 0);
|
||||
WriteGpuRegister(base, 0x3250, 0);
|
||||
for (DWORD channel = 0; channel < 2; ++channel)
|
||||
{
|
||||
if (m_HalInfo.FifoInUse)
|
||||
{
|
||||
WriteGpuRegister(base, m_HalInfo.FifoContextAddr1 + channel * 64 + 4,
|
||||
ReadGpuRegister(base, m_HalInfo.FifoContextAddr1 + channel * 64));
|
||||
WriteGpuRegister(base, m_HalInfo.FifoContextAddr1 + channel * 64 + 16, 0);
|
||||
}
|
||||
}
|
||||
WriteGpuRegister(base, 0x3250, fifoPull);
|
||||
WriteGpuRegister(base, 0x3200, fifoPush);
|
||||
WriteGpuRegister(base, 0x2500, fifoReassign);
|
||||
WriteGpuRegister(base, 0x2508, 0);
|
||||
WriteGpuRegister(base, 0x2140, 0);
|
||||
HalGrLoadChannelContext(2);
|
||||
WriteGpuRegister(base, 0x100200, m_HalInfo.FbSave0);
|
||||
WriteGpuRegister(base, 0x100204, m_HalInfo.FbSave1);
|
||||
WriteGpuRegister(base, 0x200, m_HalInfo.McSave);
|
||||
WriteGpuRegister(base, 0x140, m_HalInfo.McSaveIntrEn0);
|
||||
HalRegisterShutdownNotification(
|
||||
&m_ShutdownRegistration, FALSE);
|
||||
KeDisconnectInterrupt(&m_InterruptObject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
/* Tile lifecycle reconstructed from January target accesses and corroborated
|
||||
* by pinned RXDK mpcore. Valid callers provide tile indices below eight and
|
||||
* aligned, GPU-addressable regions. Device readbacks can require retrying. */
|
||||
int CMiniport::CreateTile(
|
||||
DWORD tile,
|
||||
DWORD offset,
|
||||
DWORD size,
|
||||
DWORD pitch,
|
||||
DWORD memoryType,
|
||||
DWORD zTag,
|
||||
DWORD zOffset)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
DWORD dmaPush;
|
||||
TilingUpdateIdle(&dmaPush);
|
||||
do
|
||||
{
|
||||
HalGrIdle();
|
||||
WriteGpuRegister(base, 0x100244 + tile * 16, offset + size - 1);
|
||||
WriteGpuRegister(base, 0x100248 + tile * 16, pitch);
|
||||
WriteGpuRegister(base, 0x400904 + tile * 16, offset + size - 1);
|
||||
WriteGpuRegister(base, 0x400908 + tile * 16, pitch);
|
||||
if (memoryType & D3DTILE_FLAGS_ZBUFFER)
|
||||
{
|
||||
WriteGpuRegister(base, 0x400900 + tile * 16, offset | 3);
|
||||
WriteGpuRegister(base, 0x100240 + tile * 16, offset | 3);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x10) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, offset | 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteGpuRegister(base, 0x400900 + tile * 16, offset | 1);
|
||||
WriteGpuRegister(base, 0x100240 + tile * 16, offset | 1);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x10) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, offset | 1);
|
||||
}
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x30) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, offset + size - 1);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x50) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, pitch);
|
||||
} while (ReadGpuRegister(base, 0x100240 + tile * 16) != ReadGpuRegister(base, 0x400900 + tile * 16) ||
|
||||
ReadGpuRegister(base, 0x100248 + tile * 16) != ReadGpuRegister(base, 0x400908 + tile * 16) ||
|
||||
(ReadGpuRegister(base, 0x100244 + tile * 16) & ~0x3fffUL) !=
|
||||
(ReadGpuRegister(base, 0x400904 + tile * 16) & ~0x3fffUL));
|
||||
if (memoryType & D3DTILE_FLAGS_ZCOMPRESS)
|
||||
{
|
||||
DWORD zData = (zTag / 4) | 0x80000000UL;
|
||||
if (memoryType & D3DTILE_FLAGS_Z32BITS)
|
||||
{
|
||||
zData |= 0x04000000;
|
||||
}
|
||||
do
|
||||
{
|
||||
HalGrIdle();
|
||||
WriteGpuRegister(base, 0x100300 + tile * 4, zData);
|
||||
WriteGpuRegister(base, 0x400980 + tile * 4, zData);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x90) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, zData);
|
||||
} while (ReadGpuRegister(base, 0x100300 + tile * 4) !=
|
||||
ReadGpuRegister(base, 0x400980 + tile * 4));
|
||||
if (zOffset != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
DWORD zOffsetValue = zOffset | tile | 0x80000000UL;
|
||||
HalGrIdle();
|
||||
WriteGpuRegister(base, 0x100324, zOffsetValue);
|
||||
WriteGpuRegister(base, 0x4009a0, zOffsetValue);
|
||||
} while (ReadGpuRegister(base, 0x100324) != ReadGpuRegister(base, 0x4009a0));
|
||||
}
|
||||
}
|
||||
WriteGpuRegister(base, 0x3220, dmaPush);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CMiniport::DestroyTile(
|
||||
DWORD tile,
|
||||
DWORD zOffset)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
DWORD dmaPush;
|
||||
TilingUpdateIdle(&dmaPush);
|
||||
do
|
||||
{
|
||||
HalGrIdle();
|
||||
WriteGpuRegister(base, 0x100240 + tile * 16, 0);
|
||||
WriteGpuRegister(base, 0x400900 + tile * 16, 0);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x10) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, 0);
|
||||
} while (ReadGpuRegister(base, 0x100240 + tile * 16) !=
|
||||
ReadGpuRegister(base, 0x400900 + tile * 16));
|
||||
WriteGpuRegister(base, 0x100300 + tile * 4, 0);
|
||||
WriteGpuRegister(base, 0x400980 + tile * 4, 0);
|
||||
WriteGpuRegister(base, 0x400750, 0xea0000 | ((tile * 4 + 0x90) & 0x1ffc));
|
||||
WriteGpuRegister(base, 0x400754, 0);
|
||||
if (zOffset != 0)
|
||||
{
|
||||
WriteGpuRegister(base, 0x100324, 0);
|
||||
WriteGpuRegister(base, 0x4009a0, 0);
|
||||
}
|
||||
WriteGpuRegister(base, 0x3220, dmaPush);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
int CMiniport::LoadEngines(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
DWORD command = ReadGpuRegister(base, 0x184c);
|
||||
WriteGpuRegister(base, 0x184c, command & ~0x300UL);
|
||||
WriteGpuRegister(base, 0x184c, command);
|
||||
WriteGpuRegister(base, 0x200, 0xffffffffUL);
|
||||
EnableInterrupts();
|
||||
HalDacLoad();
|
||||
|
||||
LARGE_INTEGER systemTime;
|
||||
_TIME_FIELDS fields;
|
||||
static const BYTE timerMonthDays[12] =
|
||||
{
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
KeQuerySystemTime(&systemTime);
|
||||
RtlTimeToTimeFields(&systemTime, &fields);
|
||||
if (fields.Year > 1990)
|
||||
{
|
||||
fields.Year -= 1990;
|
||||
}
|
||||
DWORD days = fields.Year * 365 + (fields.Year + 1) / 4;
|
||||
if (!((fields.Year + 2) & 3) && fields.Month > 2)
|
||||
{
|
||||
++days;
|
||||
}
|
||||
// Preserve the original timer's month indexing, rather than substituting
|
||||
// a corrected calendar conversion. Kernel TIME_FIELDS months are 1..12.
|
||||
while (--fields.Month)
|
||||
{
|
||||
days += timerMonthDays[fields.Month];
|
||||
}
|
||||
days += fields.Day;
|
||||
DWORD highTime = days * 20117 + fields.Hour * 838 +
|
||||
(fields.Minute * 257698 + fields.Second * 4295) / 1000;
|
||||
highTime += 146951526;
|
||||
WriteGpuRegister(base, 0x9400, 0);
|
||||
WriteGpuRegister(base, 0x9410, highTime);
|
||||
WriteGpuRegister(base, 0x400720, 0);
|
||||
HalGrControlLoad();
|
||||
WriteGpuRegister(base, 0x400100, 0xffffffffUL);
|
||||
WriteGpuRegister(base, 0x400140, 0xffffffffUL);
|
||||
HalFifoControlLoad();
|
||||
WriteGpuRegister(base, 0x2100, 0xffffffffUL);
|
||||
WriteGpuRegister(base, 0x2140, m_HalInfo.FifoIntrEn0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CMiniport::InitHardware(
|
||||
void)
|
||||
{
|
||||
KeInitializeDpc(&m_Dpc, CMiniport::Dpc, this);
|
||||
KeInitializeEvent(&m_BusyBlockEvent, NotificationEvent, TRUE);
|
||||
KeInitializeEvent(&m_VerticalBlankEvent, NotificationEvent, TRUE);
|
||||
if (!MapRegisters())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!GetGeneralInfo())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BYTE interruptIrql;
|
||||
DWORD vector = HalGetInterruptVector(3, &interruptIrql);
|
||||
KeInitializeInterrupt(&m_InterruptObject, CMiniport::Isr, this,
|
||||
vector, interruptIrql, LevelSensitive, TRUE);
|
||||
if (!KeConnectInterrupt(&m_InterruptObject))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
m_ShutdownRegistration.NotificationRoutine = CMiniport::ShutdownNotification;
|
||||
m_ShutdownRegistration.Priority = 0;
|
||||
HalRegisterShutdownNotification(&m_ShutdownRegistration, TRUE);
|
||||
if (!InitEngines())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
for (DWORD bank = 0; bank < 2; ++bank)
|
||||
{
|
||||
D3DGAMMARAMP *ramp = &m_GammaRamp[bank];
|
||||
for (DWORD value = 0; value < 256; ++value)
|
||||
{
|
||||
ramp->red[value] = (BYTE)value;
|
||||
ramp->green[value] = (BYTE)value;
|
||||
ramp->blue[value] = (BYTE)value;
|
||||
}
|
||||
}
|
||||
_outp(0x80c0, 1);
|
||||
m_InterruptsEnabled = TRUE;
|
||||
if (!LoadEngines())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* January target/PDB reconstruction. Hardware writes are not executed here. */
|
||||
#include <conio.h>
|
||||
#include "hardware_internal.h"
|
||||
#pragma intrinsic(_inp)
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
void CMiniport::DacProgramGammaRamp(
|
||||
D3DGAMMARAMP *ramp)
|
||||
{
|
||||
volatile BYTE *registers = (volatile BYTE *)m_RegisterBase;
|
||||
registers[0x6813c8] = 0;
|
||||
for (DWORD i = 0; i < 256; ++i)
|
||||
{
|
||||
registers[0x6813c9] = ramp->red[i];
|
||||
registers[0x6813c9] = ramp->green[i];
|
||||
registers[0x6813c9] = ramp->blue[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void CMiniport::DacProgramVideoStart(
|
||||
DWORD offset)
|
||||
{
|
||||
DWORD oddField = ((DWORD)_inp(0x80c0) & 0x20UL) >> 5;
|
||||
volatile DWORD *registers = (volatile DWORD *)m_RegisterBase;
|
||||
DWORD mode = m_DisplayMode & 0xc0000000UL;
|
||||
if (mode == 0x40000000UL) oddField = !oddField;
|
||||
if (!m_FirstFlip)
|
||||
{
|
||||
if ((m_CurrentAvInfo & 0x01000000) && mode != 0x80000000UL && oddField)
|
||||
{
|
||||
offset -= m_SurfacePitch / 2;
|
||||
}
|
||||
else if (mode == 0x80000000UL && (m_CurrentAvInfo & 0x00200000) && oddField)
|
||||
{
|
||||
offset += m_SurfacePitch;
|
||||
}
|
||||
registers[0x600800 / sizeof(DWORD)] = offset;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
+1118
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,419 @@
|
||||
/* January-PDB miniport interrupt helpers; actual MMIO read/write ordering.
|
||||
* No hardware or original game image is executed by this reconstruction. */
|
||||
#include "hardware_internal.h"
|
||||
#include "kernel_interrupt.h"
|
||||
#include "display_internal.h"
|
||||
#include "miniport_constants.h"
|
||||
#include "kernel_debug.h"
|
||||
#include "memory_internal.h"
|
||||
#include "pusher_state.h"
|
||||
#include <conio.h>
|
||||
#pragma intrinsic(_inp)
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
DWORD CMiniport::ServiceMediaPortInterrupt(
|
||||
void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void CMiniport::GrDone(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
while (ReadGpuRegister(base, 0x400700))
|
||||
{
|
||||
}
|
||||
return;
|
||||
}
|
||||
DWORD CMiniport::ServiceVideoInterrupt(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
if (ReadGpuRegister(base, 0x8100) & 1)
|
||||
{
|
||||
WriteGpuRegister(base, 0x8100, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI CMiniport::ShutdownNotification(
|
||||
_HAL_SHUTDOWN_REGISTRATION *registration)
|
||||
{
|
||||
CMiniport *miniport = CONTAINING_RECORD(registration,
|
||||
CMiniport, m_ShutdownRegistration);
|
||||
miniport->DisableInterrupts();
|
||||
miniport->ShutdownEngines();
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI CMiniport::Dpc(
|
||||
_KDPC *dpc,
|
||||
void *context,
|
||||
void *argument1,
|
||||
void *argument2)
|
||||
{
|
||||
CMiniport *miniport = (CMiniport *)context;
|
||||
_HWREG *base = (_HWREG *)miniport->m_RegisterBase;
|
||||
DWORD pending;
|
||||
do
|
||||
{
|
||||
DWORD interrupts = ReadGpuRegister(base, 0x100);
|
||||
pending = 0;
|
||||
if (interrupts & 0x100000)
|
||||
{
|
||||
WriteGpuRegister(base, 0x9100, 1);
|
||||
pending = ReadGpuRegister(base, 0x9100);
|
||||
}
|
||||
if (interrupts & 0x01000000)
|
||||
{
|
||||
pending |= miniport->VBlank();
|
||||
}
|
||||
if (interrupts & 0x1000)
|
||||
{
|
||||
pending |= miniport->ServiceGrInterrupt();
|
||||
}
|
||||
if ((interrupts & 0x100) || (ReadGpuRegister(base, 0x2080) & 1))
|
||||
{
|
||||
pending |= miniport->ServiceFifoInterrupt();
|
||||
}
|
||||
if (interrupts & 0x10000)
|
||||
{
|
||||
pending |= miniport->ServiceVideoInterrupt();
|
||||
}
|
||||
} while (pending);
|
||||
miniport->EnableInterrupts();
|
||||
return;
|
||||
}
|
||||
|
||||
void CMiniport::FixupPushBuffer(
|
||||
PUSHBUFFERFIXUPINFO *fixup,
|
||||
DWORD method)
|
||||
{
|
||||
BYTE *start = fixup->pStart;
|
||||
const BYTE *record = (const BYTE *)fixup->pFixup;
|
||||
if (record)
|
||||
{
|
||||
DWORD length;
|
||||
memcpy(&length, record, sizeof(length));
|
||||
while (length != 0xffffffffUL)
|
||||
{
|
||||
DWORD destination;
|
||||
memcpy(&destination, record + sizeof(DWORD), sizeof(destination));
|
||||
record += 2 * sizeof(DWORD);
|
||||
memcpy(start + destination, record, length);
|
||||
record += length;
|
||||
memcpy(&length, record, sizeof(length));
|
||||
}
|
||||
}
|
||||
DWORD returnAddress = (DWORD)fixup->ReturnAddress & 0x0fffffffUL;
|
||||
// Snapshot the destination before patching memory: the write must not
|
||||
// cause a later reload of the fixup record's original return offset.
|
||||
DWORD returnOffset = fixup->ReturnOffset;
|
||||
DWORD jump = returnAddress + 1;
|
||||
memcpy(start + returnOffset, &jump, sizeof(jump));
|
||||
if (method == 0x308)
|
||||
{
|
||||
WriteGpuRegister((_HWREG *)m_RegisterBase, 0x324c, returnAddress);
|
||||
m_PusherGetRunSize += returnOffset;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
DWORD g_Adjusts;
|
||||
DWORD g_VideoOffset;
|
||||
|
||||
int CMiniport::IsFlipPending(
|
||||
void)
|
||||
{
|
||||
return m_VBlankFlips[m_VBlankFlipNext].Pending;
|
||||
}
|
||||
|
||||
BYTE WINAPI CMiniport::Isr(
|
||||
_KINTERRUPT *interrupt,
|
||||
void *context)
|
||||
{
|
||||
CMiniport *miniport = (CMiniport *)context;
|
||||
_HWREG *base = (_HWREG *)miniport->m_RegisterBase;
|
||||
if (miniport->m_InterruptsEnabled && ReadGpuRegister(base, 0x140))
|
||||
{
|
||||
DWORD pending = ReadGpuRegister(base, 0x100);
|
||||
if (pending)
|
||||
{
|
||||
if (pending & 0x01000000)
|
||||
{
|
||||
if (miniport->m_VBlankFlips[miniport->m_VBlankFlipNext].Pending == TRUE &&
|
||||
(miniport->m_PresentationInterval != D3DPRESENT_INTERVAL_TWO ||
|
||||
miniport->IsOddField()))
|
||||
{
|
||||
g_VideoOffset = miniport->m_VBlankFlips[miniport->m_VBlankFlipNext].Offset;
|
||||
miniport->DacProgramVideoStart(g_VideoOffset);
|
||||
}
|
||||
else if ((miniport->m_DisplayMode & 0xc0000000UL) == 0x80000000UL &&
|
||||
(miniport->m_CurrentAvInfo & 0x00200000))
|
||||
{
|
||||
miniport->DacProgramVideoStart(g_VideoOffset);
|
||||
}
|
||||
}
|
||||
miniport->DisableInterrupts();
|
||||
KeInsertQueueDpc(&miniport->m_Dpc, NULL, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD CMiniport::VBlank(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
BYTE crtcIndex = ReadGpuRegister8(base, 0x6013d4);
|
||||
++m_VBlankCount;
|
||||
if (m_VBlankFlips[m_VBlankFlipNext].Pending == TRUE &&
|
||||
(m_PresentationInterval != D3DPRESENT_INTERVAL_TWO || IsOddField()))
|
||||
{
|
||||
DacProgramVideoStart(m_VBlankFlips[m_VBlankFlipNext].Offset);
|
||||
m_VBlankFlips[m_VBlankFlipNext].Pending = FALSE;
|
||||
DWORD bank = m_VBlankFlipCount & 1;
|
||||
if (m_GammaUpdated[bank] == TRUE)
|
||||
{
|
||||
DacProgramGammaRamp(&m_GammaRamp[bank]);
|
||||
m_GammaUpdated[bank] = FALSE;
|
||||
}
|
||||
WriteGpuRegister(base, 0x40071c, ReadGpuRegister(base, 0x40071c) | 2);
|
||||
if (++m_VBlankFlipNext == 5)
|
||||
{
|
||||
m_VBlankFlipNext = 0;
|
||||
}
|
||||
++m_VBlankFlipCount;
|
||||
}
|
||||
do
|
||||
{
|
||||
WriteGpuRegister(base, 0x600100, 1);
|
||||
} while (ReadGpuRegister(base, 0x100) & 0x01000000);
|
||||
KeSetEvent(&m_VerticalBlankEvent, 1, FALSE);
|
||||
if (m_pVerticalBlankCallback)
|
||||
{
|
||||
m_pVerticalBlankCallback(m_VBlankCount);
|
||||
}
|
||||
WriteGpuRegister8(base, 0x6013d4, crtcIndex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void CMiniport::SoftwareMethod(
|
||||
DWORD method,
|
||||
DWORD data)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
switch (method)
|
||||
{
|
||||
case SoftwareFlipImmediate:
|
||||
{
|
||||
DacProgramVideoStart(data);
|
||||
WriteGpuRegister(base, 0x40071c, ReadGpuRegister(base, 0x40071c) | 2);
|
||||
DWORD bank = m_VBlankFlipCount & 1;
|
||||
if (m_GammaUpdated[bank] == TRUE)
|
||||
{
|
||||
DacProgramGammaRamp(&m_GammaRamp[bank]);
|
||||
m_GammaUpdated[bank] = FALSE;
|
||||
}
|
||||
++m_VBlankFlipCount;
|
||||
}
|
||||
break;
|
||||
case SoftwareFlipQueued:
|
||||
m_VBlankFlips[m_VBlankQueueNext].Pending = TRUE;
|
||||
m_VBlankFlips[m_VBlankQueueNext].Offset = data;
|
||||
if (++m_VBlankQueueNext == 5)
|
||||
{
|
||||
m_VBlankQueueNext = 0;
|
||||
}
|
||||
break;
|
||||
case SoftwareRunPushBuffer:
|
||||
case SoftwareFixupPushBuffer:
|
||||
{
|
||||
PUSHBUFFERFIXUPINFO fixup = *(PUSHBUFFERFIXUPINFO *)data;
|
||||
FixupPushBuffer(&fixup, method);
|
||||
FlushWCCache();
|
||||
}
|
||||
break;
|
||||
case SoftwareFence:
|
||||
KeSetEvent(&m_BusyBlockEvent, 1, FALSE);
|
||||
break;
|
||||
case SoftwareReadCallback:
|
||||
case SoftwareWriteCallback:
|
||||
((D3DCALLBACK)data)(ReadGpuRegister(base, 0x40186c));
|
||||
break;
|
||||
case SoftwareDxt1NoiseEnable:
|
||||
WriteGpuRegister(base, 0x400750, 0xe00050);
|
||||
WriteGpuRegister(base, 0x400754, data);
|
||||
WriteGpuRegister(base, 0x400750, 0xdf0008);
|
||||
WriteGpuRegister(base, 0x400754, data);
|
||||
break;
|
||||
case SoftwareWriteRegister:
|
||||
WriteGpuRegister(base, data, ReadGpuRegister(base, 0x40186c));
|
||||
break;
|
||||
case SoftwareSetSurfacePitchAndOffset:
|
||||
{
|
||||
DWORD offset = ReadGpuRegister(base, 0x40186c);
|
||||
if (offset != ReadGpuRegister(base, 0x400828))
|
||||
{
|
||||
DbgPrint("D3D: Adjusting offset\n");
|
||||
WriteGpuRegister(base, 0x400828, offset);
|
||||
++g_Adjusts;
|
||||
}
|
||||
if (data != ReadGpuRegister(base, 0x400858))
|
||||
{
|
||||
DbgPrint("D3D: Adjusting pitch\n");
|
||||
WriteGpuRegister(base, 0x400858, data);
|
||||
++g_Adjusts;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD CMiniport::ServiceGrInterrupt(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
WriteGpuRegister(base, 0x400720, 0);
|
||||
DWORD interrupts = ReadGpuRegister(base, 0x400100);
|
||||
DWORD method = ReadGpuRegister(base, 0x400704);
|
||||
DWORD notifySource = ReadGpuRegister(base, 0x400108);
|
||||
DWORD channel = (method >> 20) & 0x1f;
|
||||
method &= 0x1ffc;
|
||||
if (interrupts & 0x1000)
|
||||
{
|
||||
WriteGpuRegister(base, 0x400100, 0x1000);
|
||||
GrDone();
|
||||
HalGrLoadChannelContext(channel);
|
||||
}
|
||||
if (interrupts & 0x10)
|
||||
{
|
||||
WriteGpuRegister(base, 0x400100, 0x10);
|
||||
}
|
||||
if (((interrupts & 1) || (interrupts & 0x100000)) && (notifySource & 0x40))
|
||||
{
|
||||
WriteGpuRegister(base, 0x400100, (interrupts & 1) ? 1 : 0x100000);
|
||||
}
|
||||
interrupts = ReadGpuRegister(base, 0x400100);
|
||||
if (interrupts)
|
||||
{
|
||||
WriteGpuRegister(base, 0x400100, interrupts);
|
||||
if (interrupts != 0x1000 && interrupts != 0x01000000)
|
||||
{
|
||||
if (interrupts & 0x10)
|
||||
{
|
||||
GrDone();
|
||||
}
|
||||
if (notifySource && ((interrupts & 1) || (interrupts & 0x100000)))
|
||||
{
|
||||
DWORD objectClass = ReadGpuRegister(base, 0x40014c) & 0xff;
|
||||
DWORD data = ReadGpuRegister(base, 0x400708);
|
||||
if (!(notifySource & 0x40))
|
||||
{
|
||||
if (method == 0x100)
|
||||
{
|
||||
SoftwareMethod(data, ReadGpuRegister(base, 0x401a88));
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("MP: GRAPHICS HARDWARE ERROR\nMP: Source: %08x\nMP: ChID: %d\nMP: Class: %x\nMP: Offset: %08x\nMP: Data: %08x\n", notifySource, channel, objectClass, method, data);
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (interrupts & 0x10000)
|
||||
{
|
||||
GrDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteGpuRegister(base, 0x400720, 1);
|
||||
return ReadGpuRegister(base, 0x400100);
|
||||
}
|
||||
|
||||
DWORD CMiniport::ServiceFifoInterrupt(
|
||||
void)
|
||||
{
|
||||
_HWREG *base = (_HWREG *)m_RegisterBase;
|
||||
DWORD interrupts = ReadGpuRegister(base, 0x2100);
|
||||
if (interrupts & 0x100000)
|
||||
{
|
||||
WriteGpuRegister(base, 0x2100, 0x100000);
|
||||
}
|
||||
if (interrupts & 0x01000000)
|
||||
{
|
||||
WriteGpuRegister(base, 0x2100, 0x01000000);
|
||||
}
|
||||
interrupts = ReadGpuRegister(base, 0x2100);
|
||||
if (interrupts & 1)
|
||||
{
|
||||
DWORD pull = ReadGpuRegister(base, 0x3250);
|
||||
WriteGpuRegister(base, 0x2500, 0);
|
||||
WriteGpuRegister(base, 0x3250, 0);
|
||||
WriteGpuRegister(base, 0x2100, 1);
|
||||
DWORD retries = 0xffff;
|
||||
do
|
||||
{
|
||||
if (!(pull & 0x1000))
|
||||
{
|
||||
break;
|
||||
}
|
||||
pull = ReadGpuRegister(base, 0x3250);
|
||||
} while (--retries);
|
||||
WriteGpuRegister(base, 0x3258, 0);
|
||||
WriteGpuRegister(base, 0x3250, 1);
|
||||
WriteGpuRegister(base, 0x2500, 1);
|
||||
}
|
||||
if (interrupts & 0x1000)
|
||||
{
|
||||
DbgPrint("SW PUT=%x\n", g_pDevice->m_Pusher.m_pPut);
|
||||
DbgPrint("HW PUT=%x\n", *(volatile DWORD *)0xfd003240UL);
|
||||
DbgPrint("HW GET=%x\n", *(volatile DWORD *)0xfd003244UL);
|
||||
WriteGpuRegister(base, 0x2100, 0x1000);
|
||||
WriteGpuRegister(base, 0x3228, 0);
|
||||
if (ReadGpuRegister(base, 0x3240) != ReadGpuRegister(base, 0x3244))
|
||||
{
|
||||
WriteGpuRegister(base, 0x3244, ReadGpuRegister(base, 0x3244) + 4);
|
||||
}
|
||||
}
|
||||
if (ReadGpuRegister(base, 0x3220) & 0x1000)
|
||||
{
|
||||
while (!(ReadGpuRegister(base, 0x3214) & 0x10) && !ReadGpuRegister(base, 0x2100))
|
||||
{
|
||||
if (ReadGpuRegister(base, 0x400100))
|
||||
{
|
||||
ServiceGrInterrupt();
|
||||
}
|
||||
if (ReadGpuRegister(base, 0x100) & 0x01000000)
|
||||
{
|
||||
VBlank();
|
||||
}
|
||||
}
|
||||
if (ReadGpuRegister(base, 0x3214) & 0x10)
|
||||
{
|
||||
while (ReadGpuRegister(base, 0x2500) & 0x10)
|
||||
{
|
||||
}
|
||||
WriteGpuRegister(base, 0x3220, ReadGpuRegister(base, 0x3220) & ~0x1000UL);
|
||||
}
|
||||
}
|
||||
if (!ReadGpuRegister(base, 0x2100))
|
||||
{
|
||||
WriteGpuRegister(base, 0x3250, 1);
|
||||
WriteGpuRegister(base, 0x2500, 1);
|
||||
}
|
||||
return ReadGpuRegister(base, 0x2100) | (ReadGpuRegister(base, 0x2080) & 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* January AV-info and display-mode selection, corroborated by RXDK-Libs
|
||||
* (2026 Team Resurgent), GPL-3.0-or-later. Preserve pinned reference notices.
|
||||
* The table data and ABI/field choices are from the original January target. */
|
||||
#include "display_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
DWORD WINAPI CMiniport::GetPresentFlagsFromAvInfo(
|
||||
DWORD avInfo)
|
||||
{
|
||||
DWORD flags = 0;
|
||||
if (avInfo & 0x10000) flags = 0x10;
|
||||
if (avInfo & 0x200000) flags |= 0x20;
|
||||
else if (avInfo & 0x1000000) flags |= 0xa0;
|
||||
else flags |= 0x40;
|
||||
if (avInfo & 0x2000000) flags |= 0x100;
|
||||
return flags;
|
||||
}
|
||||
DWORD WINAPI CMiniport::GetDisplayCapabilities(
|
||||
void)
|
||||
{
|
||||
if (!D3D__AvInfo)
|
||||
{
|
||||
AvSendTVEncoderOption(NULL, 6, 0, &D3D__AvInfo);
|
||||
}
|
||||
return D3D__AvInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma const_seg("D3D_RD")
|
||||
namespace D3D
|
||||
{
|
||||
const DWORD g_DisplayModeCount = sizeof(g_DisplayModes) / sizeof(g_DisplayModes[0]);
|
||||
const DISPLAYMODE g_DisplayModes[191] =
|
||||
{
|
||||
#include "display_modes.inc"
|
||||
};
|
||||
|
||||
const DISPLAYMODE *WINAPI GetTableForCurrentAvInfo(
|
||||
void)
|
||||
{
|
||||
DWORD avInfo = CMiniport::GetDisplayCapabilities();
|
||||
DWORD region = avInfo & AV_STANDARD_MASK;
|
||||
DWORD pack = avInfo & AV_PACK_MASK;
|
||||
const DISPLAYMODE *mode;
|
||||
DWORD i;
|
||||
DWORD count = g_DisplayModeCount;
|
||||
// The table is nonempty, so the first loop assigns mode on every path.
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
mode = &g_DisplayModes[i];
|
||||
if ((mode->AvInfo & AV_STANDARD_MASK) == region)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < count; ++i)
|
||||
{
|
||||
mode = &g_DisplayModes[i];
|
||||
DWORD modePack = mode->AvInfo & AV_PACK_MASK;
|
||||
if (!modePack || modePack == pack)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
void CMiniport::SetVideoMode(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
DWORD refresh,
|
||||
DWORD flags,
|
||||
D3DFORMAT format,
|
||||
DWORD presentationInterval,
|
||||
DWORD pitch)
|
||||
{
|
||||
format = MapToLinearD3DFORMAT(format);
|
||||
DWORD depth = VideoBitsPerPixelOfD3DFORMAT(format);
|
||||
const DISPLAYMODE *mode = GetTableForCurrentAvInfo();
|
||||
DWORD avInfo = GetDisplayCapabilities();
|
||||
DWORD modePack = mode->AvInfo & AV_PACK_MASK;
|
||||
DWORD pack = avInfo & AV_PACK_MASK;
|
||||
DWORD avRefresh = avInfo & AV_REFRESH_MASK;
|
||||
DWORD hdtvModes = 0;
|
||||
DWORD field = flags & (D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_PROGRESSIVE);
|
||||
if (flags & D3DPRESENTFLAG_FIELD)
|
||||
{
|
||||
field &= ~D3DPRESENTFLAG_INTERLACED;
|
||||
}
|
||||
if (pack == AV_PACK_HDTV)
|
||||
{
|
||||
hdtvModes = avInfo & AV_HDTV_MODE_MASK;
|
||||
}
|
||||
// Zero means no refresh override. Only enter the selection for a
|
||||
// caller-specified rate; 50 and 60 are the supported explicit rates.
|
||||
if (refresh)
|
||||
{
|
||||
switch (refresh)
|
||||
{
|
||||
case 50:
|
||||
avRefresh = AV_FLAGS_50Hz;
|
||||
break;
|
||||
case 60:
|
||||
avRefresh = AV_FLAGS_60Hz;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DWORD displayMode = 0;
|
||||
if (pack != AV_PACK_NONE)
|
||||
{
|
||||
for (;; ++mode)
|
||||
{
|
||||
if ((mode->AvInfo & AV_PACK_MASK) != modePack)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (pack == AV_PACK_HDTV && !(mode->AvInfo & hdtvModes) &&
|
||||
(mode->AvInfo & AV_HDTV_MODE_MASK))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (mode->Width != width || mode->Height != height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(mode->AvInfo & AV_FLAGS_WIDESCREEN) != !(flags & D3DPRESENTFLAG_WIDESCREEN))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(mode->AvInfo & AV_FLAGS_FIELD) != !(flags & D3DPRESENTFLAG_FIELD))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(mode->AvInfo & AV_FLAGS_10x11PAR) != !(flags & D3DPRESENTFLAG_10X11PIXELASPECTRATIO))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(mode->AvInfo & avRefresh))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (field &&
|
||||
!((field & D3DPRESENTFLAG_INTERLACED) && (mode->AvInfo & AV_FLAGS_INTERLACED)) &&
|
||||
!((field & D3DPRESENTFLAG_PROGRESSIVE) && !(mode->AvInfo & AV_FLAGS_INTERLACED)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
displayMode = mode->DisplayMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_DisplayMode = displayMode;
|
||||
m_Format = format;
|
||||
m_PresentationInterval = presentationInterval;
|
||||
m_SurfacePitch = pitch;
|
||||
m_GammaUpdated[m_GammaCurrentIndex] = TRUE;
|
||||
m_CurrentAvInfo = mode->AvInfo;
|
||||
m_FirstFlip = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#pragma const_seg()
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef HALO_D3D8_NOTIFICATION_INTERNAL_H
|
||||
#define HALO_D3D8_NOTIFICATION_INTERNAL_H
|
||||
#include "hardware_internal.h"
|
||||
namespace D3D
|
||||
{
|
||||
/* Read the GPU-owned words in low/high order without aliasing a DWORD array
|
||||
* as an unrelated 64-bit object. This is not an atomic snapshot. */
|
||||
__inline unsigned __int64 ReadNotificationTime(
|
||||
volatile NvNotification *notification)
|
||||
{
|
||||
DWORD low = notification->timeStamp.nanoseconds[0];
|
||||
DWORD high = notification->timeStamp.nanoseconds[1];
|
||||
return low | ((unsigned __int64)high << 32);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,442 @@
|
||||
/* Pixel-container reconstruction against the January Halo binary.
|
||||
* Algorithms adapted from RXDK-Libs, 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Target-specific APIs and layouts differ from the reference.
|
||||
*/
|
||||
#include "device_layout.h"
|
||||
#include "pixeljar.h"
|
||||
#include "resource_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
/* Period math helper and target both use BSF. Keep an explicit C return. */
|
||||
DWORD __fastcall Log2(
|
||||
DWORD value)
|
||||
{
|
||||
DWORD result;
|
||||
__asm
|
||||
{
|
||||
mov ecx, value
|
||||
bsf eax, ecx
|
||||
mov result, eax
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
D3DFORMAT WINAPI MapToLinearD3DFORMAT(
|
||||
D3DFORMAT format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8: format = D3DFMT_LIN_A8R8G8B8; break;
|
||||
case D3DFMT_X8R8G8B8: format = D3DFMT_LIN_X8R8G8B8; break;
|
||||
case D3DFMT_R5G6B5: format = D3DFMT_LIN_R5G6B5; break;
|
||||
case D3DFMT_X1R5G5B5: format = D3DFMT_LIN_X1R5G5B5; break;
|
||||
case D3DFMT_A1R5G5B5: format = D3DFMT_LIN_A1R5G5B5; break;
|
||||
case D3DFMT_D16: format = D3DFMT_LIN_D16; break;
|
||||
case D3DFMT_D24S8: format = D3DFMT_LIN_D24S8; break;
|
||||
case D3DFMT_F16: format = D3DFMT_LIN_F16; break;
|
||||
case D3DFMT_F24S8: format = D3DFMT_LIN_F24S8; break;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
bool WINAPI IsCompressedD3DFORMAT(
|
||||
DWORD format)
|
||||
{
|
||||
bool compressed = false;
|
||||
switch (format)
|
||||
{
|
||||
case D3DFMT_DXT1:
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT4:
|
||||
compressed = true;
|
||||
break;
|
||||
}
|
||||
return compressed;
|
||||
}
|
||||
DWORD WINAPI CalcPitch(
|
||||
DWORD width,
|
||||
DWORD texelSize)
|
||||
{
|
||||
return (width * texelSize / 8 + D3DTEXTURE_PITCH_ALIGNMENT - 1) &
|
||||
~(D3DTEXTURE_PITCH_ALIGNMENT - 1);
|
||||
}
|
||||
DWORD WINAPI VideoBitsPerPixelOfD3DFORMAT(
|
||||
DWORD format)
|
||||
{
|
||||
DWORD bitsPerPixel;
|
||||
if (format == D3DFMT_X1R5G5B5 || format == D3DFMT_LIN_X1R5G5B5)
|
||||
{
|
||||
bitsPerPixel = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitsPerPixel = BitsPerPixelOfD3DFORMAT(format);
|
||||
}
|
||||
return bitsPerPixel;
|
||||
}
|
||||
DWORD WINAPI CalcTilePitch(
|
||||
DWORD width,
|
||||
D3DFORMAT format)
|
||||
{
|
||||
DWORD pitch = CalcPitch(width, BitsPerPixelOfD3DFORMAT(format));
|
||||
DWORD i;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (pitch <= g_TilePitches[i])
|
||||
{
|
||||
pitch = g_TilePitches[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pitch;
|
||||
}
|
||||
namespace PixelJar
|
||||
{
|
||||
void WINAPI GetDepthBufferScale(
|
||||
D3DPixelContainer *pixel,
|
||||
float *scale)
|
||||
{
|
||||
switch (GetFormat(pixel))
|
||||
{
|
||||
case D3DFMT_D16:
|
||||
case D3DFMT_LIN_D16:
|
||||
*scale = (float)D3DZ_MAX_D16;
|
||||
break;
|
||||
case D3DFMT_D24S8:
|
||||
case D3DFMT_LIN_D24S8:
|
||||
*scale = (float)D3DZ_MAX_D24S8;
|
||||
break;
|
||||
case D3DFMT_F16:
|
||||
case D3DFMT_LIN_F16:
|
||||
*scale = (float)D3DZ_MAX_F16;
|
||||
break;
|
||||
case D3DFMT_F24S8:
|
||||
case D3DFMT_LIN_F24S8:
|
||||
*scale = (float)D3DZ_MAX_F24S8;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI GetSize(
|
||||
D3DPixelContainer *pixel,
|
||||
DWORD level,
|
||||
DWORD *width,
|
||||
DWORD *height,
|
||||
DWORD *depth,
|
||||
DWORD *pitch,
|
||||
DWORD *slice)
|
||||
{
|
||||
DWORD size = pixel->Size;
|
||||
if (!size)
|
||||
{
|
||||
long logWidth = GetLogWidth(pixel) - level;
|
||||
long logHeight = GetLogHeight(pixel) - level;
|
||||
long logDepth = GetLogDepth(pixel) - level;
|
||||
DWORD bitsPerPixel = GetBitsPerPixel(pixel);
|
||||
*height = 1 << (logHeight > 0 ? logHeight : 0);
|
||||
*depth = 1 << (logDepth > 0 ? logDepth : 0);
|
||||
*width = 1 << (logWidth > 0 ? logWidth : 0);
|
||||
long logMin = (long)MinimumTextureSizeOfD3DFORMAT(GetFormat(pixel));
|
||||
DWORD physicalWidth = 1 << max(logMin, logWidth);
|
||||
DWORD physicalHeight = 1 << max(logMin, logHeight);
|
||||
switch (GetFormat(pixel))
|
||||
{
|
||||
case D3DFMT_DXT1:
|
||||
*pitch = physicalWidth * 2;
|
||||
break;
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT4:
|
||||
*pitch = physicalWidth * 4;
|
||||
break;
|
||||
default:
|
||||
*pitch = physicalWidth * bitsPerPixel / 8;
|
||||
break;
|
||||
}
|
||||
*slice = physicalWidth * physicalHeight * bitsPerPixel / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = (size & D3DSIZE_WIDTH_MASK) + 1;
|
||||
*height = ((size & D3DSIZE_HEIGHT_MASK) >> D3DSIZE_HEIGHT_SHIFT) + 1;
|
||||
*depth = 1;
|
||||
*pitch = PitchFromSize(size);
|
||||
*slice = *pitch * *height;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI Get2DSurfaceDesc(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DSURFACE_DESC *desc)
|
||||
{
|
||||
desc->Format = GetFormat(pixel);
|
||||
desc->Type = pixel->GetType();
|
||||
desc->Usage = 0;
|
||||
if (level == 0)
|
||||
{
|
||||
if (IsValidRenderTarget(pixel))
|
||||
{
|
||||
desc->Usage = D3DUSAGE_RENDERTARGET;
|
||||
}
|
||||
else if (IsValidDepthBuffer(pixel))
|
||||
{
|
||||
desc->Usage = D3DUSAGE_DEPTHSTENCIL;
|
||||
}
|
||||
}
|
||||
if (pixel->Data == g_pDevice->m_FrameBufferSurfaces[0].Data &&
|
||||
(D3D__RenderState[D3DRS_MULTISAMPLETYPE] & 0x3000))
|
||||
{
|
||||
desc->MultiSampleType = (D3DMULTISAMPLE_TYPE)D3D__RenderState[D3DRS_MULTISAMPLETYPE];
|
||||
}
|
||||
else
|
||||
{
|
||||
desc->MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
}
|
||||
DWORD width, height, depth, pitch, slice;
|
||||
GetSize(pixel, level, &width, &height, &depth, &pitch, &slice);
|
||||
desc->Width = width;
|
||||
desc->Height = height;
|
||||
desc->Size = slice;
|
||||
return;
|
||||
}
|
||||
void WINAPI Get3DSurfaceDesc(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DVOLUME_DESC *desc)
|
||||
{
|
||||
desc->Format = GetFormat(pixel);
|
||||
desc->Type = pixel->GetType();
|
||||
desc->Usage = 0;
|
||||
DWORD width, height, depth, pitch, slice;
|
||||
GetSize(pixel, level, &width, &height, &depth, &pitch, &slice);
|
||||
desc->Width = width;
|
||||
desc->Height = height;
|
||||
desc->Depth = depth;
|
||||
desc->Size = slice * depth;
|
||||
return;
|
||||
}
|
||||
void WINAPI FindSurfaceWithinTexture(
|
||||
D3DPixelContainer *pixel,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
BYTE **outData,
|
||||
DWORD *outRowPitch,
|
||||
DWORD *outSlicePitch,
|
||||
DWORD *outFormat,
|
||||
DWORD *outSize)
|
||||
{
|
||||
BYTE *data = GetDataFromResource(pixel);
|
||||
DWORD texelSize = GetBitsPerPixel(pixel);
|
||||
DWORD rowPitch, slicePitch;
|
||||
DWORD size = pixel->Size;
|
||||
if (!size)
|
||||
{
|
||||
DWORD logWidth = GetLogWidth(pixel);
|
||||
DWORD logHeight = GetLogHeight(pixel);
|
||||
DWORD logDepth = GetLogDepth(pixel);
|
||||
DWORD logMin = MinimumTextureSizeOfD3DFORMAT(GetFormat(pixel));
|
||||
if (face != D3DCUBEMAP_FACE_POSITIVE_X)
|
||||
{
|
||||
DWORD levels = GetMipmapLevelCount(pixel);
|
||||
DWORD faceWidth = logWidth;
|
||||
DWORD faceHeight = logHeight;
|
||||
DWORD faceDepth = logDepth;
|
||||
DWORD faceSize = 0;
|
||||
for (; levels; levels--)
|
||||
{
|
||||
faceSize += (1 << (max(faceWidth, logMin) + max(faceHeight, logMin))) * texelSize / 8;
|
||||
if (faceWidth > 0) faceWidth--;
|
||||
if (faceHeight > 0) faceHeight--;
|
||||
if (faceDepth > 0) faceDepth--;
|
||||
}
|
||||
faceSize = (faceSize + D3DTEXTURE_CUBEFACE_ALIGNMENT - 1) &
|
||||
~(D3DTEXTURE_CUBEFACE_ALIGNMENT - 1);
|
||||
data += faceSize * face;
|
||||
}
|
||||
if (level)
|
||||
{
|
||||
DWORD levels = level;
|
||||
DWORD logSize;
|
||||
for (; levels; levels--)
|
||||
{
|
||||
logSize = max(logWidth, logMin) + max(logHeight, logMin) + logDepth;
|
||||
data += (1 << logSize) * texelSize / 8;
|
||||
if (logWidth > 0) logWidth--;
|
||||
if (logHeight > 0) logHeight--;
|
||||
if (logDepth > 0) logDepth--;
|
||||
}
|
||||
}
|
||||
DWORD format = pixel->Format & ~(D3DFORMAT_USIZE_MASK | D3DFORMAT_VSIZE_MASK | D3DFORMAT_PSIZE_MASK);
|
||||
format |= logWidth << D3DFORMAT_USIZE_SHIFT;
|
||||
format |= logHeight << D3DFORMAT_VSIZE_SHIFT;
|
||||
format |= logDepth << D3DFORMAT_PSIZE_SHIFT;
|
||||
logWidth = max(logWidth, logMin);
|
||||
logHeight = max(logHeight, logMin);
|
||||
switch (GetFormat(pixel))
|
||||
{
|
||||
case D3DFMT_DXT1: rowPitch = (1 << logWidth) * 2; break;
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT4: rowPitch = (1 << logWidth) * 4; break;
|
||||
default: rowPitch = (1 << logWidth) * texelSize / 8; break;
|
||||
}
|
||||
slicePitch = (1 << (logWidth + logHeight)) * texelSize / 8;
|
||||
*outFormat = format;
|
||||
*outSize = pixel->Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD textureHeight = ((size & D3DSIZE_HEIGHT_MASK) >> D3DSIZE_HEIGHT_SHIFT) + 1;
|
||||
rowPitch = PitchFromSize(size);
|
||||
slicePitch = rowPitch * textureHeight;
|
||||
*outFormat = pixel->Format;
|
||||
*outSize = pixel->Size;
|
||||
}
|
||||
*outData = data;
|
||||
*outRowPitch = rowPitch;
|
||||
*outSlicePitch = slicePitch;
|
||||
return;
|
||||
}
|
||||
static void WINAPI LockSurface(
|
||||
D3DPixelContainer *pixel,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
DWORD flags,
|
||||
BYTE **data,
|
||||
DWORD *rowPitch,
|
||||
DWORD *slicePitch)
|
||||
{
|
||||
if (!(flags & D3DLOCK_NOOVERWRITE))
|
||||
{
|
||||
BlockOnResource(pixel);
|
||||
}
|
||||
DWORD format, size;
|
||||
FindSurfaceWithinTexture(pixel, face, level, data, rowPitch, slicePitch, &format, &size);
|
||||
if (flags & D3DLOCK_TILED)
|
||||
{
|
||||
/* Target Xbox tiled framebuffer mapping. This is an address-space
|
||||
* conversion, not an aliasing/lifetime trick. */
|
||||
*data = (BYTE *)(((DWORD)*data & ~0xf0000000UL) | 0xf0000000UL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI Lock2DSurface(
|
||||
D3DPixelContainer *pixel,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
D3DLOCKED_RECT *locked,
|
||||
const RECT *rect,
|
||||
DWORD flags)
|
||||
{
|
||||
DWORD rowPitch, slicePitch;
|
||||
BYTE *data;
|
||||
LockSurface(pixel, face, level, flags, &data, &rowPitch, &slicePitch);
|
||||
if (rect)
|
||||
{
|
||||
DWORD texelSize = GetBitsPerPixel(pixel);
|
||||
data += rect->top * rowPitch + rect->left * texelSize / 8;
|
||||
}
|
||||
locked->Pitch = rowPitch;
|
||||
locked->pBits = data;
|
||||
return;
|
||||
}
|
||||
void WINAPI Lock3DSurface(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DLOCKED_BOX *locked,
|
||||
const D3DBOX *box,
|
||||
DWORD flags)
|
||||
{
|
||||
DWORD rowPitch, slicePitch;
|
||||
BYTE *data;
|
||||
LockSurface(pixel, D3DCUBEMAP_FACE_POSITIVE_X, level, flags, &data, &rowPitch, &slicePitch);
|
||||
if (box)
|
||||
{
|
||||
DWORD texelSize = GetBitsPerPixel(pixel);
|
||||
data += box->Front * slicePitch + box->Top * rowPitch + box->Left * texelSize / 8;
|
||||
}
|
||||
locked->RowPitch = rowPitch;
|
||||
locked->SlicePitch = slicePitch;
|
||||
locked->pBits = data;
|
||||
return;
|
||||
}
|
||||
DWORD WINAPI EncodeFormat(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
DWORD depth,
|
||||
DWORD levels,
|
||||
D3DFORMAT d3dFormat,
|
||||
DWORD pitch,
|
||||
bool videoMemory,
|
||||
bool cubeMap,
|
||||
bool volume,
|
||||
DWORD *outFormat,
|
||||
DWORD *outSize)
|
||||
{
|
||||
DWORD size = 0;
|
||||
DWORD texelSize = BitsPerPixelOfD3DFORMAT(d3dFormat);
|
||||
DWORD logWidth, logHeight, logDepth, sizeWidth, sizeHeight;
|
||||
if ((g_TextureFormat[d3dFormat] & 1) || IsCompressedD3DFORMAT(d3dFormat))
|
||||
{
|
||||
logWidth = Log2(width);
|
||||
logHeight = Log2(height);
|
||||
logDepth = Log2(depth);
|
||||
sizeWidth = 0;
|
||||
sizeHeight = 0;
|
||||
DWORD logMin = MinimumTextureSizeOfD3DFORMAT(d3dFormat);
|
||||
if (levels == 0)
|
||||
{
|
||||
levels = max(logWidth, max(logHeight, logDepth)) + 1;
|
||||
}
|
||||
DWORD currentLevel;
|
||||
DWORD currentWidth = logWidth;
|
||||
DWORD currentHeight = logHeight;
|
||||
DWORD currentDepth = logDepth;
|
||||
DWORD logSize;
|
||||
for (currentLevel = levels; currentLevel; currentLevel--)
|
||||
{
|
||||
logSize = max(currentWidth, logMin) + max(currentHeight, logMin) + currentDepth;
|
||||
size += (1 << logSize) * texelSize / 8;
|
||||
if (currentWidth > 0) currentWidth--;
|
||||
if (currentHeight > 0) currentHeight--;
|
||||
if (currentDepth > 0) currentDepth--;
|
||||
}
|
||||
if (cubeMap)
|
||||
{
|
||||
size = (size + D3DTEXTURE_CUBEFACE_ALIGNMENT - 1) & ~(D3DTEXTURE_CUBEFACE_ALIGNMENT - 1);
|
||||
size *= 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logWidth = logHeight = logDepth = 0;
|
||||
if (levels == 0) levels = 1;
|
||||
if (pitch == 0) pitch = CalcPitch(width, texelSize);
|
||||
sizeWidth = width;
|
||||
sizeHeight = height;
|
||||
size = pitch * height;
|
||||
}
|
||||
*outFormat = (cubeMap ? D3DFORMAT_CUBEMAP : 0)
|
||||
| (volume ? 3 : 2) << D3DFORMAT_DIMENSION_SHIFT
|
||||
| d3dFormat << D3DFORMAT_FORMAT_SHIFT
|
||||
| levels << D3DFORMAT_MIPMAP_SHIFT
|
||||
| logWidth << D3DFORMAT_USIZE_SHIFT
|
||||
| logHeight << D3DFORMAT_VSIZE_SHIFT
|
||||
| logDepth << D3DFORMAT_PSIZE_SHIFT
|
||||
| (videoMemory ? D3DFORMAT_DMACHANNEL_B : D3DFORMAT_DMACHANNEL_A)
|
||||
| D3DFORMAT_BORDERSOURCE_COLOR;
|
||||
if (sizeWidth)
|
||||
{
|
||||
*outSize = (sizeWidth - 1)
|
||||
| (sizeHeight - 1) << D3DSIZE_HEIGHT_SHIFT
|
||||
| ((pitch / D3DTEXTURE_PITCH_ALIGNMENT) - 1) << D3DSIZE_PITCH_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outSize = 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/* Pixel helpers adapted from RXDK-Libs, 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* See libs/d3d8/PROVENANCE.md.
|
||||
*/
|
||||
#ifndef D3D8_PIXELJAR_H
|
||||
#define D3D8_PIXELJAR_H
|
||||
#include <xtl.h>
|
||||
namespace D3D
|
||||
{
|
||||
DWORD __fastcall Log2(
|
||||
DWORD value);
|
||||
extern const BYTE g_TextureFormat[];
|
||||
extern const DWORD g_TilePitches[16];
|
||||
D3DFORMAT WINAPI MapToLinearD3DFORMAT(
|
||||
D3DFORMAT format);
|
||||
bool WINAPI IsCompressedD3DFORMAT(
|
||||
DWORD format);
|
||||
DWORD WINAPI CalcPitch(
|
||||
DWORD width,
|
||||
DWORD texelSize);
|
||||
DWORD WINAPI VideoBitsPerPixelOfD3DFORMAT(
|
||||
DWORD format);
|
||||
DWORD WINAPI CalcTilePitch(
|
||||
DWORD width,
|
||||
D3DFORMAT format);
|
||||
__inline DWORD WINAPI BitsPerPixelOfD3DFORMAT(
|
||||
DWORD format)
|
||||
{
|
||||
return g_TextureFormat[format] & 0x3c;
|
||||
}
|
||||
__inline DWORD WINAPI MinimumTextureSizeOfD3DFORMAT(
|
||||
DWORD format)
|
||||
{
|
||||
return IsCompressedD3DFORMAT(format) ? 2 : 0;
|
||||
}
|
||||
namespace PixelJar
|
||||
{
|
||||
__inline BOOL WINAPI IsSwizzled(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return g_TextureFormat[(pixel->Format & D3DFORMAT_FORMAT_MASK) >> D3DFORMAT_FORMAT_SHIFT] & 1;
|
||||
}
|
||||
__inline bool WINAPI IsCompressed(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return IsCompressedD3DFORMAT((pixel->Format & D3DFORMAT_FORMAT_MASK) >> D3DFORMAT_FORMAT_SHIFT);
|
||||
}
|
||||
__inline bool WINAPI IsSurface(
|
||||
D3DResource *resource)
|
||||
{
|
||||
return (resource->Common & D3DCOMMON_TYPE_MASK) == D3DCOMMON_TYPE_SURFACE;
|
||||
}
|
||||
__inline D3DBaseTexture *WINAPI GetParent(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if (IsSurface(resource))
|
||||
{
|
||||
return ((D3DSurface *)resource)->Parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
__inline D3DFORMAT WINAPI GetFormat(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return (D3DFORMAT)((pixel->Format & D3DFORMAT_FORMAT_MASK) >> D3DFORMAT_FORMAT_SHIFT);
|
||||
}
|
||||
__inline DWORD WINAPI GetLogWidth(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return (pixel->Format & D3DFORMAT_USIZE_MASK) >> D3DFORMAT_USIZE_SHIFT;
|
||||
}
|
||||
__inline DWORD WINAPI GetLogHeight(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return (pixel->Format & D3DFORMAT_VSIZE_MASK) >> D3DFORMAT_VSIZE_SHIFT;
|
||||
}
|
||||
__inline DWORD WINAPI GetLogDepth(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return (pixel->Format & D3DFORMAT_PSIZE_MASK) >> D3DFORMAT_PSIZE_SHIFT;
|
||||
}
|
||||
__inline DWORD WINAPI GetBitsPerPixel(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return BitsPerPixelOfD3DFORMAT(GetFormat(pixel));
|
||||
}
|
||||
__inline BOOL WINAPI IsValidRenderTarget(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return g_TextureFormat[GetFormat(pixel)] & 0x80;
|
||||
}
|
||||
__inline BOOL WINAPI IsValidDepthBuffer(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return g_TextureFormat[GetFormat(pixel)] & 0x40;
|
||||
}
|
||||
__inline DWORD WINAPI GetMipmapLevelCount(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
return (pixel->Format & D3DFORMAT_MIPMAP_MASK) >> D3DFORMAT_MIPMAP_SHIFT;
|
||||
}
|
||||
__inline DWORD WINAPI PitchFromSize(
|
||||
DWORD size)
|
||||
{
|
||||
return (((size & D3DSIZE_PITCH_MASK) >> D3DSIZE_PITCH_SHIFT) + 1) * D3DTEXTURE_PITCH_ALIGNMENT;
|
||||
}
|
||||
/* Original header ABI is stdcall (PDB/decorated target definitions).
|
||||
* These are genuine layout accessors used by viewport and copy operations. */
|
||||
__inline DWORD WINAPI GetWidth(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
DWORD size = pixel->Size;
|
||||
if (!size) { return 1UL << GetLogWidth(pixel); }
|
||||
return (size & D3DSIZE_WIDTH_MASK) + 1;
|
||||
}
|
||||
__inline DWORD WINAPI GetHeight(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
DWORD size = pixel->Size;
|
||||
if (!size) { return 1UL << GetLogHeight(pixel); }
|
||||
return ((size & D3DSIZE_HEIGHT_MASK) >> D3DSIZE_HEIGHT_SHIFT) + 1;
|
||||
}
|
||||
__inline DWORD WINAPI GetDepth(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
if (!pixel->Size) { return 1UL << GetLogDepth(pixel); }
|
||||
return 1;
|
||||
}
|
||||
__inline DWORD WINAPI GetPitch(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
DWORD size = pixel->Size;
|
||||
if (!size)
|
||||
{
|
||||
DWORD width = GetWidth(pixel);
|
||||
D3DFORMAT format = GetFormat(pixel);
|
||||
switch (format)
|
||||
{
|
||||
case D3DFMT_DXT1: return width * 2;
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT4: return width * 4;
|
||||
default: return width * BitsPerPixelOfD3DFORMAT(format) / 8;
|
||||
}
|
||||
}
|
||||
return PitchFromSize(
|
||||
size);
|
||||
}
|
||||
__inline DWORD WINAPI GetSlice(
|
||||
D3DPixelContainer *pixel)
|
||||
{
|
||||
DWORD bits = GetBitsPerPixel(pixel);
|
||||
DWORD size = pixel->Size;
|
||||
DWORD logMin = MinimumTextureSizeOfD3DFORMAT(GetFormat(pixel));
|
||||
if (!size)
|
||||
{
|
||||
DWORD logWidth = max(logMin, GetLogWidth(pixel));
|
||||
DWORD logHeight = max(logMin, GetLogHeight(pixel));
|
||||
return (1UL << (logWidth + logHeight)) * bits / 8;
|
||||
}
|
||||
return (((size & D3DSIZE_HEIGHT_MASK) >> D3DSIZE_HEIGHT_SHIFT) + 1) * PitchFromSize(
|
||||
size);
|
||||
}
|
||||
DWORD WINAPI EncodeFormat(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
DWORD depth,
|
||||
DWORD levels,
|
||||
D3DFORMAT d3dFormat,
|
||||
DWORD pitch,
|
||||
bool videoMemory,
|
||||
bool cubeMap,
|
||||
bool volume,
|
||||
DWORD *outFormat,
|
||||
DWORD *outSize);
|
||||
void WINAPI GetSize(
|
||||
D3DPixelContainer *pixel,
|
||||
DWORD level,
|
||||
DWORD *width,
|
||||
DWORD *height,
|
||||
DWORD *depth,
|
||||
DWORD *pitch,
|
||||
DWORD *slice);
|
||||
DWORD WINAPI GetSurfaceFormat(
|
||||
D3DPixelContainer *renderTarget,
|
||||
D3DPixelContainer *zBuffer);
|
||||
void WINAPI GetDepthBufferScale(
|
||||
D3DPixelContainer *pixel,
|
||||
float *scale);
|
||||
void WINAPI Get2DSurfaceDesc(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DSURFACE_DESC *desc);
|
||||
void WINAPI Get3DSurfaceDesc(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DVOLUME_DESC *desc);
|
||||
void WINAPI Lock2DSurface(
|
||||
D3DPixelContainer *pixel,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
D3DLOCKED_RECT *locked,
|
||||
const RECT *rect,
|
||||
DWORD flags);
|
||||
void WINAPI Lock3DSurface(
|
||||
D3DPixelContainer *pixel,
|
||||
UINT level,
|
||||
D3DLOCKED_BOX *locked,
|
||||
const D3DBOX *box,
|
||||
DWORD flags);
|
||||
void WINAPI FindSurfaceWithinTexture(
|
||||
D3DPixelContainer *pixel,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
BYTE **data,
|
||||
DWORD *rowPitch,
|
||||
DWORD *slicePitch,
|
||||
DWORD *format,
|
||||
DWORD *size);
|
||||
}
|
||||
HRESULT WINAPI CreateTexture(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
DWORD depth,
|
||||
DWORD levels,
|
||||
DWORD usage,
|
||||
D3DFORMAT format,
|
||||
bool cubeMap,
|
||||
bool volume,
|
||||
D3DBaseTexture **texture);
|
||||
HRESULT WINAPI CreateStandAloneSurface(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
D3DFORMAT format,
|
||||
bool renderTarget,
|
||||
D3DSurface **surface);
|
||||
HRESULT WINAPI CreateSurfaceOfTexture(
|
||||
DWORD format,
|
||||
DWORD size,
|
||||
D3DBaseTexture *texture,
|
||||
void *data,
|
||||
D3DSurface **surface);
|
||||
HRESULT WINAPI CreateVolumeOfTexture(
|
||||
DWORD format,
|
||||
D3DBaseTexture *texture,
|
||||
void *data,
|
||||
D3DVolume **volume);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,381 @@
|
||||
/* January anti-alias presentation reconstruction. Related state-management
|
||||
* reference: Team-Resurgent/RXDK-Libs, GPL-3.0-or-later, pinned in provenance.
|
||||
* The older AntiAliased* ABI and behavior here come from the supplied target.
|
||||
* Copyright (C) 2026 Team Resurgent; SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
#define D3DCOMPILE_NOTINLINE 1
|
||||
#include "present_internal.h"
|
||||
#include "draw_internal.h"
|
||||
#include "push_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#include "vshader_internal.h"
|
||||
#include "state_internal.h"
|
||||
#include "pusher_state.h"
|
||||
#include "display_internal.h"
|
||||
#include "kernel_memory.h"
|
||||
#pragma code_seg("D3D")
|
||||
#pragma const_seg("D3D_RD")
|
||||
namespace D3D
|
||||
{
|
||||
DWORD g_FlipAddress;
|
||||
static const float KELVIN_BORDER = 0.53125f;
|
||||
|
||||
const DWORD g_AntiAliasedRenderStates[] =
|
||||
{
|
||||
D3DRS_FILLMODE, D3DFILL_SOLID,
|
||||
D3DRS_BACKFILLMODE, D3DFILL_SOLID,
|
||||
D3DRS_CULLMODE, D3DCULL_NONE,
|
||||
D3DRS_DITHERENABLE, TRUE,
|
||||
D3DRS_ALPHATESTENABLE, FALSE,
|
||||
D3DRS_ALPHABLENDENABLE, FALSE,
|
||||
D3DRS_FOGENABLE, FALSE,
|
||||
D3DRS_EDGEANTIALIAS, FALSE,
|
||||
D3DRS_STENCILENABLE, FALSE,
|
||||
D3DRS_LIGHTING, FALSE,
|
||||
D3DRS_MULTISAMPLEMASK, 0xffffffffUL,
|
||||
D3DRS_LOGICOP, D3DLOGICOP_NONE,
|
||||
D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALL,
|
||||
D3DRS_YUVENABLE, FALSE,
|
||||
D3DRS_SPECULARENABLE, FALSE,
|
||||
D3DRS_ZBIAS, 0,
|
||||
};
|
||||
const DWORD g_AntiAliasedTextureStates[] =
|
||||
{
|
||||
D3DTSS_COLOROP, D3DTOP_SELECTARG1,
|
||||
D3DTSS_COLORARG1, D3DTA_TEXTURE,
|
||||
D3DTSS_ALPHAOP, D3DTOP_DISABLE,
|
||||
D3DTSS_TEXCOORDINDEX, 0,
|
||||
D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP,
|
||||
D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP,
|
||||
D3DTSS_COLORKEYOP, D3DTCOLORKEYOP_DISABLE,
|
||||
D3DTSS_COLORSIGN, 0,
|
||||
D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE,
|
||||
D3DTSS_MINFILTER, D3DTEXF_LINEAR,
|
||||
D3DTSS_MAGFILTER, D3DTEXF_LINEAR,
|
||||
};
|
||||
|
||||
void WINAPI AntiAliasedSetState(
|
||||
AntiAliasedSavedState *saved,
|
||||
D3DSurface *destination,
|
||||
D3DSurface *source,
|
||||
DWORD filter)
|
||||
{
|
||||
DWORD i;
|
||||
CDevice *device = g_pDevice;
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
device->SetRenderState((D3DRENDERSTATETYPE)g_AntiAliasedRenderStates[2 * i],
|
||||
g_AntiAliasedRenderStates[2 * i + 1]);
|
||||
}
|
||||
for (i = 0; i < 11; ++i)
|
||||
{
|
||||
device->SetTextureStageState(0, (D3DTEXTURESTAGESTATETYPE)g_AntiAliasedTextureStates[2 * i],
|
||||
g_AntiAliasedTextureStates[2 * i + 1]);
|
||||
}
|
||||
device->SetPixelShader(0);
|
||||
device->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
||||
device->SetRenderTarget(destination, NULL);
|
||||
device->SetTextureStageState(0, D3DTSS_MINFILTER, filter);
|
||||
device->SetTextureStageState(0, D3DTSS_MAGFILTER, filter);
|
||||
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
/* Copy the common pixel-container representation, not a fictional derived
|
||||
* texture object at the surface address. The temporary stays live through
|
||||
* restoration; only the resource type bits are replaced. */
|
||||
memcpy(&saved->SrcTexture, source, sizeof(saved->SrcTexture));
|
||||
saved->SrcTexture.Common = (saved->SrcTexture.Common & ~D3DCOMMON_TYPE_MASK)
|
||||
| D3DCOMMON_TYPE_TEXTURE;
|
||||
device->SetTexture(0, &saved->SrcTexture);
|
||||
SetState();
|
||||
return;
|
||||
}
|
||||
void WINAPI AntiAliasedSaveState(
|
||||
AntiAliasedSavedState *saved)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD i;
|
||||
saved->pRenderTarget = device->m_pRenderTarget;
|
||||
saved->pRenderTarget->AddRef();
|
||||
saved->pZBuffer = device->m_pZBuffer;
|
||||
if (saved->pZBuffer) saved->pZBuffer->AddRef();
|
||||
saved->pTexture = device->m_Textures[0];
|
||||
if (saved->pTexture) saved->pTexture->AddRef();
|
||||
saved->pPixelShader = device->m_pPixelShader;
|
||||
saved->VertexShaderHandle = device->m_VertexShaderHandle;
|
||||
saved->Viewport = device->m_Viewport;
|
||||
saved->Stage1ColorOp = D3D__TextureState[1][D3DTSS_COLOROP];
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
saved->RenderState[i] = D3D__RenderState[g_AntiAliasedRenderStates[2 * i]];
|
||||
}
|
||||
for (i = 0; i < 11; ++i)
|
||||
{
|
||||
saved->TextureState[i] = D3D__TextureState[0][g_AntiAliasedTextureStates[2 * i]];
|
||||
}
|
||||
if (saved->pPixelShader)
|
||||
{
|
||||
for (i = D3DRS_PS_MIN; i < D3DRS_PS_MAX; ++i)
|
||||
saved->PixelShaderState[i - D3DRS_PS_MIN] = D3D__RenderState[i];
|
||||
saved->PSTextureModes = D3D__RenderState[D3DRS_PSTEXTUREMODES];
|
||||
}
|
||||
memcpy(saved->VertexShaders, device->m_VertexShaderProgramSlots, sizeof(saved->VertexShaders));
|
||||
return;
|
||||
}
|
||||
void WINAPI AntiAliasedRestoreState(
|
||||
AntiAliasedSavedState *saved)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD i;
|
||||
device->SetRenderTarget(saved->pRenderTarget, saved->pZBuffer);
|
||||
saved->pRenderTarget->Release();
|
||||
if (saved->pZBuffer) saved->pZBuffer->Release();
|
||||
device->SetTexture(0, saved->pTexture);
|
||||
if (saved->pTexture) saved->pTexture->Release();
|
||||
device->SetPixelShader((DWORD)saved->pPixelShader);
|
||||
device->SetVertexShader(saved->VertexShaderHandle);
|
||||
device->SetViewport(&saved->Viewport);
|
||||
BOOL shadowed = !(device->m_StateFlags & 0x10);
|
||||
device->SetTextureStageState(1, D3DTSS_COLOROP, saved->Stage1ColorOp);
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
if (shadowed || g_AntiAliasedRenderStates[2 * i] >= D3DRS_SIMPLE_MAX)
|
||||
device->SetRenderState((D3DRENDERSTATETYPE)g_AntiAliasedRenderStates[2 * i], saved->RenderState[i]);
|
||||
}
|
||||
for (i = 0; i < 11; ++i)
|
||||
device->SetTextureStageState(0, (D3DTEXTURESTAGESTATETYPE)g_AntiAliasedTextureStates[2 * i], saved->TextureState[i]);
|
||||
if (shadowed)
|
||||
{
|
||||
if (saved->pPixelShader)
|
||||
{
|
||||
for (i = D3DRS_PS_MIN; i < D3DRS_PS_MAX; ++i)
|
||||
device->SetRenderState((D3DRENDERSTATETYPE)i, saved->PixelShaderState[i - D3DRS_PS_MIN]);
|
||||
device->SetRenderState(D3DRS_PSTEXTUREMODES, saved->PSTextureModes);
|
||||
}
|
||||
RestoreVertexShaders(saved->VertexShaders, sizeof(saved->VertexShaders) / sizeof(DWORD));
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI AliasedFlip(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD i = device->m_FrameBufferCount - 1;
|
||||
DWORD data = device->m_FrameBufferSurfaces[i].Data;
|
||||
DWORD lock = device->m_FrameBufferSurfaces[i].Lock;
|
||||
for (; i != 0; --i)
|
||||
{
|
||||
device->m_FrameBufferSurfaces[i].Data = device->m_FrameBufferSurfaces[i - 1].Data;
|
||||
device->m_FrameBufferSurfaces[i].Lock = device->m_FrameBufferSurfaces[i - 1].Lock;
|
||||
}
|
||||
device->m_FrameBufferSurfaces[0].Data = data;
|
||||
device->m_FrameBufferSurfaces[0].Lock = lock;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x12c, 0);
|
||||
Push1(push + 2, NV097_NO_OPERATION, 0);
|
||||
DWORD flipAddress = device->m_FrameBufferSurfaces[1].Data;
|
||||
g_FlipAddress = flipAddress;
|
||||
Push1(push + 4, NV097_WAIT_FOR_IDLE, 0);
|
||||
Push1(push + 6, 0x1d8c, flipAddress);
|
||||
if (device->m_PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE)
|
||||
Push1(push + 8, NV097_NO_OPERATION, 0x300);
|
||||
else
|
||||
Push1(push + 8, NV097_NO_OPERATION, 0x304);
|
||||
push += 10;
|
||||
if (device->m_pRenderTarget == &device->m_FrameBufferSurfaces[0])
|
||||
{
|
||||
Push1(push, 0x130, 0);
|
||||
Push1(push + 2, 0x210, device->m_FrameBufferSurfaces[0].Data);
|
||||
push += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
device->m_StateFlags |= 0x100;
|
||||
}
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
DWORD *WINAPI AntiAliasedFilterBlt(
|
||||
DWORD *push,
|
||||
DWORD xScale,
|
||||
DWORD yScale,
|
||||
const RECT *rectangle)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD left = 0;
|
||||
DWORD top = 0;
|
||||
DWORD right = PixelJar::GetWidth(device->m_pRenderTarget);
|
||||
DWORD bottom = PixelJar::GetHeight(device->m_pRenderTarget);
|
||||
if (rectangle)
|
||||
{
|
||||
left = max((LONG)left, rectangle->left);
|
||||
right = min((LONG)right, rectangle->right);
|
||||
top = max((LONG)top, rectangle->top);
|
||||
bottom = min((LONG)bottom, rectangle->bottom);
|
||||
}
|
||||
if (left < right && top < bottom)
|
||||
{
|
||||
PushCount(push++, 0x1760, 16);
|
||||
for (DWORD i = 0; i < 16; ++i) *push++ = SIZEANDTYPE_DISABLED;
|
||||
Push1(push, 0x1760, 0x22);
|
||||
Push1(push + 2, 0x1784, 0x22);
|
||||
Push1(push + 4, 0x17fc, 5);
|
||||
PushCount(push + 6, 0x40001818, 12);
|
||||
DWORD filter = D3D__TextureState[0][D3DTSS_MINFILTER];
|
||||
float uAdjust = 0.0f;
|
||||
float vAdjust = 0.0f;
|
||||
if (filter == D3DTEXF_QUINCUNX || filter == D3DTEXF_GAUSSIANCUBIC)
|
||||
{
|
||||
if (xScale == 2) uAdjust = 0.5f;
|
||||
if (yScale == 2) vAdjust = 0.5f;
|
||||
}
|
||||
/* The command payload is a 12-float triangle. memcpy writes float
|
||||
* representations without dereferencing an incompatible DWORD lvalue.
|
||||
* Bounds: caller reserves at least 38 words for a nonempty rectangle. */
|
||||
float value = (float)left - KELVIN_BORDER;
|
||||
memcpy(push + 7, &value, sizeof(value));
|
||||
value = (float)top - KELVIN_BORDER;
|
||||
memcpy(push + 8, &value, sizeof(value));
|
||||
value = (float)(left * xScale) + uAdjust;
|
||||
memcpy(push + 9, &value, sizeof(value));
|
||||
value = (float)(top * yScale) + vAdjust;
|
||||
memcpy(push + 10, &value, sizeof(value));
|
||||
value = (float)right * 4.0f - KELVIN_BORDER;
|
||||
memcpy(push + 11, &value, sizeof(value));
|
||||
value = (float)top * 4.0f - KELVIN_BORDER;
|
||||
memcpy(push + 12, &value, sizeof(value));
|
||||
value = (float)(right * xScale) * 4.0f + uAdjust;
|
||||
memcpy(push + 13, &value, sizeof(value));
|
||||
value = (float)(top * yScale) * 4.0f + vAdjust;
|
||||
memcpy(push + 14, &value, sizeof(value));
|
||||
value = (float)left * 4.0f - KELVIN_BORDER;
|
||||
memcpy(push + 15, &value, sizeof(value));
|
||||
value = (float)bottom * 4.0f - KELVIN_BORDER;
|
||||
memcpy(push + 16, &value, sizeof(value));
|
||||
value = (float)(left * xScale) * 4.0f + uAdjust;
|
||||
memcpy(push + 17, &value, sizeof(value));
|
||||
value = (float)(bottom * yScale) * 4.0f + vAdjust;
|
||||
memcpy(push + 18, &value, sizeof(value));
|
||||
Push1(push + 19, 0x17fc, 0);
|
||||
push += 21;
|
||||
device->m_DirtyFlags |= 0x7ff;
|
||||
}
|
||||
return push;
|
||||
}
|
||||
void WINAPI AntiAliasedCopy(
|
||||
const RECT *rectangle)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (device->m_FrameBufferCount > 2 &&
|
||||
device->m_PresentationInterval != D3DPRESENT_INTERVAL_IMMEDIATE)
|
||||
{
|
||||
DWORD data = device->m_FrameBufferSurfaces[2].Data;
|
||||
DWORD lock = device->m_FrameBufferSurfaces[2].Lock;
|
||||
device->m_FrameBufferSurfaces[2].Data = device->m_FrameBufferSurfaces[1].Data;
|
||||
device->m_FrameBufferSurfaces[2].Lock = device->m_FrameBufferSurfaces[1].Lock;
|
||||
device->m_FrameBufferSurfaces[1].Data = data;
|
||||
device->m_FrameBufferSurfaces[1].Lock = lock;
|
||||
}
|
||||
AntiAliasedSavedState savedState;
|
||||
AntiAliasedSaveState(&savedState);
|
||||
DWORD sample = D3D__RenderState[D3DRS_MULTISAMPLETYPE];
|
||||
DWORD xScale = (sample >> 4) & 15;
|
||||
DWORD yScale = sample & 15;
|
||||
D3DSurface *destination = &device->m_FrameBufferSurfaces[1];
|
||||
D3DSurface *source = &device->m_FrameBufferSurfaces[0];
|
||||
DWORD filter = D3DTEXF_LINEAR;
|
||||
if (sample & 0x100) filter = D3DTEXF_QUINCUNX;
|
||||
else if (sample & 0x200) filter = D3DTEXF_GAUSSIANCUBIC;
|
||||
DWORD flipAddress = destination->Data;
|
||||
g_FlipAddress = flipAddress;
|
||||
AntiAliasedSetState(&savedState, destination, source, filter);
|
||||
DWORD *push = device->StartPush();
|
||||
if (device->m_PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE)
|
||||
{
|
||||
push = AntiAliasedFilterBlt(push, xScale, yScale, rectangle);
|
||||
if (device->m_PresentCount == 1)
|
||||
{
|
||||
Push1(push, NV097_WAIT_FOR_IDLE, 0);
|
||||
push += 2;
|
||||
}
|
||||
Push1(push, 0x1d8c, flipAddress);
|
||||
Push1(push + 2, NV097_NO_OPERATION, 0x300);
|
||||
push += 4;
|
||||
}
|
||||
else if (device->m_FrameBufferCount < 3)
|
||||
{
|
||||
Push1(push, 0x12c, 0);
|
||||
Push1(push + 2, NV097_NO_OPERATION, 0);
|
||||
Push1(push + 4, NV097_WAIT_FOR_IDLE, 0);
|
||||
Push1(push + 6, 0x1d8c, flipAddress);
|
||||
Push1(push + 8, NV097_NO_OPERATION, 0x304);
|
||||
Push1(push + 10, 0x130, 0);
|
||||
push = AntiAliasedFilterBlt(push + 12, xScale, yScale, rectangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Push1(push, 0x130, 0);
|
||||
push = AntiAliasedFilterBlt(push + 2, xScale, yScale, rectangle);
|
||||
Push1(push, NV097_WAIT_FOR_IDLE, 0);
|
||||
Push1(push + 2, 0x1d8c, flipAddress);
|
||||
Push1(push + 4, NV097_NO_OPERATION, 0x304);
|
||||
Push1(push + 6, 0x12c, 0);
|
||||
Push1(push + 8, NV097_NO_OPERATION, 0);
|
||||
push += 10;
|
||||
}
|
||||
device->EndPush(push);
|
||||
AntiAliasedRestoreState(&savedState);
|
||||
return;
|
||||
}
|
||||
extern "C" void WINAPI D3DDevice_Present(
|
||||
const RECT *sourceRect,
|
||||
const RECT *destRect,
|
||||
void *destWindowOverride,
|
||||
void *dirtyRegion)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
SetFence(2);
|
||||
while (device->m_PresentCount - device->m_Miniport.m_VBlankFlipCount >= 2)
|
||||
BusyLoop();
|
||||
++device->m_PresentCount;
|
||||
if (D3D__RenderState[D3DRS_MULTISAMPLETYPE] & 0x3000)
|
||||
AntiAliasedCopy(sourceRect);
|
||||
else
|
||||
AliasedFlip();
|
||||
device->KickOff();
|
||||
device->RecordSurfaceWritePush(&device->m_FrameBufferSurfaces[1]);
|
||||
if (device->m_Miniport.m_FirstFlip)
|
||||
{
|
||||
DWORD pitch = device->m_Miniport.m_SurfacePitch;
|
||||
DWORD mode = device->m_Miniport.m_DisplayMode;
|
||||
DWORD format = device->m_Miniport.m_Format;
|
||||
void *registerBase = device->m_Miniport.m_RegisterBase;
|
||||
KickOffAndWaitForIdle();
|
||||
if (device->m_Miniport.m_CurrentAvInfo & AV_FLAGS_FIELD) pitch >>= 1;
|
||||
DWORD step = 0;
|
||||
do
|
||||
{
|
||||
device->BlockUntilVerticalBlank();
|
||||
step = AvSetDisplayMode(registerBase, step, mode, format, pitch, g_FlipAddress);
|
||||
} while (step);
|
||||
if (device->m_Miniport.m_CurrentAvInfo & AV_FLAGS_FIELD)
|
||||
AvSendTVEncoderOption(device->m_Miniport.m_RegisterBase, 11, 0, NULL);
|
||||
DWORD field;
|
||||
AvSendTVEncoderOption(device->m_Miniport.m_RegisterBase, 15, 0, &field);
|
||||
if (!((device->m_Miniport.m_VBlankCount ^ field) & 1))
|
||||
++device->m_Miniport.m_VBlankCount;
|
||||
void *saved = AvGetSavedDataAddress();
|
||||
if (saved)
|
||||
{
|
||||
DWORD bytes = MmQueryAllocationSize(saved);
|
||||
MmPersistContiguousMemory(saved, bytes, FALSE);
|
||||
MmFreeContiguousMemory(saved);
|
||||
AvSetSavedDataAddress(NULL);
|
||||
}
|
||||
AvSendTVEncoderOption(registerBase, AV_OPTION_BLANK_SCREEN, 0, NULL);
|
||||
device->m_Miniport.m_FirstFlip = FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef D3D8_PRESENT_INTERNAL_H
|
||||
#define D3D8_PRESENT_INTERNAL_H
|
||||
/* January presentation owner. Layout and sizes are authenticated from the
|
||||
* supplied PDB, not copied from later SwapSavedState revisions. */
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
struct AntiAliasedSavedState
|
||||
{
|
||||
D3DSurface *pRenderTarget;
|
||||
D3DSurface *pZBuffer;
|
||||
D3DBaseTexture *pTexture;
|
||||
D3D::PixelShader *pPixelShader;
|
||||
unsigned long VertexShaderHandle;
|
||||
_D3DVIEWPORT8 Viewport;
|
||||
unsigned long Stage1ColorOp;
|
||||
unsigned long PSTextureModes;
|
||||
unsigned long RenderState[16];
|
||||
unsigned long TextureState[11];
|
||||
unsigned long PixelShaderState[57];
|
||||
unsigned long VertexShaders[48];
|
||||
D3DTexture SrcTexture;
|
||||
};
|
||||
typedef char AntiAliasedSavedState_size[sizeof(AntiAliasedSavedState) == 600 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_pRenderTarget_offset[offsetof(AntiAliasedSavedState, pRenderTarget) == 0 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_pZBuffer_offset[offsetof(AntiAliasedSavedState, pZBuffer) == 4 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_pTexture_offset[offsetof(AntiAliasedSavedState, pTexture) == 8 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_pPixelShader_offset[offsetof(AntiAliasedSavedState, pPixelShader) == 12 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_VertexShaderHandle_offset[offsetof(AntiAliasedSavedState, VertexShaderHandle) == 16 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_Viewport_offset[offsetof(AntiAliasedSavedState, Viewport) == 20 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_Stage1ColorOp_offset[offsetof(AntiAliasedSavedState, Stage1ColorOp) == 44 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_PSTextureModes_offset[offsetof(AntiAliasedSavedState, PSTextureModes) == 48 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_RenderState_offset[offsetof(AntiAliasedSavedState, RenderState) == 52 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_TextureState_offset[offsetof(AntiAliasedSavedState, TextureState) == 116 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_PixelShaderState_offset[offsetof(AntiAliasedSavedState, PixelShaderState) == 160 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_VertexShaders_offset[offsetof(AntiAliasedSavedState, VertexShaders) == 388 ? 1 : -1];
|
||||
typedef char AntiAliasedSavedState_SrcTexture_offset[offsetof(AntiAliasedSavedState, SrcTexture) == 580 ? 1 : -1];
|
||||
extern const DWORD g_AntiAliasedRenderStates[32];
|
||||
extern const DWORD g_AntiAliasedTextureStates[22];
|
||||
extern DWORD g_FlipAddress;
|
||||
void WINAPI AntiAliasedSetState(
|
||||
AntiAliasedSavedState *saved,
|
||||
D3DSurface *destination,
|
||||
D3DSurface *source,
|
||||
DWORD filter);
|
||||
void WINAPI AntiAliasedSaveState(
|
||||
AntiAliasedSavedState *saved);
|
||||
void WINAPI AntiAliasedRestoreState(
|
||||
AntiAliasedSavedState *saved);
|
||||
DWORD *WINAPI AntiAliasedFilterBlt(
|
||||
DWORD *push,
|
||||
DWORD xScale,
|
||||
DWORD yScale,
|
||||
const RECT *rectangle);
|
||||
void WINAPI AntiAliasedCopy(
|
||||
const RECT *rectangle);
|
||||
void WINAPI AliasedFlip(
|
||||
void);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
/* Pixel shader state adapted from RXDK-Libs, 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* See libs/d3d8/PROVENANCE.md. */
|
||||
#include "device_layout.h"
|
||||
#include "math_internal.h"
|
||||
#include "push_internal.h"
|
||||
#include "state_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
using namespace D3D;
|
||||
void WINAPI D3DDevice_DeletePixelShader(
|
||||
DWORD handle)
|
||||
{
|
||||
PixelShader *shader = (PixelShader *)handle;
|
||||
if (--shader->RefCount == 0 && shader->D3DOwned)
|
||||
{
|
||||
LocalFree(shader);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetPixelShaderProgram(
|
||||
D3DPIXELSHADERDEF *definition)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (definition)
|
||||
{
|
||||
device->m_UserPixelShader.RefCount = 1;
|
||||
device->m_UserPixelShader.D3DOwned = 0;
|
||||
device->m_UserPixelShader.pPSDef = definition;
|
||||
D3DDevice_SetPixelShader((DWORD)&device->m_UserPixelShader);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3DDevice_SetPixelShader(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetPixelShader(
|
||||
DWORD *handle)
|
||||
{
|
||||
*handle = (DWORD)g_pDevice->m_pPixelShader;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetPixelShaderFunction(
|
||||
DWORD handle,
|
||||
D3DPIXELSHADERDEF *definition)
|
||||
{
|
||||
*definition = *((PixelShader *)handle)->pPSDef;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetPixelShaderConstant(
|
||||
DWORD index,
|
||||
void *data,
|
||||
DWORD count)
|
||||
{
|
||||
float *colors = (float *)data;
|
||||
for (DWORD i = 0; i < count; ++i, ++index, colors += 4)
|
||||
{
|
||||
DWORD color = g_pDevice->m_pPixelShaderConstants[index];
|
||||
colors[3] = (float)((color >> 24) & 255) * (1.0f / 255.0f);
|
||||
colors[0] = (float)((color >> 16) & 255) * (1.0f / 255.0f);
|
||||
colors[1] = (float)((color >> 8) & 255) * (1.0f / 255.0f);
|
||||
colors[2] = (float)(color & 255) * (1.0f / 255.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI D3DDevice_SetPixelShader(
|
||||
DWORD handle)
|
||||
{
|
||||
PixelShader *shader = (PixelShader *)handle;
|
||||
CDevice *device = g_pDevice;
|
||||
PixelShader *oldShader = device->m_pPixelShader;
|
||||
device->m_pPixelShader = shader;
|
||||
if (!shader)
|
||||
{
|
||||
device->m_DirtyFlags |= 0x408;
|
||||
if (device->m_ShaderUsesSpecFog) device->m_DirtyFlags |= 0x40;
|
||||
D3DDevice_SetRenderState_TextureFactor(D3D__RenderState[D3DRS_TEXTUREFACTOR]);
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetTextureBumpEnv(device, push);
|
||||
Push1(push, 0x1e78, 0x00210000);
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
device->m_ShaderUsesSpecFog = shader->pPSDef->PSFinalCombinerInputsABCD | shader->pPSDef->PSFinalCombinerInputsEFG;
|
||||
device->m_ShaderAdjustsTexMode = shader->pPSDef->PSFinalCombinerConstants & 0x100;
|
||||
D3DPIXELSHADERDEF *definition = shader->pPSDef;
|
||||
device->m_PSShaderStageProgram = definition->PSTextureModes;
|
||||
device->m_DirtyFlags |= 0x400;
|
||||
DWORD *push = device->StartPush();
|
||||
if (!oldShader) push = CommonSetTextureBumpEnv(device, push);
|
||||
PushCount(push, 0x260, 8);
|
||||
memcpy(push + 1, definition->PSAlphaInputs, 8 * sizeof(DWORD));
|
||||
PushCount(push + 9, 0xa60, 32);
|
||||
memcpy(push + 10, (const BYTE *)definition + offsetof(D3DPIXELSHADERDEF, PSConstant0), 32 * sizeof(DWORD));
|
||||
Push1(push + 42, 0x17f8, definition->PSCompareMode);
|
||||
PushCount(push + 44, 0x1e20, 2);
|
||||
memcpy(push + 45, (const BYTE *)definition + offsetof(D3DPIXELSHADERDEF, PSFinalCombinerConstant0), 2 * sizeof(DWORD));
|
||||
PushCount(push + 47, 0x1e40, 9);
|
||||
memcpy(push + 48, (const BYTE *)definition + offsetof(D3DPIXELSHADERDEF, PSRGBOutputs), 9 * sizeof(DWORD));
|
||||
PushCount(push + 57, 0x1e74, 2);
|
||||
memcpy(push + 58, (const BYTE *)definition + offsetof(D3DPIXELSHADERDEF, PSDotMapping), 2 * sizeof(DWORD));
|
||||
if (device->m_ShaderUsesSpecFog)
|
||||
{
|
||||
PushCount(push + 60, 0x288, 2);
|
||||
memcpy(push + 61, (const BYTE *)definition + offsetof(D3DPIXELSHADERDEF, PSFinalCombinerInputsABCD), 2 * sizeof(DWORD));
|
||||
device->EndPush(push + 63);
|
||||
}
|
||||
else device->EndPush(push + 60);
|
||||
if (!(device->m_StateFlags & 0x10))
|
||||
{
|
||||
memcpy(D3D__RenderState, definition, sizeof(*definition) - 3 * sizeof(DWORD));
|
||||
D3D__RenderState[D3DRS_PSTEXTUREMODES] = definition->PSTextureModes;
|
||||
}
|
||||
return;
|
||||
}
|
||||
namespace D3D
|
||||
{
|
||||
__inline UCHAR WINAPI Float2UChar(
|
||||
float value)
|
||||
{
|
||||
if (value > 1.0f) value = 1.0f;
|
||||
else if (value < 0.0f) value = 0.0f;
|
||||
return (UCHAR)FloatToLong(value * 255.0f + 0.5f);
|
||||
}
|
||||
}
|
||||
void WINAPI D3DDevice_SetPixelShaderConstant(
|
||||
DWORD index,
|
||||
const void *data,
|
||||
DWORD count)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3DPIXELSHADERDEF *definition = device->m_pPixelShader->pPSDef;
|
||||
const float *colors = (const float *)data;
|
||||
for (UINT i = 0; i < count; i++, index++, colors += 4)
|
||||
{
|
||||
DWORD color = ((DWORD)Float2UChar(colors[3]) << 24) |
|
||||
((DWORD)Float2UChar(colors[0]) << 16) |
|
||||
((DWORD)Float2UChar(colors[1]) << 8) |
|
||||
(DWORD)Float2UChar(colors[2]);
|
||||
device->m_pPixelShaderConstants[index] = color;
|
||||
UINT r;
|
||||
for (r = 0; r < 8; r++)
|
||||
{
|
||||
if (((definition->PSC0Mapping >> (4 * r)) & 15) == index)
|
||||
D3DDevice_SetRenderStateNotInline((D3DRENDERSTATETYPE)(D3DRS_PSCONSTANT0_0 + r), color);
|
||||
}
|
||||
for (r = 0; r < 8; r++)
|
||||
{
|
||||
if (((definition->PSC1Mapping >> (4 * r)) & 15) == index)
|
||||
D3DDevice_SetRenderStateNotInline((D3DRENDERSTATETYPE)(D3DRS_PSCONSTANT1_0 + r), color);
|
||||
}
|
||||
for (r = 0; r < 2; r++)
|
||||
{
|
||||
if (((definition->PSFinalCombinerConstants >> (4 * r)) & 15) == index)
|
||||
D3DDevice_SetRenderStateNotInline((D3DRENDERSTATETYPE)(D3DRS_PSFINALCOMBINERCONSTANT0 + r), color);
|
||||
}
|
||||
if (index == 0)
|
||||
{
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x181c, 3);
|
||||
memcpy(push + 1, colors, 3 * sizeof(DWORD));
|
||||
device->EndPush(push + 4);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DDevice_CreatePixelShader(
|
||||
const D3DPIXELSHADERDEF *definition,
|
||||
DWORD *handle)
|
||||
{
|
||||
PixelShader *shader = (PixelShader *)LocalAlloc(
|
||||
LMEM_FIXED, sizeof(PixelShader) + sizeof(D3DPIXELSHADERDEF));
|
||||
if (!shader)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
shader->pPSDef = (D3DPIXELSHADERDEF *)(shader + 1);
|
||||
shader->RefCount = 1;
|
||||
shader->D3DOwned = 1;
|
||||
*shader->pPSDef = *definition;
|
||||
*handle = (DWORD)shader;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
#ifndef D3D8_PUSH_INTERNAL_H
|
||||
#define D3D8_PUSH_INTERNAL_H
|
||||
/* Target dynamic method expressions fold the count with ADD, not OR.
|
||||
* Valid method fields do not overlap the count field.
|
||||
* NV2A FIFO packet operations. The method word and data words are GPU
|
||||
* commands, never native x86 instruction bytes. */
|
||||
#include "device_layout.h"
|
||||
extern "C" DWORD *WINAPI XMETAL_StartPush(
|
||||
_XMETAL_PushBuffer *buffer);
|
||||
extern "C" DWORD *WINAPI XMETAL_StartPushCount(
|
||||
_XMETAL_PushBuffer *buffer,
|
||||
DWORD count);
|
||||
extern "C" _XMETAL_PushBuffer *g_pPushBuffer;
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI DumpMatrixTransposed(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
const D3DMATRIX *matrix);
|
||||
void WINAPI KickOffAndWaitForIdle(
|
||||
void);
|
||||
void WINAPI BlockOnTime(
|
||||
DWORD time,
|
||||
BOOL makeSpace);
|
||||
DWORD WINAPI SetFence(
|
||||
DWORD flags);
|
||||
__inline DWORD *CDevice::StartPush(
|
||||
void)
|
||||
{
|
||||
return XMETAL_StartPush(
|
||||
&m_Pusher);
|
||||
}
|
||||
__inline DWORD *CDevice::StartPush(
|
||||
DWORD count)
|
||||
{
|
||||
return XMETAL_StartPushCount(
|
||||
&m_Pusher,
|
||||
count);
|
||||
}
|
||||
__inline void CDevice::EndPush(
|
||||
DWORD *put)
|
||||
{
|
||||
m_Pusher.m_pPut = put;
|
||||
return;
|
||||
}
|
||||
__inline void WINAPI PushCount(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
DWORD count)
|
||||
{
|
||||
push[0] = method + (count << 18);
|
||||
return;
|
||||
}
|
||||
__inline void WINAPI Push1(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
DWORD value)
|
||||
{
|
||||
push[0] = method + (1 << 18);
|
||||
push[1] = value;
|
||||
return;
|
||||
}
|
||||
__inline void WINAPI Push2(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
DWORD first,
|
||||
DWORD second)
|
||||
{
|
||||
push[0] = method + (2 << 18);
|
||||
push[1] = first;
|
||||
push[2] = second;
|
||||
return;
|
||||
}
|
||||
/* NV2A matrix packets have sixteen transposed words, or twelve words of
|
||||
* an already-computed inverse. Copies preserve the float representation. */
|
||||
__inline void WINAPI PushMatrixTransposed(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
const D3DMATRIX *matrix)
|
||||
{
|
||||
DumpMatrixTransposed(push, method + (16 << 18), matrix);
|
||||
return;
|
||||
}
|
||||
__inline void WINAPI PushInverseModelViewMatrix(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
const D3DMATRIX *matrix)
|
||||
{
|
||||
PushCount(push, method, 12);
|
||||
memcpy(push + 1, matrix, 12 * sizeof(DWORD));
|
||||
return;
|
||||
}
|
||||
__inline DWORD WINAPI SwapRgb(
|
||||
DWORD color)
|
||||
{
|
||||
return (color & 0xff00ff00UL) | ((color & 0xff) << 16) | ((color >> 16) & 0xff);
|
||||
}
|
||||
/* IEEE-754 encodings used as constant GPU payload words. These are not
|
||||
* host instruction encodings; dynamic float payloads use representation copies. */
|
||||
enum NvFloatWord
|
||||
{
|
||||
NV_FLOAT_ZERO = 0x00000000,
|
||||
NV_FLOAT_ONE = 0x3f800000,
|
||||
NV_FLOAT_POSITIVE_INFINITY = 0x7f800000,
|
||||
NV_FLOAT_INFINITE_LIGHT_RANGE = 0x7149f2ca /* 1e30f */
|
||||
};
|
||||
/* NV097 method numbers, confirmed at all corresponding target writes. */
|
||||
enum
|
||||
{
|
||||
NV097_NO_OPERATION = 0x100,
|
||||
NV097_INVALIDATE_VERTEX_CACHE = 0x1710,
|
||||
NV097_WAIT_FOR_IDLE = 0x110,
|
||||
NV097_SET_FOG_COLOR = 0x2a8,
|
||||
NV097_SET_CULL_FACE_ENABLE = 0x308,
|
||||
NV097_SET_LINE_SMOOTH_ENABLE = 0x320,
|
||||
NV097_SET_CULL_FACE = 0x39c,
|
||||
NV097_SET_FRONT_FACE = 0x3a0,
|
||||
NV097_SET_NORMALIZATION_ENABLE = 0x3a4,
|
||||
NV097_SET_LINE_WIDTH = 0x3b8,
|
||||
NV097_SET_COMBINER_FACTOR0 = 0xa60,
|
||||
NV097_SET_SHADOW_DEPTH_FUNC = 0x1e6c,
|
||||
NV097_SET_CULL_FACE_V_FRONT = 0x404,
|
||||
NV097_SET_CULL_FACE_V_BACK = 0x405
|
||||
};
|
||||
__inline void WINAPI Push4f(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
float w)
|
||||
{
|
||||
/* GPU command memory contains float payloads, not x86 instructions. */
|
||||
push[0] = method + (4 << 18);
|
||||
((float *)(push + 1))[0] = x;
|
||||
((float *)(push + 1))[1] = y;
|
||||
((float *)(push + 1))[2] = z;
|
||||
((float *)(push + 1))[3] = w;
|
||||
return;
|
||||
}
|
||||
__inline void CDevice::RecordResourceReadPush(
|
||||
D3DResource *resource)
|
||||
{
|
||||
resource->Lock = m_CpuTime;
|
||||
return;
|
||||
}
|
||||
__inline void CDevice::RecordSurfaceWritePush(
|
||||
D3DResource *resource)
|
||||
{
|
||||
D3DBaseTexture *parent = ((D3DSurface *)resource)->Parent;
|
||||
if (parent) resource = parent;
|
||||
resource->Lock = m_CpuTime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,244 @@
|
||||
/* Transposed matrix packet from January target. GPU payload writes only. */
|
||||
#include <xmmintrin.h>
|
||||
#include "push_internal.h"
|
||||
#include "pusher_state.h"
|
||||
#include "resource_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI DumpMatrixTransposed(
|
||||
DWORD *push,
|
||||
DWORD method,
|
||||
const D3DMATRIX *matrix)
|
||||
{
|
||||
push[0] = method;
|
||||
memcpy(push + 1, &matrix->m[0][0], sizeof(float));
|
||||
memcpy(push + 2, &matrix->m[1][0], sizeof(float));
|
||||
memcpy(push + 3, &matrix->m[2][0], sizeof(float));
|
||||
memcpy(push + 4, &matrix->m[3][0], sizeof(float));
|
||||
memcpy(push + 5, &matrix->m[0][1], sizeof(float));
|
||||
memcpy(push + 6, &matrix->m[1][1], sizeof(float));
|
||||
memcpy(push + 7, &matrix->m[2][1], sizeof(float));
|
||||
memcpy(push + 8, &matrix->m[3][1], sizeof(float));
|
||||
memcpy(push + 9, &matrix->m[0][2], sizeof(float));
|
||||
memcpy(push + 10, &matrix->m[1][2], sizeof(float));
|
||||
memcpy(push + 11, &matrix->m[2][2], sizeof(float));
|
||||
memcpy(push + 12, &matrix->m[3][2], sizeof(float));
|
||||
memcpy(push + 13, &matrix->m[0][3], sizeof(float));
|
||||
memcpy(push + 14, &matrix->m[1][3], sizeof(float));
|
||||
memcpy(push + 15, &matrix->m[2][3], sizeof(float));
|
||||
memcpy(push + 16, &matrix->m[3][3], sizeof(float));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
/* Deliberate, short polling delay. The target performs these counter accesses
|
||||
* and the reference BusyLoop documents avoidance of excessive HwGet polling. */
|
||||
void WINAPI BusyLoop(
|
||||
void)
|
||||
{
|
||||
volatile DWORD count = 400;
|
||||
do { } while (--count != 0);
|
||||
return;
|
||||
}
|
||||
void CDevice::InitializePushBuffer(
|
||||
void)
|
||||
{
|
||||
m_PushSegmentSize = m_PushBufferSize / 16;
|
||||
m_Pusher.m_pPut = m_pPushBase;
|
||||
m_Pusher.m_pThreshold = m_pPushBase + m_PushSegmentSize / sizeof(DWORD) - 129;
|
||||
m_CpuTime = 5;
|
||||
*m_pGpuTime = 3;
|
||||
m_LastRunPushBufferTime = 3;
|
||||
return;
|
||||
}
|
||||
void CDevice::HwPut(
|
||||
DWORD *put)
|
||||
{
|
||||
m_pControlDma->Put = (DWORD)put & 0x03ffffffUL;
|
||||
return;
|
||||
}
|
||||
DWORD *CDevice::GpuGet(
|
||||
void)
|
||||
{
|
||||
DWORD *get = HwGet();
|
||||
if (get < m_pPushBase || get >= m_pPushLimit)
|
||||
{
|
||||
get = (DWORD *)((ReadGpuRegister(m_NvBase, 0x324c) & ~1UL) | 0x80000000UL);
|
||||
}
|
||||
return get;
|
||||
}
|
||||
void WINAPI FlushWCCache(
|
||||
void)
|
||||
{
|
||||
volatile DWORD *base = (volatile DWORD *)g_pDevice->m_Miniport.m_RegisterBase;
|
||||
/* One-instruction, target-evidenced cache fence. The intrinsic trial lets
|
||||
* VC7 move an MMIO read before SFENCE. No raw instruction bytes are used. */
|
||||
__asm sfence;
|
||||
base[0x100410 / sizeof(DWORD)] |= 0x10000;
|
||||
while ((base[0x100410 / sizeof(DWORD)] >> 16) & 1) { }
|
||||
return;
|
||||
}
|
||||
void CDevice::KickOff(
|
||||
void)
|
||||
{
|
||||
if (!D3D__NullHardware)
|
||||
{
|
||||
DWORD *put = (m_StateFlags & 4) ? m_pPushBufferRecordSavedPut : m_Pusher.m_pPut;
|
||||
FlushWCCache();
|
||||
HwPut(put);
|
||||
m_pKickOff = put;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Pusher.m_pPut = HwGet();
|
||||
m_pKickOff = m_Pusher.m_pPut;
|
||||
*m_pGpuTime = m_CpuTime - 2;
|
||||
m_Miniport.m_VBlankFlipCount = m_PresentCount;
|
||||
}
|
||||
return;
|
||||
}
|
||||
DWORD WINAPI SetFence(
|
||||
DWORD flags)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
FenceEncoding *encoding = (FenceEncoding *)push;
|
||||
DWORD time = device->m_CpuTime;
|
||||
encoding->m_SemaphoreCommand = 0x41d70;
|
||||
encoding->m_Time = time;
|
||||
encoding->m_SetColorClearCommand1 = 0x41d90;
|
||||
encoding->m_SetColorClearArgument1 = 0;
|
||||
encoding->m_SetColorClearCommand2 = 0x41d90;
|
||||
encoding->m_SetColorClearArgument2 = 0;
|
||||
device->EndPush(push + sizeof(FenceEncoding) / sizeof(DWORD));
|
||||
DWORD index = (time >> 1) & 63;
|
||||
DWORD distance = device->m_PusherPutRunSize;
|
||||
device->m_PusherFence[index].Time = time;
|
||||
device->m_PusherFence[index].pEncoding = encoding;
|
||||
device->m_PusherFence[index].Distance = distance;
|
||||
if (flags & 1)
|
||||
{
|
||||
index = (device->m_PusherLastSegment + 1) & 15;
|
||||
device->m_PusherLastSegment = index;
|
||||
device->m_PusherSegment[index].Time = time;
|
||||
device->m_PusherSegment[index].pEncoding = encoding;
|
||||
device->m_PusherSegment[index].Distance = distance;
|
||||
}
|
||||
if (!(flags & 2)) device->KickOff();
|
||||
device->m_CpuTime += 2;
|
||||
return time;
|
||||
}
|
||||
Fence *WINAPI FindFence(
|
||||
DWORD time)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD age = device->Age(time);
|
||||
if (age <= 128)
|
||||
{
|
||||
return &device->m_PusherFence[(time >> 1) & 63];
|
||||
}
|
||||
DWORD index = device->m_PusherLastSegment;
|
||||
if (device->Age(device->m_PusherSegment[index].Time) > age)
|
||||
{
|
||||
return &device->m_PusherFence[(device->m_CpuTime >> 1) & 63];
|
||||
}
|
||||
do
|
||||
{
|
||||
index = (index + 1) & 15;
|
||||
} while (device->Age(device->m_PusherSegment[index].Time) > age);
|
||||
return &device->m_PusherSegment[index];
|
||||
}
|
||||
DWORD __fastcall ComputeGap(
|
||||
CDevice *device,
|
||||
Fence *fence)
|
||||
{
|
||||
DWORD get = (DWORD)device->GpuGet();
|
||||
DWORD put = (DWORD)device->m_Pusher.m_pPut;
|
||||
if (get <= put) get += device->m_PusherLastSize;
|
||||
DWORD fenceAddress = (DWORD)fence->pEncoding;
|
||||
if (fenceAddress <= put) fenceAddress += device->m_PusherLastSize;
|
||||
LONG gap = (LONG)(fenceAddress - get);
|
||||
if (gap < 0) return 0;
|
||||
return gap + device->m_PusherPutRunSize - device->m_Miniport.m_PusherGetRunSize;
|
||||
}
|
||||
void WINAPI KickOffAndWaitForIdle(
|
||||
void)
|
||||
{
|
||||
BlockOnTime(g_pDevice->m_CpuTime, FALSE);
|
||||
return;
|
||||
}
|
||||
void WINAPI BlockOnResource(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if (g_pDevice)
|
||||
{
|
||||
D3DResource *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
if (IsResourceSetInDevice(resource))
|
||||
{
|
||||
KickOffAndWaitForIdle();
|
||||
return;
|
||||
}
|
||||
resource = parent;
|
||||
}
|
||||
DWORD time = resource->Lock;
|
||||
if (IsResourceSetInDevice(resource)) KickOffAndWaitForIdle();
|
||||
else BlockOnTime(time, FALSE);
|
||||
resource->Lock = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
using namespace D3D;
|
||||
BOOL WINAPI D3DDevice_IsFencePending(
|
||||
DWORD fence)
|
||||
{
|
||||
return g_pDevice->IsTimePending(fence);
|
||||
}
|
||||
void WINAPI D3DDevice_InsertCallback(
|
||||
D3DCALLBACKTYPE type,
|
||||
D3DCALLBACK callback,
|
||||
DWORD context)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push2(push, 0x1d8c, (DWORD)callback, context);
|
||||
if (type == D3DCALLBACK_READ)
|
||||
{
|
||||
Push1(push + 3, 0x100, 0x314);
|
||||
device->EndPush(push + 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
Push1(push + 3, 0x110, 0);
|
||||
Push1(push + 5, 0x100, 0x318);
|
||||
device->EndPush(push + 7);
|
||||
}
|
||||
return;
|
||||
}
|
||||
extern "C" DWORD *WINAPI XMETAL_StartPush(
|
||||
_XMETAL_PushBuffer *buffer)
|
||||
{
|
||||
DWORD *put = buffer->m_pPut;
|
||||
if (put >= buffer->m_pThreshold)
|
||||
{
|
||||
put = ((CDevice *)buffer)->MakeSpace();
|
||||
}
|
||||
return put;
|
||||
}
|
||||
extern "C" DWORD *WINAPI XMETAL_StartPushCount(
|
||||
_XMETAL_PushBuffer *buffer,
|
||||
DWORD count)
|
||||
{
|
||||
DWORD *put = buffer->m_pPut;
|
||||
if (put + count >= buffer->m_pThreshold + 128)
|
||||
{
|
||||
put = ((CDevice *)buffer)->MakeSpace();
|
||||
}
|
||||
return put;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef D3D8_PUSHER_STATE_H
|
||||
#define D3D8_PUSHER_STATE_H
|
||||
#include "hardware_internal.h"
|
||||
namespace D3D
|
||||
{
|
||||
/* Original 24-byte fence packet and its patchable command fields. */
|
||||
struct FenceEncoding
|
||||
{
|
||||
DWORD m_SemaphoreCommand;
|
||||
DWORD m_Time;
|
||||
union { DWORD m_SetColorClearCommand1; DWORD m_WaitForIdleCommand; };
|
||||
union { DWORD m_SetColorClearArgument1; DWORD m_WaitForIdleArgument; };
|
||||
union { DWORD m_SetColorClearCommand2; DWORD m_NoOperationCommand; };
|
||||
union { DWORD m_SetColorClearArgument2; DWORD m_FenceCommand; };
|
||||
};
|
||||
typedef char fence_encoding_size[sizeof(FenceEncoding) == 24 ? 1 : -1];
|
||||
void WINAPI BusyLoop(
|
||||
void);
|
||||
void WINAPI FlushWCCache(
|
||||
void);
|
||||
Fence *WINAPI FindFence(
|
||||
DWORD time);
|
||||
DWORD __fastcall ComputeGap(
|
||||
CDevice *device,
|
||||
Fence *fence);
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"mpdac": {
|
||||
"optimization": "/O1",
|
||||
"evidence": "The January DacProgramGammaRamp is 65 unpadded bytes; /O2 produced 80 and differed, while /O1 reproduces all bytes. Output-matching hypothesis, not a recovered complete original command."
|
||||
},
|
||||
"mpmode": {
|
||||
"optimization": "/O1",
|
||||
"evidence": "Trial for size-optimized miniport code: target instruction forms and non-16-aligned section lengths. Must be validated function by function."
|
||||
},
|
||||
"mpcore": {
|
||||
"optimization": "/O1",
|
||||
"evidence": "Size-optimized miniport hypothesis from original odd-length sections and gamma/video-start control matches. Every section remains individually compared. Original CreateGrObject contains inlined zero-fill STOS instructions; /O1 /Oi reproduces its 155 bytes and preserves the eight other current exact methods. Ordinary header-defined OBJECTINFO::Init; no forced inline.",
|
||||
"additional_flags": [
|
||||
"/Oi"
|
||||
]
|
||||
},
|
||||
"mphal": {
|
||||
"optimization": "/O1",
|
||||
"evidence": "Original HAL methods use odd-sized unpadded code sections and size-optimized forms. Per-module hypothesis; count only complete comparator passes."
|
||||
},
|
||||
"block": {
|
||||
"optimization": "/O1",
|
||||
"evidence": "Target block sections have nonaligned sizes (60,14,1070,392,685). Pinned RXDK block.cpp has an explicit optimize-for-size directive. /O1 is a per-TU hypothesis; each complete target section must pass the unchanged comparator. No production optimizer pragma. Original ClearStateBlockFlags uses inline rep-stos for the 516-byte dirty array; /Oi requests genuine CRT intrinsics rather than substituting a fake loop.",
|
||||
"additional_flags": [
|
||||
"/Oi"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"module": "pixeljar",
|
||||
"target": "_code_001e3fc0",
|
||||
"candidate": "?LockSurface@PixelJar@D3D@@YGXPAUD3DPixelContainer@@W4_D3DCUBEMAP_FACES@@IKPAPAEPAK3@Z",
|
||||
"evidence": "Private LockSurface: caller-connected locking graph, same 80 padded bytes and both ordered public call relocations; original callee-pop 20-byte private ABI. No callee renaming in comparator."
|
||||
},
|
||||
{
|
||||
"module": "d3dbase",
|
||||
"target": "_code_001d6fa0",
|
||||
"candidate": "?Round@D3D@@YGKM@Z",
|
||||
"evidence": "Original module PDB names D3D::Round; original scalar parameter, callee stack-pop, constant references, public FloatToLong relocation and complete section match the already-emitted authentic helper. Entry-name pairing only, no relocation renaming or equality changes. See continuation/private_owner_evidence.json."
|
||||
},
|
||||
{
|
||||
"module": "state",
|
||||
"target": "_code_001d9060",
|
||||
"candidate": "?Round@D3D@@YGKM@Z",
|
||||
"evidence": "Original module PDB names D3D::Round; original scalar parameter, callee stack-pop, constant references, public FloatToLong relocation and complete section match the already-emitted authentic helper. Entry-name pairing only, no relocation renaming or equality changes. See continuation/private_owner_evidence.json."
|
||||
},
|
||||
{
|
||||
"module": "pshader",
|
||||
"target": "_code_001dbc90",
|
||||
"candidate": "?Float2UChar@D3D@@YGEM@Z",
|
||||
"evidence": "Original module PDB names D3D::Float2UChar; original scalar parameter, callee stack-pop, constant references, public FloatToLong relocation and complete section match the already-emitted authentic helper. Entry-name pairing only, no relocation renaming or equality changes. See continuation/private_owner_evidence.json."
|
||||
},
|
||||
{
|
||||
"module": "combiner",
|
||||
"target": "_code_001e6000",
|
||||
"candidate": "?nvKelvinACModulate@D3D@@YGJPAVCDevice@1@KK@Z",
|
||||
"evidence": "Original combiner module PDB procedure at the PE-mapped file offset, original return/argument types and length. Entry-only name pairing; every relocation still checked by the unchanged comparator. See evidence/wave10/combiner_owner_proofs.json."
|
||||
},
|
||||
{
|
||||
"module": "combiner",
|
||||
"target": "_code_001e6350",
|
||||
"candidate": "?nvKelvinACLerp@D3D@@YGJPAVCDevice@1@HH@Z",
|
||||
"evidence": "Original combiner module PDB procedure at the PE-mapped file offset, original return/argument types and length. Entry-only name pairing; every relocation still checked by the unchanged comparator. See evidence/wave10/combiner_owner_proofs.json."
|
||||
},
|
||||
{
|
||||
"module": "combiner",
|
||||
"target": "_code_001e6890",
|
||||
"candidate": "?nvKelvinCCModulate@D3D@@YGJPAVCDevice@1@KK@Z",
|
||||
"evidence": "Original combiner module PDB procedure at the PE-mapped file offset, original return/argument types and length. Entry-only name pairing; every relocation still checked by the unchanged comparator. See evidence/wave10/combiner_owner_proofs.json."
|
||||
},
|
||||
{
|
||||
"module": "combiner",
|
||||
"target": "_code_001e6cd0",
|
||||
"candidate": "?nvKelvinCCDotProduct@D3D@@YGJPAVCDevice@1@KK@Z",
|
||||
"evidence": "Original combiner module PDB procedure at the PE-mapped file offset, original return/argument types and length. Entry-only name pairing; every relocation still checked by the unchanged comparator. See evidence/wave10/combiner_owner_proofs.json."
|
||||
},
|
||||
{
|
||||
"module": "combiner",
|
||||
"target": "_code_001e6d60",
|
||||
"candidate": "?nvKelvinCCLerp@D3D@@YGJPAVCDevice@1@HH@Z",
|
||||
"evidence": "Original combiner module PDB procedure at the PE-mapped file offset, original return/argument types and length. Entry-only name pairing; every relocation still checked by the unchanged comparator. See evidence/wave10/combiner_owner_proofs.json."
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,173 @@
|
||||
# Continuation 010 — combiner reconstruction and original private identities
|
||||
|
||||
## Counts and distinct proof categories
|
||||
|
||||
The incoming checkpoint009 was freshly rebuilt in this continuation workspace:
|
||||
350 sections /44,611 padded /42,253 NOP-excluded bytes. All14 stages passed.
|
||||
Its original source, candidate objects, progress reports and replay log are frozen
|
||||
under evidence/wave10_baseline. Cumulative checkpoints must never be added together.
|
||||
|
||||
Current source compiles27 C++ units and contains59 authored source/header/data files.
|
||||
Thirty newly reconstructed combiner functions reproduce4,496 padded /4,292
|
||||
NOP-excluded code bytes. No new SDK wrapper or recovered data is called an algorithm.
|
||||
|
||||
There are TWO explicit verification categories:
|
||||
|
||||
* **356 raw-symbol comparator matches /45,107 padded /42,703 NOP-excluded bytes.**
|
||||
This preserves all350 incoming matches and adds six combiner functions /496 bytes.
|
||||
The six comprise the public AlphaOutput function and five PDB-authenticated
|
||||
PRIVATE ENTRY-ONLY pairs. Entry pairing does not rename referenced relocations.
|
||||
Cumulatively,347 are same-name comparisons and nine are entry-only pairs.
|
||||
* **24 ADDITIONAL combiner functions /4,000 padded /3,842 NOP-excluded bytes** pass
|
||||
the IDENTICAL comparator in an explicitly scoped, original-PDB-recovered symbol
|
||||
identity view, AND independently reproduce their original executable bytes after
|
||||
candidate relocation in memory. These are NOT raw-symbol comparator passes and
|
||||
must not silently enter a raw-symbol or canonical ledger as such.
|
||||
|
||||
Together these are380 distinct reproduced target sections /49,107 padded /
|
||||
46,545 NOP-excluded bytes,62.30% of78,827 padded D3D8 code bytes. The target remains
|
||||
29 objects and685 contributions.29,720 padded bytes remain unmatched. The expanded
|
||||
census has67 nonexact entries and238 without a paired candidate symbol; some absent
|
||||
pairs represent not-emitted helpers rather than absent source text.
|
||||
|
||||
`evidence/progress_combined.json` remains the unmodified RAW-gate census.
|
||||
`evidence/progress_verified.json` is the separately labeled expanded census.
|
||||
Neither implies whole-object, canonical, final-image or hardware completion.
|
||||
Function contributions can include jump tables and padding. NOP-exclusion is not
|
||||
automatically the canonical meaningful-byte definition. All350 baseline target
|
||||
and candidate function fingerprints are preserved; no regression is waived.
|
||||
|
||||
## Source work
|
||||
|
||||
`combiner.cpp` contains32 complete functions: alpha/color input selection,
|
||||
complement/expansion, select/modulate/add/subtract/blending/premodulate/dot-product,
|
||||
multiply-add/lerp, output configuration and their constructor dispatchers.
|
||||
Thirty reproduce; two are retained NONEXACT. Types, declarations, named input
|
||||
selectors and shift modes are owned by combiner_internal.h. Existing code/source
|
||||
outside this combiner family was not changed. No old TU options or build.py changed.
|
||||
|
||||
The related GPL-3.0-or-later RXDK source at pinned commit
|
||||
29e018674a3443f9df5b5cb4478bb9c54d8a2a3a supplies semantic corroboration, not the target
|
||||
ABI or byte proof. Its later premodulate implementation removed tests that the
|
||||
January target still performs. Restoring those genuine conditions closes the
|
||||
color premodulate body and exposes the alpha boundary case below.
|
||||
|
||||
The four-input shift table is a real16-byte writable table with values24,16,8,0.
|
||||
It matches the original data separately; it receives ZERO code credit.
|
||||
The source uses an authentic descriptive name, not `_data` plus an address.
|
||||
|
||||
Original null-texture fallback, first-stage diffuse versus later-stage current
|
||||
inputs, specular-needed state, argument save/restore, temporary-result selection,
|
||||
shift/bias limitations and signed/complement map values are preserved. Valid
|
||||
callers supply texture stages0..3, combiner stages0..7, input selectors0..3,
|
||||
supported texture operations and stable single-threaded device state.
|
||||
|
||||
## Why private-symbol comparison needed another proof
|
||||
|
||||
The supplied portable split labels24 private procedures `_code_<address>` and the
|
||||
shift table `_data_<address>`. The original PDB has their authentic source names,
|
||||
logical types, code sections/offsets and lengths. Putting address placeholders in
|
||||
new source would violate house rules; treating every equal-size helper as an alias
|
||||
would be unsound. Neither is done.
|
||||
|
||||
`verify_wave10_combiner.py` performs these independent checks:
|
||||
|
||||
1. Pins the original EXE hash and checks its NB10 signature/age against the PDB.
|
||||
Reads original PE section mappings rather than assuming a load base or that
|
||||
file offsets and virtual addresses are interchangeable.
|
||||
2. Finds the unique original d3d8/combiner module. Authenticates all32 procedure
|
||||
records against PRE-REVIEWED names, return/argument types, calling convention,
|
||||
original local/global record kind, section, offset and procedure length.
|
||||
Candidate names are dictated by those reviewed signatures, not byte similarity.
|
||||
3. Authenticates the shift table's unique S_LDATA32 record, unsigned-long[4] type,
|
||||
16-byte extent, source declaration, original location, contents and candidate
|
||||
contents. Four type-zero empty padding records provide no naming evidence and
|
||||
are explicitly not used for ownership. The unchanged strict parser is retained.
|
||||
4. Builds an IN-MEMORY target metadata view restoring only those independently
|
||||
recovered private names. Original target/candidate files, instruction bytes,
|
||||
section flags/storage classes and the comparator remain untouched. The same
|
||||
comparator still requires full size, normalized bytes and ordered relocations.
|
||||
5. Resolves candidate relocations independently at original PDB procedure/data
|
||||
addresses. The one public external, D3D__TextureState, is mapped using untouched
|
||||
original symbol metadata. I386 DIR32/REL32 addends and patch locations are
|
||||
applied in memory; unsupported, overlapping or unowned relocations fail closed.
|
||||
Every entire relocated function contribution must equal the ORIGINAL EXE
|
||||
bytes, not merely the reconstructed target. Every target split contribution
|
||||
also must round-trip to those original bytes.
|
||||
6. Rejects deliberately changed instructions, sizes, relocation kinds/positions/
|
||||
addends, wrong actual callee bindings, wrong table addresses and table contents.
|
||||
A failed early test redirected an INLINED, unreferenced callee; the final test
|
||||
first asserts its chosen callee is actually referenced. Failed attempts remain
|
||||
preserved, not counted as successful negative controls.
|
||||
|
||||
This yields30 body proofs, six already in the raw gate and24 additional. The two
|
||||
nonexact bodies are REQUIRED to fail both the restored-identity gate and literal
|
||||
original-image comparison. They are not renamed into success. The original PDB
|
||||
logical convention does not by itself prove an optimizer's private register ABI;
|
||||
matching real call-site/callee machine bytes is required as well.
|
||||
|
||||
The24-body category is new and intentionally prominent in reports. This is a
|
||||
proof of the function bytes under original symbol placement, NOT proof that this
|
||||
incomplete source links at those addresses, that a nonexact callee works, or that
|
||||
the complete original object layout has been recovered. No global alias policy or
|
||||
semantic-match waiver was added. Canonical admission must review this evidence.
|
||||
|
||||
## Two nonexact functions and rejected shortcuts
|
||||
|
||||
**AlphaPremodulate:192 target /208 candidate bytes.** The target can access
|
||||
`TextureState[stage+1]` even when a point-sprite remapping makes stage3 relevant.
|
||||
The retained source explicitly checks `stage < D3DTSS_MAXSTAGES-1`; otherwise it
|
||||
uses the existing select-argument fallback. We will not count an out-of-bounds
|
||||
read as source-compliant merely because removing the guard matches instructions.
|
||||
The unguarded historical trial is retained ONLY in experiments, not production.
|
||||
This guard intentionally changes the original boundary behavior; it has zero
|
||||
matching credit. The matched constructor caller does not certify this callee.
|
||||
|
||||
**ColorOutput:240 target /240 candidate,35 normalized differing positions.**
|
||||
The remaining output-word/register-lifetime differences did not close with the
|
||||
saved plausible operation-order and word-snapshot trials. The ordinary reference-
|
||||
shaped source is retained and parked; no dummy work, volatile carrier, register
|
||||
constraint, assembly or forced inlining was added.
|
||||
|
||||
Device Init investigation is retained as research, NOT a completed source body.
|
||||
The earlier `add_device_init.py` draft is not a replayable/approved implementation
|
||||
of the January target: the original has kernel/FS and cache-control details not
|
||||
resolved by that draft. It was NOT applied to accepted source. Do not run it to
|
||||
replace current source or count Init as complete. See the experiments note.
|
||||
|
||||
## House rules and provenance
|
||||
|
||||
Current published rules blob6bee6e0c6b67e3799527fbf96880e11bc59b6508 was checked.
|
||||
New signatures put every parameter on its own line and return explicitly. Public
|
||||
prototypes and enums stay in the associated combiner owner. Private functions
|
||||
use authentic descriptive names. Correct enum constants appear in switches;
|
||||
DWORD arithmetic retains unsigned shift semantics. No new inline assembly,
|
||||
force-inline/no-inline attributes, optimizer pragmas, synthetic volatile locals,
|
||||
raw CPU instruction emission, object patches or compiler-option changes appear.
|
||||
Ordinary private helpers are called by the real constructor graph, not fake
|
||||
emission anchors. Halo tag/object macros do not apply to SDK combiner resources.
|
||||
|
||||
The source-policy scan is only lexical. New-source review is not a formal proof
|
||||
of all inherited UB, concurrency, ownership or historical authenticity. The
|
||||
inherited BSF/SFENCE helper sites remain unchanged and disclosed. No original
|
||||
executable, extracted target routine or GPU program was run. No bespoke runtime
|
||||
or GPU tests are claimed. Preserve GPL/RXDK notices and license; this is not
|
||||
clean-room or automatically compatible with a CC0 canonical source license.
|
||||
|
||||
## Rebuild/recovery and outstanding gates
|
||||
|
||||
The wave010 replay rebuilds all27 units, runs the unchanged raw comparator,
|
||||
existing/five new entry-only pairs,44 comparator tests, earlier frozen-input and
|
||||
baseline gates,1,829 raw-code/relocation mutations, three source patch recoveries,
|
||||
and the new350-body baseline plus combiner PDB/original-image proof. Its additional
|
||||
identity proof rejects396 mutations/incorrect bindings. These two test populations
|
||||
are separately reported, not advertised as exhaustive behavioral coverage.
|
||||
|
||||
All59 current source files are bound to current candidate manifests together with
|
||||
the compiler/frontend/backend, generated SDK overlay, options and build script.
|
||||
Old clean-replay records are historical. The current final record belongs in
|
||||
`evidence/wave10/clean_replay.json`; a missing or failed record does not mean success.
|
||||
All working source and experiments are saved. Canonical/GitHub/Bink/Claude remain
|
||||
untouched. Native splitting, complete data/BSS/COMDAT/extra-section ownership,
|
||||
full inherited-source admission, final linking, GPU/concurrency and canonical
|
||||
consumer regression remain open. No whole object is admitted.
|
||||
@@ -0,0 +1,942 @@
|
||||
[
|
||||
{
|
||||
"name": "AntiAliasing",
|
||||
"byte_offset": 828,
|
||||
"initial_value": 4294901760
|
||||
},
|
||||
{
|
||||
"name": "Blend",
|
||||
"byte_offset": 832,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BlendColor",
|
||||
"byte_offset": 836,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BorderColor0",
|
||||
"byte_offset": 840,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BorderColor1",
|
||||
"byte_offset": 844,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BorderColor2",
|
||||
"byte_offset": 848,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BorderColor3",
|
||||
"byte_offset": 852,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat00_1",
|
||||
"byte_offset": 856,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat00_2",
|
||||
"byte_offset": 860,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat00_3",
|
||||
"byte_offset": 864,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat01_1",
|
||||
"byte_offset": 868,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat01_2",
|
||||
"byte_offset": 872,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat01_3",
|
||||
"byte_offset": 876,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat10_1",
|
||||
"byte_offset": 880,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat10_2",
|
||||
"byte_offset": 884,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat10_3",
|
||||
"byte_offset": 888,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat11_1",
|
||||
"byte_offset": 892,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat11_2",
|
||||
"byte_offset": 896,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpMat11_3",
|
||||
"byte_offset": 900,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpOffset1",
|
||||
"byte_offset": 904,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpOffset2",
|
||||
"byte_offset": 908,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpOffset3",
|
||||
"byte_offset": 912,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpScale1",
|
||||
"byte_offset": 916,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpScale2",
|
||||
"byte_offset": 920,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BumpScale3",
|
||||
"byte_offset": 924,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ClearRectX",
|
||||
"byte_offset": 928,
|
||||
"initial_value": 268369920
|
||||
},
|
||||
{
|
||||
"name": "ClearRectY",
|
||||
"byte_offset": 932,
|
||||
"initial_value": 268369920
|
||||
},
|
||||
{
|
||||
"name": "ColorClearValue",
|
||||
"byte_offset": 936,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ColorKeyColor0",
|
||||
"byte_offset": 940,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ColorKeyColor1",
|
||||
"byte_offset": 944,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ColorKeyColor2",
|
||||
"byte_offset": 948,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ColorKeyColor3",
|
||||
"byte_offset": 952,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_0",
|
||||
"byte_offset": 956,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_1",
|
||||
"byte_offset": 960,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_2",
|
||||
"byte_offset": 964,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_3",
|
||||
"byte_offset": 968,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_4",
|
||||
"byte_offset": 972,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_5",
|
||||
"byte_offset": 976,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_6",
|
||||
"byte_offset": 980,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor0_7",
|
||||
"byte_offset": 984,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_0",
|
||||
"byte_offset": 988,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_1",
|
||||
"byte_offset": 992,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_2",
|
||||
"byte_offset": 996,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_3",
|
||||
"byte_offset": 1000,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_4",
|
||||
"byte_offset": 1004,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_5",
|
||||
"byte_offset": 1008,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_6",
|
||||
"byte_offset": 1012,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineFactor1_7",
|
||||
"byte_offset": 1016,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI0",
|
||||
"byte_offset": 1020,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI1",
|
||||
"byte_offset": 1024,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI2",
|
||||
"byte_offset": 1028,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI3",
|
||||
"byte_offset": 1032,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI4",
|
||||
"byte_offset": 1036,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI5",
|
||||
"byte_offset": 1040,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI6",
|
||||
"byte_offset": 1044,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaI7",
|
||||
"byte_offset": 1048,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO0",
|
||||
"byte_offset": 1052,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO1",
|
||||
"byte_offset": 1056,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO2",
|
||||
"byte_offset": 1060,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO3",
|
||||
"byte_offset": 1064,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO4",
|
||||
"byte_offset": 1068,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO5",
|
||||
"byte_offset": 1072,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO6",
|
||||
"byte_offset": 1076,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineAlphaO7",
|
||||
"byte_offset": 1080,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI0",
|
||||
"byte_offset": 1084,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI1",
|
||||
"byte_offset": 1088,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI2",
|
||||
"byte_offset": 1092,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI3",
|
||||
"byte_offset": 1096,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI4",
|
||||
"byte_offset": 1100,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI5",
|
||||
"byte_offset": 1104,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI6",
|
||||
"byte_offset": 1108,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorI7",
|
||||
"byte_offset": 1112,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO0",
|
||||
"byte_offset": 1116,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO1",
|
||||
"byte_offset": 1120,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO2",
|
||||
"byte_offset": 1124,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO3",
|
||||
"byte_offset": 1128,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO4",
|
||||
"byte_offset": 1132,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO5",
|
||||
"byte_offset": 1136,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO6",
|
||||
"byte_offset": 1140,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineColorO7",
|
||||
"byte_offset": 1144,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineCtl",
|
||||
"byte_offset": 1148,
|
||||
"initial_value": 257
|
||||
},
|
||||
{
|
||||
"name": "CombineSpecFog0",
|
||||
"byte_offset": 1152,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CombineSpecFog1",
|
||||
"byte_offset": 1156,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Control0",
|
||||
"byte_offset": 1160,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Control1",
|
||||
"byte_offset": 1164,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Control2",
|
||||
"byte_offset": 1168,
|
||||
"initial_value": 273
|
||||
},
|
||||
{
|
||||
"name": "Control3",
|
||||
"byte_offset": 1172,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FogColor",
|
||||
"byte_offset": 1176,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FogParam0",
|
||||
"byte_offset": 1180,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FogParam1",
|
||||
"byte_offset": 1184,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "PointSize",
|
||||
"byte_offset": 1188,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SetupRaster",
|
||||
"byte_offset": 1192,
|
||||
"initial_value": 1145044992
|
||||
},
|
||||
{
|
||||
"name": "ShaderClipMode",
|
||||
"byte_offset": 1196,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ShaderCtl",
|
||||
"byte_offset": 1200,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ShaderProg",
|
||||
"byte_offset": 1204,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SemaphoreOffset",
|
||||
"byte_offset": 1208,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ShadowCtl",
|
||||
"byte_offset": 1212,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ShadowZSlopeThreshold",
|
||||
"byte_offset": 1216,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SpecFogFactor0",
|
||||
"byte_offset": 1220,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SpecFogFactor1",
|
||||
"byte_offset": 1224,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SurfaceClipX",
|
||||
"byte_offset": 1228,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SurfaceClipY",
|
||||
"byte_offset": 1232,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexAddress0",
|
||||
"byte_offset": 1236,
|
||||
"initial_value": 197379
|
||||
},
|
||||
{
|
||||
"name": "TexAddress1",
|
||||
"byte_offset": 1240,
|
||||
"initial_value": 197379
|
||||
},
|
||||
{
|
||||
"name": "TexAddress2",
|
||||
"byte_offset": 1244,
|
||||
"initial_value": 197379
|
||||
},
|
||||
{
|
||||
"name": "TexAddress3",
|
||||
"byte_offset": 1248,
|
||||
"initial_value": 197379
|
||||
},
|
||||
{
|
||||
"name": "TexCtl0_0",
|
||||
"byte_offset": 1252,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexCtl0_1",
|
||||
"byte_offset": 1256,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexCtl0_2",
|
||||
"byte_offset": 1260,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexCtl0_3",
|
||||
"byte_offset": 1264,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexCtl1_0",
|
||||
"byte_offset": 1268,
|
||||
"initial_value": 524288
|
||||
},
|
||||
{
|
||||
"name": "TexCtl1_1",
|
||||
"byte_offset": 1272,
|
||||
"initial_value": 524288
|
||||
},
|
||||
{
|
||||
"name": "TexCtl1_2",
|
||||
"byte_offset": 1276,
|
||||
"initial_value": 524288
|
||||
},
|
||||
{
|
||||
"name": "TexCtl1_3",
|
||||
"byte_offset": 1280,
|
||||
"initial_value": 524288
|
||||
},
|
||||
{
|
||||
"name": "TexCtl2_0",
|
||||
"byte_offset": 1284,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexCtl2_1",
|
||||
"byte_offset": 1288,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexFilter0",
|
||||
"byte_offset": 1292,
|
||||
"initial_value": 16850944
|
||||
},
|
||||
{
|
||||
"name": "TexFilter1",
|
||||
"byte_offset": 1296,
|
||||
"initial_value": 16850944
|
||||
},
|
||||
{
|
||||
"name": "TexFilter2",
|
||||
"byte_offset": 1300,
|
||||
"initial_value": 16850944
|
||||
},
|
||||
{
|
||||
"name": "TexFilter3",
|
||||
"byte_offset": 1304,
|
||||
"initial_value": 16850944
|
||||
},
|
||||
{
|
||||
"name": "TexFormat0",
|
||||
"byte_offset": 1308,
|
||||
"initial_value": 67000
|
||||
},
|
||||
{
|
||||
"name": "TexFormat1",
|
||||
"byte_offset": 1312,
|
||||
"initial_value": 67000
|
||||
},
|
||||
{
|
||||
"name": "TexFormat2",
|
||||
"byte_offset": 1316,
|
||||
"initial_value": 67000
|
||||
},
|
||||
{
|
||||
"name": "TexFormat3",
|
||||
"byte_offset": 1320,
|
||||
"initial_value": 67000
|
||||
},
|
||||
{
|
||||
"name": "TexImageRect0",
|
||||
"byte_offset": 1324,
|
||||
"initial_value": 524296
|
||||
},
|
||||
{
|
||||
"name": "TexImageRect1",
|
||||
"byte_offset": 1328,
|
||||
"initial_value": 524296
|
||||
},
|
||||
{
|
||||
"name": "TexImageRect2",
|
||||
"byte_offset": 1332,
|
||||
"initial_value": 524296
|
||||
},
|
||||
{
|
||||
"name": "TexImageRect3",
|
||||
"byte_offset": 1336,
|
||||
"initial_value": 524296
|
||||
},
|
||||
{
|
||||
"name": "TexOffset0",
|
||||
"byte_offset": 1340,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexOffset1",
|
||||
"byte_offset": 1344,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexOffset2",
|
||||
"byte_offset": 1348,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexOffset3",
|
||||
"byte_offset": 1352,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexPalette0",
|
||||
"byte_offset": 1356,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexPalette1",
|
||||
"byte_offset": 1360,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexPalette2",
|
||||
"byte_offset": 1364,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "TexPalette3",
|
||||
"byte_offset": 1368,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX0",
|
||||
"byte_offset": 1372,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX1",
|
||||
"byte_offset": 1376,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX2",
|
||||
"byte_offset": 1380,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX3",
|
||||
"byte_offset": 1384,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX4",
|
||||
"byte_offset": 1388,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX5",
|
||||
"byte_offset": 1392,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX6",
|
||||
"byte_offset": 1396,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipX7",
|
||||
"byte_offset": 1400,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY0",
|
||||
"byte_offset": 1404,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY1",
|
||||
"byte_offset": 1408,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY2",
|
||||
"byte_offset": 1412,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY3",
|
||||
"byte_offset": 1416,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY4",
|
||||
"byte_offset": 1420,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY5",
|
||||
"byte_offset": 1424,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY6",
|
||||
"byte_offset": 1428,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "WindowClipY7",
|
||||
"byte_offset": 1432,
|
||||
"initial_value": 134152192
|
||||
},
|
||||
{
|
||||
"name": "ZCompressOcclude",
|
||||
"byte_offset": 1436,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ZStencilClearValue",
|
||||
"byte_offset": 1440,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ZClipMax",
|
||||
"byte_offset": 1444,
|
||||
"initial_value": 1266679807
|
||||
},
|
||||
{
|
||||
"name": "ZClipMin",
|
||||
"byte_offset": 1448,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ContextDmaA",
|
||||
"byte_offset": 1452,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ContextDmaB",
|
||||
"byte_offset": 1456,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ContextDmaVtxA",
|
||||
"byte_offset": 1460,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ContextDmaVtxB",
|
||||
"byte_offset": 1464,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ZOffsetBias",
|
||||
"byte_offset": 1468,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ZOffsetFactor",
|
||||
"byte_offset": 1472,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Eyevec0",
|
||||
"byte_offset": 1476,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Eyevec1",
|
||||
"byte_offset": 1480,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Eyevec2",
|
||||
"byte_offset": 1484,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Shadow",
|
||||
"byte_offset": 1488,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FdData",
|
||||
"byte_offset": 1492,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FdSwatch",
|
||||
"byte_offset": 1496,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "FdExtras",
|
||||
"byte_offset": 1500,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Emission0",
|
||||
"byte_offset": 1504,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Emission1",
|
||||
"byte_offset": 1508,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Emission2",
|
||||
"byte_offset": 1512,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SceneAmb0",
|
||||
"byte_offset": 1516,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SceneAmb1",
|
||||
"byte_offset": 1520,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "SceneAmb2",
|
||||
"byte_offset": 1524,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "ContextDmaGetState",
|
||||
"byte_offset": 1528,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BeginPatch0",
|
||||
"byte_offset": 1532,
|
||||
"initial_value": 1
|
||||
},
|
||||
{
|
||||
"name": "BeginPatch1",
|
||||
"byte_offset": 1536,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BeginPatch2",
|
||||
"byte_offset": 1540,
|
||||
"initial_value": 16384
|
||||
},
|
||||
{
|
||||
"name": "BeginPatch3",
|
||||
"byte_offset": 1544,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BeginCurve",
|
||||
"byte_offset": 1548,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "BeginTrans0",
|
||||
"byte_offset": 1552,
|
||||
"initial_value": 1
|
||||
},
|
||||
{
|
||||
"name": "BeginTrans1",
|
||||
"byte_offset": 1556,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Csv0_D",
|
||||
"byte_offset": 1560,
|
||||
"initial_value": 262144
|
||||
},
|
||||
{
|
||||
"name": "Csv0_C",
|
||||
"byte_offset": 1564,
|
||||
"initial_value": 65536
|
||||
},
|
||||
{
|
||||
"name": "Csv1_B",
|
||||
"byte_offset": 1568,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "Csv1_A",
|
||||
"byte_offset": 1572,
|
||||
"initial_value": 0
|
||||
},
|
||||
{
|
||||
"name": "CheopsOffset",
|
||||
"byte_offset": 1576,
|
||||
"initial_value": 0
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"status": "primary_source_correlated_declarations; original-target kernel type records not recovered",
|
||||
"source_repository": "XboxDev/nxdk",
|
||||
"source_commit": "58427c078b4ccb0121f359b6b6c536b3b2914976",
|
||||
"source_path": "lib/xboxkrnl/xboxkrnl.h",
|
||||
"entries": [
|
||||
{
|
||||
"name": "HalRegisterShutdownNotification",
|
||||
"return_type": "VOID",
|
||||
"parameters": [
|
||||
"PHAL_SHUTDOWN_REGISTRATION",
|
||||
"BOOLEAN"
|
||||
],
|
||||
"owner": "kernel_interrupt.h"
|
||||
},
|
||||
{
|
||||
"name": "KeDisconnectInterrupt",
|
||||
"return_type": "BOOLEAN",
|
||||
"parameters": [
|
||||
"PKINTERRUPT"
|
||||
],
|
||||
"owner": "kernel_interrupt.h",
|
||||
"correction": "initial new draft said void; corrected before final full replay. Caller discards the result and retains exact code."
|
||||
},
|
||||
{
|
||||
"name": "AvGetSavedDataAddress",
|
||||
"return_type": "PVOID",
|
||||
"parameters": [],
|
||||
"owner": "display_internal.h"
|
||||
},
|
||||
{
|
||||
"name": "KeStallExecutionProcessor",
|
||||
"return_type": "VOID",
|
||||
"parameters": [
|
||||
"ULONG"
|
||||
],
|
||||
"owner": "kernel_gpu.h"
|
||||
}
|
||||
],
|
||||
"calling_convention": "32-bit stdcall, corroborated by original relocation import names and caller stack use",
|
||||
"original_pdb_limit": "The diagnostic module scan did not recover named import type records; its failures/empty result are retained. NXDK corroboration is not claimed as the original SDK.",
|
||||
"proprietary_assets_modified": false
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
# Continuation 006 — initialization, interrupts, clear and mode selection
|
||||
|
||||
## Result and baseline
|
||||
|
||||
The full checkpoint005 source was freshly replayed before authoring: all14
|
||||
stages passed, 289 code sections /31,643 padded bytes /29,642 NOP-excluded bytes.
|
||||
The untouched baseline source, objects, report and replay log are retained in
|
||||
`evidence/wave6_baseline/`. Current-source final results are under evidence/wave6;
|
||||
old checkpoint reports elsewhere are history, not fresh verification.
|
||||
|
||||
Nine newly reconstructed functions account for3,288 padded bytes. All are
|
||||
same-name passes through the unchanged strict comparator, with no new private
|
||||
pair, relocation alias, SDK wrapper, approximate score or standalone-data credit.
|
||||
The resulting code census is298 sections /34,931 padded /32,895 NOP-excluded bytes.
|
||||
|
||||
## Reviewed source and actual target interface
|
||||
|
||||
| Function | Code bytes | Interface/behavior evidence and limitations |
|
||||
|---|---:|---|
|
||||
| InitHardware |312|Original PDB member signature, record addresses, DPC/event initialization, interrupt setup, shutdown registration, gamma arrays and GPIO setup. No later AGP-configuration additions were copied.|
|
||||
| IsFlipPending |16|Actual indexed queue member and PDB signature, not an unimplemented constant stub.|
|
||||
| Isr |192|Original static stdcall callback, hardware status/enable reads, field GPIO, flip condition, callback queuing and return.|
|
||||
| VBlank |320|Original queue state, gamma updates, read counter, hardware acknowledgement loop, event/callback dispatch and CRTC-index restoration.|
|
||||
| SoftwareMethod |560|Original un-packed method IDs0x300–0x324, callbacks, actual16-byte fixup record and hardware register programming. Its jump table is part of its code contribution.|
|
||||
| ServiceFifoInterrupt |400|Original FIFO exception masks, retry countdown, diagnostics, GET recovery and resume sequence.|
|
||||
| D3DDevice_Clear |976|Original color/depth format cases, viewport clipping, sample scaling, ordered NV2A writes and format restore. Includes associated jump tables.|
|
||||
| GetTableForCurrentAvInfo |121|Original191-entry table, region/pack selection and generic-pack fallback.|
|
||||
| SetVideoMode |391|Original zero-versus-explicit refresh choice, flag/size/mode filtering, gamma reset and deferred mode state.|
|
||||
|
||||
Each new procedure is authenticated against a unique original-PDB record,
|
||||
return/parameter types, calling convention and length, then compared again
|
||||
against the current candidate. Clear and the table lookup are ordinary stdcall
|
||||
functions; Isr is a static stdcall member. Other new CMiniport methods are
|
||||
thiscall. Do not infer kernel-import return types solely from callers that
|
||||
ignore them: primary kernel headers corroborate those declarations separately.
|
||||
|
||||
### Kernel records and owner headers
|
||||
|
||||
The original PDB establishes112-byte KINTERRUPT,28-byte KDPC,16-byte event,
|
||||
16-byte dispatcher header,16-byte shutdown registration and16-byte TIME_FIELDS.
|
||||
The required event/shutdown/time fields are decoded. Interrupt/DPC internals stay
|
||||
opaque and are only passed to real kernel routines. Replacing former byte spans
|
||||
with their true owner-record types preserves every affected CDevice/CMiniport
|
||||
size and offset; all local consumers are rebuilt in the final replay.
|
||||
|
||||
KeInitializeEvent is reconstructed as the genuine historical kernel header
|
||||
macro, supported by cross-build NT header evidence and the original inline
|
||||
instruction sequence. The simple field assignments set Type, Size, SignalState
|
||||
and the empty wait list; Absolute/Inserted are not invented stores. All current
|
||||
macro arguments are stable addresses/constants. This is not a fake emission
|
||||
anchor or a new force-inline annotation. The first ordinary helper form was
|
||||
nonexact and is retained as an experiment. It is not counted.
|
||||
|
||||
EnableInterrupts now lives as an ordinary inline in its genuine hardware owner
|
||||
header next to DisableInterrupts. The standalone original entry still matches,
|
||||
as do all previous Dpc consumers. The original GPIO polarity is inverse bit5;
|
||||
using its real unsigned port value closes Isr and VBlank. Intrinsics _inp/_outp
|
||||
express actual I/O operations, not assembly written to steer other registers.
|
||||
|
||||
### Interrupt graph and retained nonexact work
|
||||
|
||||
SoftwareMethod uses actual method enums and true callback/fixup interfaces.
|
||||
The isolated FIFO debug-register reads access the real fixed MMIO lvalues;
|
||||
no volatile local or synthetic load was introduced. They reflect the original
|
||||
hardware macro access, unlike a discarded helper-return temporary. This closes
|
||||
the FIFO body while preserving its bounds/retry checks.
|
||||
|
||||
ServiceGrInterrupt is complete but NONEXACT: current target/candidate sizes are
|
||||
368 bytes, with a this-pointer versus method-variable register-lifetime
|
||||
permutation. Its real fatal diagnostic uses the compiler's __debugbreak intrinsic
|
||||
(the original target has INT3); no new inline assembly or raw-byte emission was
|
||||
introduced. A separate probe confirmed compiler support. This body gets zero
|
||||
credit and was parked instead of pursuing arbitrary register constraints.
|
||||
|
||||
LoadEngines is complete with equal315-byte normalized instruction sections, but
|
||||
the authentic month-table owner is not reconciled with the portable target's
|
||||
private data anchor. It remains NONEXACT and uncredited. No new relocation alias
|
||||
or address-shaped source variable was used. Its original month-index and timing
|
||||
arithmetic are visible; later corrected calendar formulas are not substituted.
|
||||
|
||||
### Clear and presentation modes
|
||||
|
||||
Clear matched on its first complete compiled draft. The two floating-depth
|
||||
conversions read the high32bits of an IEEE754 double using memcpy through byte
|
||||
views, avoiding an unrelated DWORD lvalue. Packing shifts use unsigned values.
|
||||
Valid use assumes finite depth in[0,1], valid allocated rectangles, supported
|
||||
surface formats and device-range coordinates. Original early return when depth
|
||||
flags become empty occurs before swizzled-format restoration; this quirk is
|
||||
preserved and commented, not represented as an improved driver.
|
||||
|
||||
GetTableForCurrentAvInfo matched initially. SetVideoMode initially differed
|
||||
at384 bytes. The original separates unspecified refresh0 from explicit50/60Hz;
|
||||
spelling that genuine outer conditional produced the391-byte exact body. There
|
||||
is no compiler assumption, new optimization flag or fabricated caller. Table
|
||||
selection assumes supported AV information and a valid mode as checked by its
|
||||
real caller graph; it is not a new defensive parser for arbitrary AV values.
|
||||
|
||||
The original191 display records and count are recovered as typed configuration
|
||||
data (2296 bytes). Their contents are verified independently against compiled
|
||||
owned ranges and do not inflate code progress. MPMode now has4/4 matching code
|
||||
sections. It is NOT a whole-object admission: the target data contributions are
|
||||
COMDATs, the current constant section combines them with an alignment gap, and
|
||||
three unused SDK encoding tables are emitted. These metadata/ownership holds
|
||||
are recorded rather than hidden by making the target agree with the candidate.
|
||||
|
||||
## Rules and provenance
|
||||
|
||||
Latest fetched rules blob:6bee6e0c6b67e3799527fbf96880e11bc59b6508, unchanged
|
||||
from005. New definitions have separate-line parameters and explicit returns.
|
||||
Declarations stay in genuine kernel/display/hardware/math owner headers. Driver
|
||||
SDK types are appropriate; unrelated Halo tag/object macros are not introduced.
|
||||
Mode/depth/software-method switches use the actual SDK or method enumerations.
|
||||
|
||||
No new assembly, force-inline/no-inline/optimization pragma, volatile local,
|
||||
raw instruction output, target patch or comparator change. The two inherited
|
||||
BSF/SFENCE helpers remain disclosed. Genuine MMIO/shared-state volatiles and
|
||||
port intrinsics do not establish concurrent hardware correctness by themselves.
|
||||
The source-policy scan is limited lexical evidence, NOT all-house-rule approval
|
||||
for the inherited reconstruction or an exhaustive undefined-behavior proof.
|
||||
|
||||
Attributed RXDK code remains GPL-3.0-or-later and is not automatically compatible
|
||||
with canonical CC0 publication. The reference-provenance JSON distinguishes
|
||||
later SDK corroboration from original PDB/byte evidence; no later flip queues,
|
||||
modern callback shims or packed-method formats were substituted for January.
|
||||
|
||||
## Verification and recovery
|
||||
|
||||
Final replay recompiles all22 current C++ units from the47-file source/header/
|
||||
initializer tree, binds source and generated ABI-overlay hashes to every output,
|
||||
runs the unchanged comparator,44 comparator unit tests and the inherited full
|
||||
mutation suite, and preserves all289 starting fingerprints plus earlier
|
||||
protected checkpoint populations. The new verifier authenticates new PDB
|
||||
procedures, selected record layouts and the independent display-data ranges.
|
||||
Read final evidence/wave6/clean_replay.json for actual completed stages/status.
|
||||
|
||||
No supplied Halo image, extracted original function or GPU program is executed.
|
||||
No new bespoke runtime harness is claimed. Event/interrupt concurrency,
|
||||
hardware progress, callbacks, malformed inputs, driver linking and graphics
|
||||
behavior remain untested. Native-csplit download attempts failed; this is NOT a
|
||||
passed native-split comparison. Whole-object data/BSS/COMDAT/extra-section and
|
||||
actual canonical consumer review remain open. Canonical/GitHub/Bink/Claude
|
||||
worktrees are untouched; isolated counts are not added to the canonical ledger.
|
||||
|
||||
The new005-to006 source patch and full/repair-relative alternatives are replayed
|
||||
independently. Apply only the one matching the starting source tree; source
|
||||
patches alone do not replace the SDK ABI overlay and build scripts. Failed
|
||||
source/interface trials, probes and authoring scripts are retained under
|
||||
experiments/wave6; scripts/reproduce.py is the portable replay entry point.
|
||||
|
||||
Next: finish the GR handler and table ownership only with new interface/source
|
||||
evidence, or move into presentation/lazy-state/device-initialization families.
|
||||
Preserve all298 body proofs; do not generate fake callers for missing helpers.
|
||||
|
||||
## Packaging repair
|
||||
|
||||
The first in-place full replay passed source compilation and comparison gates
|
||||
but failed git apply because the newly generated full patch omitted new-file
|
||||
mode headers. The patch format was corrected; no production source, target,
|
||||
compiler setting or comparator was changed to pass the patch check. All three
|
||||
patches then recovered the current47-file source set. That failed attempt is
|
||||
retained in evidence/wave6/failed_replay_attempt1, separate from the final
|
||||
fresh-extraction verification.
|
||||
@@ -0,0 +1,360 @@
|
||||
/* Resource lifetime logic adapted from RXDK-Libs (2026 Team Resurgent).
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Target-specific behavior and layouts are checked against January COFF/PDB.
|
||||
* See libs/d3d8/PROVENANCE.md. */
|
||||
#include "device_layout.h"
|
||||
#include "resource_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#include "kernel_memory.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
struct PrivateDataNode
|
||||
{
|
||||
PrivateDataNode *pNext;
|
||||
void *pObject;
|
||||
GUID guid;
|
||||
DWORD size;
|
||||
DWORD flags;
|
||||
union
|
||||
{
|
||||
IUnknown *pUnknown;
|
||||
BYTE Data[1];
|
||||
};
|
||||
};
|
||||
typedef char PrivateDataNode_size_check[sizeof(PrivateDataNode) == 36 ? 1 : -1];
|
||||
static PrivateDataNode *g_pPrivateData;
|
||||
|
||||
PrivateDataNode *WINAPI FindPrivateData(
|
||||
void *object,
|
||||
REFGUID guid)
|
||||
{
|
||||
PrivateDataNode *node = g_pPrivateData;
|
||||
/* BUG (original): the January function never advances this list cursor.
|
||||
* A nonmatching nonempty head loops forever (target branches +0x18/+0x28).
|
||||
* A corrected implementation would advance node = node->pNext, but that
|
||||
* change belongs in a separately labeled nonmatching build. */
|
||||
while (node != NULL)
|
||||
{
|
||||
if (node->pObject == object && node->guid == guid)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void WINAPI CleanPrivateData(
|
||||
void *object)
|
||||
{
|
||||
PrivateDataNode *node = g_pPrivateData;
|
||||
PrivateDataNode **previous = &g_pPrivateData;
|
||||
while (node != NULL)
|
||||
{
|
||||
if (node->pObject == object)
|
||||
{
|
||||
*previous = node->pNext;
|
||||
if (node->flags & D3DSPD_IUNKNOWN)
|
||||
{
|
||||
node->pUnknown->Release();
|
||||
}
|
||||
LocalFree(node);
|
||||
node = *previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous = &node->pNext;
|
||||
node = node->pNext;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
BYTE *WINAPI GetDataFromResource(
|
||||
D3DResource *resource)
|
||||
{
|
||||
return (BYTE *)(resource->Data | 0x80000000UL);
|
||||
}
|
||||
void WINAPI DestroyResource(
|
||||
D3DResource *resource)
|
||||
{
|
||||
DWORD type = resource->Common & D3DCOMMON_TYPE_MASK;
|
||||
if (type != D3DCOMMON_TYPE_SURFACE || resource->Common & D3DSURFACE_OWNSMEMORY)
|
||||
{
|
||||
BlockOnResource(resource);
|
||||
}
|
||||
CleanPrivateData(resource);
|
||||
if (type == D3DCOMMON_TYPE_SURFACE)
|
||||
{
|
||||
if (resource->Common & D3DSURFACE_OWNSMEMORY)
|
||||
{
|
||||
MmFreeContiguousMemory((void *)(resource->Data | 0x80000000UL));
|
||||
}
|
||||
}
|
||||
else if (type == D3DCOMMON_TYPE_PUSHBUFFER)
|
||||
{
|
||||
if (!(resource->Common & D3DPUSHBUFFER_RUN_USING_CPU_COPY))
|
||||
{
|
||||
MmFreeContiguousMemory((void *)resource->Data);
|
||||
}
|
||||
}
|
||||
else if (type != D3DCOMMON_TYPE_INDEXBUFFER && type != D3DCOMMON_TYPE_FIXUP)
|
||||
{
|
||||
MmFreeContiguousMemory((void *)(resource->Data | 0x80000000UL));
|
||||
}
|
||||
LocalFree(resource);
|
||||
return;
|
||||
}
|
||||
BOOL WINAPI IsResourceSetInDevice(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if (resource->Common & D3DCOMMON_INTREFCOUNT_MASK)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if ((resource->Common & D3DCOMMON_TYPE_MASK) == D3DCOMMON_TYPE_SURFACE)
|
||||
{
|
||||
D3DBaseTexture *parent = PixelJar::GetParent(resource);
|
||||
if (parent && (parent->Common & D3DCOMMON_INTREFCOUNT_MASK))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
void WINAPI InternalAddRef(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if ((resource->Common & D3DCOMMON_TYPE_MASK) == D3DCOMMON_TYPE_SURFACE)
|
||||
{
|
||||
if (!(resource->Common & D3DCOMMON_INTREFCOUNT_MASK))
|
||||
{
|
||||
D3DBaseTexture *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
InternalAddRef(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
resource->Common += 1 << D3DCOMMON_INTREFCOUNT_SHIFT;
|
||||
return;
|
||||
}
|
||||
void WINAPI InternalReleaseSurface(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if ((resource->Common & D3DCOMMON_INTREFCOUNT_MASK) == (1 << D3DCOMMON_INTREFCOUNT_SHIFT))
|
||||
{
|
||||
D3DBaseTexture *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
InternalRelease(parent);
|
||||
}
|
||||
if (!(resource->Common & D3DCOMMON_REFCOUNT_MASK))
|
||||
{
|
||||
DestroyResource(resource);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resource->Common -= 1 << D3DCOMMON_INTREFCOUNT_SHIFT;
|
||||
return;
|
||||
}
|
||||
__inline DWORD CDevice::GpuTime(
|
||||
void)
|
||||
{
|
||||
return *m_pGpuTime;
|
||||
}
|
||||
__inline DWORD CDevice::Age(
|
||||
DWORD time)
|
||||
{
|
||||
return m_CpuTime - time;
|
||||
}
|
||||
__inline BOOL CDevice::IsTimePending(
|
||||
DWORD time)
|
||||
{
|
||||
return Age(time) < Age(GpuTime());
|
||||
}
|
||||
}
|
||||
using namespace D3D;
|
||||
ULONG WINAPI D3DResource_AddRef(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if (!(resource->Common & D3DCOMMON_REFCOUNT_MASK))
|
||||
{
|
||||
if ((resource->Common & D3DCOMMON_TYPE_MASK) == D3DCOMMON_TYPE_SURFACE)
|
||||
{
|
||||
D3DBaseTexture *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
parent->AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ++resource->Common & D3DCOMMON_REFCOUNT_MASK;
|
||||
}
|
||||
ULONG WINAPI D3DResource_Release(
|
||||
D3DResource *resource)
|
||||
{
|
||||
if ((resource->Common & D3DCOMMON_REFCOUNT_MASK) == 1)
|
||||
{
|
||||
if ((resource->Common & D3DCOMMON_TYPE_MASK) == D3DCOMMON_TYPE_SURFACE)
|
||||
{
|
||||
D3DBaseTexture *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
parent->Release();
|
||||
}
|
||||
}
|
||||
if (!(resource->Common & D3DCOMMON_INTREFCOUNT_MASK))
|
||||
{
|
||||
DestroyResource(resource);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return --resource->Common & D3DCOMMON_REFCOUNT_MASK;
|
||||
}
|
||||
D3DRESOURCETYPE WINAPI D3DResource_GetType(
|
||||
D3DResource *resource)
|
||||
{
|
||||
DWORD type = resource->Common & D3DCOMMON_TYPE_MASK;
|
||||
switch (type)
|
||||
{
|
||||
case D3DCOMMON_TYPE_VERTEXBUFFER: return D3DRTYPE_VERTEXBUFFER;
|
||||
case D3DCOMMON_TYPE_INDEXBUFFER: return D3DRTYPE_INDEXBUFFER;
|
||||
case D3DCOMMON_TYPE_PUSHBUFFER: return D3DRTYPE_PUSHBUFFER;
|
||||
case D3DCOMMON_TYPE_FIXUP: return D3DRTYPE_FIXUP;
|
||||
case D3DCOMMON_TYPE_PALETTE: return D3DRTYPE_PALETTE;
|
||||
case D3DCOMMON_TYPE_TEXTURE:
|
||||
{
|
||||
DWORD format = ((D3DBaseTexture *)resource)->Format;
|
||||
if (format & D3DFORMAT_CUBEMAP) return D3DRTYPE_CUBETEXTURE;
|
||||
else if ((format & D3DFORMAT_DIMENSION_MASK) > (2 << D3DFORMAT_DIMENSION_SHIFT)) return D3DRTYPE_VOLUMETEXTURE;
|
||||
else return D3DRTYPE_TEXTURE;
|
||||
}
|
||||
case D3DCOMMON_TYPE_SURFACE:
|
||||
{
|
||||
DWORD format = ((D3DPixelContainer *)resource)->Format;
|
||||
if ((format & D3DFORMAT_DIMENSION_MASK) > (2 << D3DFORMAT_DIMENSION_SHIFT)) return D3DRTYPE_VOLUME;
|
||||
else return D3DRTYPE_SURFACE;
|
||||
}
|
||||
default: return (D3DRESOURCETYPE)0;
|
||||
}
|
||||
}
|
||||
BOOL WINAPI D3DResource_IsBusy(
|
||||
D3DResource *resource)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3DResource *parent = PixelJar::GetParent(resource);
|
||||
if (parent)
|
||||
{
|
||||
if (IsResourceSetInDevice(resource)) return TRUE;
|
||||
resource = parent;
|
||||
}
|
||||
if (IsResourceSetInDevice(resource)) return TRUE;
|
||||
BOOL result = resource->Lock != 0 && device->IsTimePending(resource->Lock);
|
||||
if (!result) resource->Lock = 0;
|
||||
return result;
|
||||
}
|
||||
void WINAPI D3DResource_GetDevice(
|
||||
D3DResource *resource,
|
||||
D3DDevice **device)
|
||||
{
|
||||
*device = g_pDevice;
|
||||
g_pDevice->AddRef();
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DResource_Register(
|
||||
D3DResource *resource,
|
||||
void *base)
|
||||
{
|
||||
DWORD type = resource->Common & D3DCOMMON_TYPE_MASK;
|
||||
void *memory = (BYTE *)base + resource->Data;
|
||||
if (type == D3DCOMMON_TYPE_PUSHBUFFER)
|
||||
{
|
||||
resource->Data = (DWORD)memory;
|
||||
}
|
||||
else
|
||||
{
|
||||
resource->Data = (DWORD)memory & 0x03ffffffUL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DResource_BlockUntilNotBusy(
|
||||
D3DResource *resource)
|
||||
{
|
||||
BlockOnResource(resource);
|
||||
return;
|
||||
}
|
||||
HRESULT WINAPI D3DResource_SetPrivateData(
|
||||
D3DResource *resource,
|
||||
REFGUID guid,
|
||||
const void *data,
|
||||
DWORD size,
|
||||
DWORD flags)
|
||||
{
|
||||
PrivateDataNode *node = FindPrivateData(resource, guid);
|
||||
if (node) D3DResource_FreePrivateData(resource, guid);
|
||||
node = (PrivateDataNode *)LocalAlloc(LMEM_ZEROINIT, sizeof(PrivateDataNode) + size);
|
||||
if (!node) return E_OUTOFMEMORY;
|
||||
node->size = size;
|
||||
node->guid = guid;
|
||||
node->flags = flags;
|
||||
node->pObject = resource;
|
||||
if (flags & D3DSPD_IUNKNOWN)
|
||||
{
|
||||
node->pUnknown = (IUnknown *)data;
|
||||
node->pUnknown->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((BYTE *)node + offsetof(PrivateDataNode, Data), data, size);
|
||||
}
|
||||
node->pNext = g_pPrivateData;
|
||||
g_pPrivateData = node;
|
||||
return D3D_OK;
|
||||
}
|
||||
HRESULT WINAPI D3DResource_GetPrivateData(
|
||||
D3DResource *resource,
|
||||
REFGUID guid,
|
||||
void *data,
|
||||
DWORD *size)
|
||||
{
|
||||
PrivateDataNode *node = FindPrivateData(resource, guid);
|
||||
if (!node) return D3DERR_NOTFOUND;
|
||||
if (!data)
|
||||
{
|
||||
*size = node->size;
|
||||
return D3D_OK;
|
||||
}
|
||||
if (*size < node->size)
|
||||
{
|
||||
*size = node->size;
|
||||
return D3DERR_MOREDATA;
|
||||
}
|
||||
*size = node->size;
|
||||
if (node->flags & D3DSPD_IUNKNOWN)
|
||||
{
|
||||
*(IUnknown **)data = node->pUnknown;
|
||||
node->pUnknown->AddRef();
|
||||
return D3D_OK;
|
||||
}
|
||||
memcpy(data, (BYTE *)node + offsetof(PrivateDataNode, Data), node->size);
|
||||
return D3D_OK;
|
||||
}
|
||||
void WINAPI D3DResource_FreePrivateData(
|
||||
D3DResource *resource,
|
||||
REFGUID guid)
|
||||
{
|
||||
PrivateDataNode *node = g_pPrivateData;
|
||||
PrivateDataNode **previous = &g_pPrivateData;
|
||||
while (node)
|
||||
{
|
||||
if (node->pObject == resource && node->guid == guid)
|
||||
{
|
||||
*previous = node->pNext;
|
||||
if (node->flags & D3DSPD_IUNKNOWN) node->pUnknown->Release();
|
||||
LocalFree(node);
|
||||
return;
|
||||
}
|
||||
previous = &node->pNext;
|
||||
node = node->pNext;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef D3D8_RESOURCE_INTERNAL_H
|
||||
#define D3D8_RESOURCE_INTERNAL_H
|
||||
#include <xtl.h>
|
||||
namespace D3D
|
||||
{
|
||||
BOOL WINAPI IsResourceSetInDevice(
|
||||
D3DResource *resource);
|
||||
void WINAPI BlockOnResource(
|
||||
D3DResource *resource);
|
||||
BYTE *WINAPI GetDataFromResource(
|
||||
D3DResource *resource);
|
||||
void WINAPI InternalAddRef(
|
||||
D3DResource *resource);
|
||||
void WINAPI InternalReleaseSurface(
|
||||
D3DResource *resource);
|
||||
void WINAPI DestroyResource(
|
||||
D3DResource *resource);
|
||||
__inline void WINAPI InternalRelease(
|
||||
D3DResource *resource)
|
||||
{
|
||||
resource->Common -= 1 << D3DCOMMON_INTREFCOUNT_SHIFT;
|
||||
if (!(resource->Common & (D3DCOMMON_REFCOUNT_MASK | D3DCOMMON_INTREFCOUNT_MASK)))
|
||||
{
|
||||
DestroyResource(resource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,617 @@
|
||||
/* State programming adapted from RXDK-Libs, 2026 Team Resurgent.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Older target method numbers/state layout are proved by its disassembly.
|
||||
*/
|
||||
#include "push_internal.h"
|
||||
#include "pixeljar.h"
|
||||
#include "state_internal.h"
|
||||
#include "math_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
DWORD *__fastcall CommonSetControl0(
|
||||
CDevice *device,
|
||||
DWORD *push)
|
||||
{
|
||||
DWORD control = 0x00100001;
|
||||
if (D3D__RenderState[D3DRS_YUVENABLE]) control |= 0x10000000;
|
||||
if (D3D__RenderState[D3DRS_ZENABLE] == D3DZB_USEW) control |= 0x00010000;
|
||||
if (device->m_pZBuffer)
|
||||
{
|
||||
D3DFORMAT format = PixelJar::GetFormat(device->m_pZBuffer);
|
||||
if (format == D3DFMT_F16 || format == D3DFMT_F24S8 ||
|
||||
format == D3DFMT_LIN_F16 || format == D3DFMT_LIN_F24S8)
|
||||
{
|
||||
control |= 0x1000;
|
||||
}
|
||||
}
|
||||
Push1(push, 0x290, control);
|
||||
return push + 2;
|
||||
}
|
||||
DWORD *__fastcall CommonSetOccludeZStencilEn(
|
||||
CDevice *device,
|
||||
DWORD *push)
|
||||
{
|
||||
DWORD control = 0;
|
||||
if (D3D__RenderState[D3DRS_STENCILCULLENABLE])
|
||||
{
|
||||
control |= 2;
|
||||
}
|
||||
if (D3D__RenderState[D3DRS_OCCLUSIONCULLENABLE] &&
|
||||
(!D3D__RenderState[D3DRS_STENCILENABLE] ||
|
||||
D3D__RenderState[D3DRS_STENCILFAIL] == D3DSTENCILOP_KEEP))
|
||||
{
|
||||
control |= 1;
|
||||
}
|
||||
Push1(push, 0x1d84, control);
|
||||
return push + 2;
|
||||
}
|
||||
void __fastcall CommonSetAntiAliasingControl(
|
||||
CDevice *device)
|
||||
{
|
||||
CommonSetPassthroughProgram(device);
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetViewport(device, push);
|
||||
Push1(push, 0x1d7c,
|
||||
(D3D__RenderState[D3DRS_MULTISAMPLEMASK] << 16) |
|
||||
(D3D__RenderState[D3DRS_MULTISAMPLEANTIALIAS] & 0xf));
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void __fastcall CommonSetDebugRegisters(
|
||||
void)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->m_Miniport.m_DebugRegister[5] &= ~8UL;
|
||||
if (D3D__RenderState[D3DRS_DONOTCULLUNCOMPRESSED])
|
||||
{
|
||||
device->m_Miniport.m_DebugRegister[5] |= 8;
|
||||
}
|
||||
device->m_Miniport.m_DebugRegister[6] &= ~0x18100000UL;
|
||||
if (D3D__RenderState[D3DRS_ROPZCMPALWAYSREAD])
|
||||
{
|
||||
device->m_Miniport.m_DebugRegister[6] |= 0x100000;
|
||||
}
|
||||
if (D3D__RenderState[D3DRS_ROPZREAD])
|
||||
{
|
||||
device->m_Miniport.m_DebugRegister[6] |= 0x08000000;
|
||||
}
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_WAIT_FOR_IDLE, 0);
|
||||
Push2(push + 2, 0x1d8c, 0x400094, device->m_Miniport.m_DebugRegister[5]);
|
||||
Push1(push + 5, NV097_NO_OPERATION, 0x320);
|
||||
Push2(push + 7, 0x1d8c, 0x400b80, device->m_Miniport.m_DebugRegister[6]);
|
||||
Push1(push + 10, NV097_NO_OPERATION, 0x320);
|
||||
device->EndPush(push + 12);
|
||||
return;
|
||||
}
|
||||
}
|
||||
using namespace D3D;
|
||||
void __fastcall D3D::CommonSetSurfaceFormat(
|
||||
CDevice *device)
|
||||
{
|
||||
float xScale = 1.0f;
|
||||
float yScale = 1.0f;
|
||||
DWORD antiAlias = 0;
|
||||
D3DSurface *surface = device->m_pRenderTarget;
|
||||
if (surface == &device->m_FrameBufferSurfaces[0])
|
||||
{
|
||||
DWORD sampling = D3D__RenderState[D3DRS_MULTISAMPLETYPE];
|
||||
if (sampling & 0x3000)
|
||||
{
|
||||
xScale = (float)((sampling >> 4) & 15);
|
||||
yScale = (float)(sampling & 15);
|
||||
if (sampling & 0x1000)
|
||||
{
|
||||
xScale *= 0.5f;
|
||||
antiAlias = 0x1000;
|
||||
if (yScale > 1.0f)
|
||||
{
|
||||
yScale *= 0.5f;
|
||||
antiAlias = 0x2000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
float scale = min(xScale, yScale);
|
||||
device->m_SuperSampleScaleX = xScale;
|
||||
device->m_SuperSampleScaleY = yScale;
|
||||
if (scale != device->m_SuperSampleScale)
|
||||
{
|
||||
device->m_SuperSampleScale = scale;
|
||||
device->m_SuperSampleLODBias = g_LODBias2x[Round(scale * 2.0f) - 2];
|
||||
device->m_DirtyFlags |= 1;
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_LINEWIDTH,
|
||||
D3D__RenderState[D3DRS_LINEWIDTH]);
|
||||
}
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x208, PixelJar::GetSurfaceFormat(surface, device->m_pZBuffer) | antiAlias);
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI D3DDevice_SetRenderState_MultiSampleType(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_MULTISAMPLETYPE] = value;
|
||||
D3DDevice_SetRenderTarget(device->m_pRenderTarget, device->m_pZBuffer);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_PSTextureModes(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->m_PSShaderStageProgram = value;
|
||||
device->m_DirtyFlags |= 0x400;
|
||||
D3D__RenderState[D3DRS_PSTEXTUREMODES] = value;
|
||||
return;
|
||||
}
|
||||
void __fastcall D3DDevice_SetRenderState_Deferred(
|
||||
D3DRENDERSTATETYPE state,
|
||||
DWORD value)
|
||||
{
|
||||
g_Device.m_DirtyFlags |= g_DirtyFromRenderState[state - D3DRS_SIMPLE_MAX];
|
||||
D3D__RenderState[state] = value;
|
||||
return;
|
||||
}
|
||||
void __fastcall D3DDevice_SetTextureState_Deferred(
|
||||
DWORD stage,
|
||||
D3DTEXTURESTAGESTATETYPE state,
|
||||
DWORD value)
|
||||
{
|
||||
g_Device.m_DirtyFlags |= g_DirtyFromTextureState[state];
|
||||
D3D__TextureState[stage][state] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderStateNotInline(
|
||||
D3DRENDERSTATETYPE state,
|
||||
DWORD value)
|
||||
{
|
||||
if (state < D3DRS_SIMPLE_MAX)
|
||||
{
|
||||
D3DDevice_SetRenderState_Simple(D3DSIMPLERENDERSTATEENCODE[state], value);
|
||||
D3D__RenderState[state] = value;
|
||||
}
|
||||
else if (state < D3DRS_DEFERRED_MAX)
|
||||
{
|
||||
D3DDevice_SetRenderState_Deferred(state, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ComplexRenderStateFunctionTable[state - D3DRS_DEFERRED_MAX](value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_EdgeAntiAlias(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push2(push, NV097_SET_LINE_SMOOTH_ENABLE, value, value);
|
||||
device->EndPush(push + 3);
|
||||
D3D__RenderState[D3DRS_EDGEANTIALIAS] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_ShadowFunc(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_SET_SHADOW_DEPTH_FUNC, value - D3DCMP_NEVER);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_SHADOWFUNC] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_FogColor(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_SET_FOG_COLOR, SwapRgb(value));
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_FOGCOLOR] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_CullMode(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
if (value == D3DCULL_NONE)
|
||||
{
|
||||
Push1(push, NV097_SET_CULL_FACE_ENABLE, FALSE);
|
||||
device->EndPush(push + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Push1(push, NV097_SET_CULL_FACE_ENABLE, TRUE);
|
||||
DWORD cullFace = value == D3D__RenderState[D3DRS_FRONTFACE] ?
|
||||
NV097_SET_CULL_FACE_V_FRONT : NV097_SET_CULL_FACE_V_BACK;
|
||||
Push1(push + 2, NV097_SET_CULL_FACE, cullFace);
|
||||
device->EndPush(push + 4);
|
||||
}
|
||||
D3D__RenderState[D3DRS_CULLMODE] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_FrontFace(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_SET_FRONT_FACE, value);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_FRONTFACE] = value;
|
||||
D3DDevice_SetRenderState_CullMode(D3D__RenderState[D3DRS_CULLMODE]);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_NormalizeNormals(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_SET_NORMALIZATION_ENABLE, value);
|
||||
device->EndPush(push + 2);
|
||||
device->m_DirtyFlags |= 2;
|
||||
D3D__RenderState[D3DRS_NORMALIZENORMALS] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_TextureFactor(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (!device->m_pPixelShader)
|
||||
{
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push++, NV097_SET_COMBINER_FACTOR0, 16);
|
||||
for (DWORD i = 0; i < 16; i++)
|
||||
{
|
||||
*push++ = value;
|
||||
}
|
||||
device->EndPush(push);
|
||||
}
|
||||
D3D__RenderState[D3DRS_TEXTUREFACTOR] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_Dxt1NoiseEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
BOOL noiseEnable = FALSE;
|
||||
if (PixelJar::GetBitsPerPixel(device->m_pRenderTarget) == 32)
|
||||
{
|
||||
noiseEnable = value;
|
||||
}
|
||||
if (noiseEnable != (device->m_StateFlags & 1))
|
||||
{
|
||||
device->m_StateFlags ^= 1;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, NV097_WAIT_FOR_IDLE, 0);
|
||||
/* January uses separate semaphore-offset argument and software method. */
|
||||
Push1(push + 2, 0x1d8c, noiseEnable);
|
||||
Push1(push + 4, NV097_NO_OPERATION, 0x31c);
|
||||
device->EndPush(push + 6);
|
||||
}
|
||||
D3D__RenderState[D3DRS_DXT1NOISEENABLE] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_YuvEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_YUVENABLE] = value;
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetControl0(device, push);
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_OcclusionCullEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_OCCLUSIONCULLENABLE] = value;
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetOccludeZStencilEn(device, push);
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_StencilCullEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_STENCILCULLENABLE] = value;
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetOccludeZStencilEn(device, push);
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_RopZCmpAlwaysRead(
|
||||
DWORD value)
|
||||
{
|
||||
D3D__RenderState[D3DRS_ROPZCMPALWAYSREAD] = value;
|
||||
CommonSetDebugRegisters();
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_RopZRead(
|
||||
DWORD value)
|
||||
{
|
||||
D3D__RenderState[D3DRS_ROPZREAD] = value;
|
||||
CommonSetDebugRegisters();
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_DoNotCullUncompressed(
|
||||
DWORD value)
|
||||
{
|
||||
D3D__RenderState[D3DRS_DONOTCULLUNCOMPRESSED] = value;
|
||||
CommonSetDebugRegisters();
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI D3DDevice_SetRenderState_LogicOp(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
if (value == D3DLOGICOP_NONE)
|
||||
{
|
||||
Push1(push, 0x17bc, FALSE);
|
||||
push += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Push2(push, 0x17bc, TRUE, value);
|
||||
push += 3;
|
||||
}
|
||||
device->EndPush(push);
|
||||
D3D__RenderState[D3DRS_LOGICOP] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_FillMode(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
DWORD back = D3D__RenderState[D3DRS_TWOSIDEDLIGHTING] ?
|
||||
D3D__RenderState[D3DRS_BACKFILLMODE] : value;
|
||||
Push2(push, 0x38c, value, back);
|
||||
device->EndPush(push + 3);
|
||||
D3D__RenderState[D3DRS_FILLMODE] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_BackFillMode(
|
||||
DWORD value)
|
||||
{
|
||||
D3D__RenderState[D3DRS_BACKFILLMODE] = value;
|
||||
D3DDevice_SetRenderState_FillMode(D3D__RenderState[D3DRS_FILLMODE]);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_TwoSidedLighting(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->m_DirtyFlags |= 0x20;
|
||||
D3D__RenderState[D3DRS_TWOSIDEDLIGHTING] = value;
|
||||
D3DDevice_SetRenderState_FillMode(D3D__RenderState[D3DRS_FILLMODE]);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_VertexBlend(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
device->m_DirtyFlags |= 2;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x328, value);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_VERTEXBLEND] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_ZEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x30c, value != D3DZB_FALSE && device->m_pZBuffer != NULL);
|
||||
device->EndPush(push + 2);
|
||||
DWORD previous = D3D__RenderState[D3DRS_ZENABLE];
|
||||
D3D__RenderState[D3DRS_ZENABLE] = value;
|
||||
if (previous == D3DZB_USEW || value == D3DZB_USEW)
|
||||
{
|
||||
UpdateProjectionViewportTransform();
|
||||
CommonSetPassthroughProgram(device);
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetControl0(device, push);
|
||||
device->EndPush(push);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_StencilEnable(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetOccludeZStencilEn(device, push);
|
||||
Push1(push, 0x32c, value && device->m_pZBuffer != NULL);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_STENCILENABLE] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_StencilFail(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
push = CommonSetOccludeZStencilEn(device, push);
|
||||
Push1(push, 0x370, value);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_STENCILFAIL] = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_MultiSampleAntiAlias(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_MULTISAMPLEANTIALIAS] = value;
|
||||
CommonSetAntiAliasingControl(device);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_MultiSampleMask(
|
||||
DWORD value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__RenderState[D3DRS_MULTISAMPLEMASK] = value;
|
||||
CommonSetAntiAliasingControl(device);
|
||||
return;
|
||||
}
|
||||
|
||||
void WINAPI D3DDevice_SetRenderState_LineWidth(
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
float width;
|
||||
memcpy(&width, &Value, sizeof(width));
|
||||
DWORD scaled = FloatToLong(width * device->m_SuperSampleScale * 8.0f + 0.5f);
|
||||
if (scaled > 511) { scaled = 511; }
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x380, scaled);
|
||||
device->EndPush(push + 2);
|
||||
D3D__RenderState[D3DRS_LINEWIDTH] = Value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetRenderState_ZBias(
|
||||
DWORD Value)
|
||||
{
|
||||
BOOL enabled = Value != 0;
|
||||
float bias = -(float)Value;
|
||||
float scale = bias * 0.25f;
|
||||
DWORD payload;
|
||||
memcpy(&payload, &scale, sizeof(payload));
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_POLYGONOFFSETZSLOPESCALE, payload);
|
||||
memcpy(&payload, &bias, sizeof(payload));
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_POLYGONOFFSETZOFFSET, payload);
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_POINTOFFSETENABLE, enabled);
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_WIREFRAMEOFFSETENABLE, enabled);
|
||||
D3DDevice_SetRenderStateNotInline(D3DRS_SOLIDOFFSETENABLE, enabled);
|
||||
D3D__RenderState[D3DRS_ZBIAS] = Value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetTextureState_TexCoordIndex(
|
||||
DWORD Stage,
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
D3D__TextureState[Stage][D3DTSS_TEXCOORDINDEX] = Value;
|
||||
DWORD needsInverse = FALSE;
|
||||
DWORD mode;
|
||||
switch (Value & 0xffff0000)
|
||||
{
|
||||
case D3DTSS_TCI_PASSTHRU:
|
||||
device->m_DirtyFlags |= 0x180;
|
||||
mode = 0;
|
||||
break;
|
||||
case D3DTSS_TCI_CAMERASPACENORMAL:
|
||||
needsInverse = TRUE;
|
||||
mode = 0x8511;
|
||||
break;
|
||||
case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
|
||||
needsInverse = TRUE;
|
||||
mode = 0x8512;
|
||||
break;
|
||||
case D3DTSS_TCI_CAMERASPACEPOSITION:
|
||||
mode = 0x2400;
|
||||
break;
|
||||
case D3DTSS_TCI_OBJECT:
|
||||
mode = 0x2401;
|
||||
break;
|
||||
default:
|
||||
/* Target default, including sphere mapping. */
|
||||
needsInverse = TRUE;
|
||||
mode = 0x2402;
|
||||
break;
|
||||
}
|
||||
if (!device->m_TexGenInverseNeeded && needsInverse) { device->m_DirtyFlags |= 2; }
|
||||
device->m_TexGenInverseNeeded &= ~(1 << Stage);
|
||||
device->m_TexGenInverseNeeded |= needsInverse << Stage;
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x3c0 + Stage * 16, 3);
|
||||
push[1] = mode;
|
||||
push[2] = mode;
|
||||
push[3] = mode;
|
||||
device->EndPush(push + 4);
|
||||
device->m_DirtyFlags |= 0x194;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetTextureState_BumpEnv(
|
||||
DWORD Stage,
|
||||
D3DTEXTURESTAGESTATETYPE Type,
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD unit = device->m_pPixelShader ? Stage : Stage + 1;
|
||||
if (unit & 3)
|
||||
{
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1b28 + unit * 64 + 4 * (Type - D3DTSS_BUMPENVMAT00), Value);
|
||||
device->EndPush(push + 2);
|
||||
}
|
||||
D3D__TextureState[Stage][Type] = Value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetTextureState_BorderColor(
|
||||
DWORD Stage,
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1b24 + Stage * 64, Value);
|
||||
device->EndPush(push + 2);
|
||||
D3D__TextureState[Stage][D3DTSS_BORDERCOLOR] = Value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetTextureState_ColorKeyColor(
|
||||
DWORD Stage,
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0xae0 + Stage * 4, Value);
|
||||
device->EndPush(push + 2);
|
||||
D3D__TextureState[Stage][D3DTSS_COLORKEYCOLOR] = Value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetTextureStageStateNotInline(
|
||||
DWORD Stage,
|
||||
D3DTEXTURESTAGESTATETYPE Type,
|
||||
DWORD Value)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (Type < D3DTSS_DEFERRED_MAX)
|
||||
{
|
||||
DWORD dirty = g_DirtyFromTextureState[Type];
|
||||
D3D__TextureState[Stage][Type] = Value;
|
||||
device->m_DirtyFlags |= dirty;
|
||||
}
|
||||
else if (Type == D3DTSS_TEXCOORDINDEX) { D3DDevice_SetTextureState_TexCoordIndex(Stage, Value); }
|
||||
else if (Type == D3DTSS_BORDERCOLOR) { D3DDevice_SetTextureState_BorderColor(Stage, Value); }
|
||||
else if (Type == D3DTSS_COLORKEYCOLOR) { D3DDevice_SetTextureState_ColorKeyColor(Stage, Value); }
|
||||
else if (Type >= D3DTSS_BUMPENVMAT00 && Type <= D3DTSS_BUMPENVLOFFSET)
|
||||
{ D3DDevice_SetTextureState_BumpEnv(Stage, Type, Value); }
|
||||
return;
|
||||
}
|
||||
namespace D3D
|
||||
{
|
||||
DWORD *__fastcall CommonSetTextureBumpEnv(
|
||||
CDevice *device,
|
||||
DWORD *push)
|
||||
{
|
||||
DWORD stage = device->m_pPixelShader ? 1 : 0;
|
||||
for (DWORD unit = 1; unit <= 3; unit++)
|
||||
{
|
||||
PushCount(push, 0x1b28 + unit * 64, 6);
|
||||
memcpy(push + 1, &D3D__TextureState[stage][D3DTSS_BUMPENVMAT00], 6 * sizeof(DWORD));
|
||||
push += 7;
|
||||
stage++;
|
||||
}
|
||||
return push;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef D3D8_STATE_INTERNAL_H
|
||||
#define D3D8_STATE_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
extern const DWORD g_DirtyFromRenderState[];
|
||||
extern const DWORD g_TransformDirtyTable[];
|
||||
extern const float g_LODBias2x[];
|
||||
extern DWORD g_DirtyFromTextureState[];
|
||||
typedef void (WINAPI *SetComplexRenderStateFunction)(
|
||||
DWORD value);
|
||||
extern const SetComplexRenderStateFunction g_ComplexRenderStateFunctionTable[];
|
||||
DWORD *__fastcall CommonSetControl0(
|
||||
CDevice *device,
|
||||
DWORD *push);
|
||||
DWORD *__fastcall CommonSetOccludeZStencilEn(
|
||||
CDevice *device,
|
||||
DWORD *push);
|
||||
void WINAPI UpdateProjectionViewportTransform(
|
||||
void);
|
||||
void __fastcall CommonSetSurfaceFormat(
|
||||
CDevice *device);
|
||||
void __fastcall CommonSetPassthroughProgram(
|
||||
CDevice *device);
|
||||
DWORD *__fastcall CommonSetViewport(
|
||||
CDevice *device,
|
||||
DWORD *push);
|
||||
void __fastcall CommonSetDebugRegisters(
|
||||
void);
|
||||
DWORD *__fastcall CommonSetTextureBumpEnv(
|
||||
CDevice *device,
|
||||
DWORD *push);
|
||||
void __fastcall CommonSetAntiAliasingControl(
|
||||
CDevice *device);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
#include "pixeljar.h"
|
||||
#include "resource_internal.h"
|
||||
#include "kernel_memory.h"
|
||||
#include "surface_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
void WINAPI D3DSurface_GetDesc(
|
||||
D3DSurface *surface,
|
||||
D3DSURFACE_DESC *desc)
|
||||
{
|
||||
D3D::PixelJar::Get2DSurfaceDesc(surface, 0, desc);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DSurface_LockRect(
|
||||
D3DSurface *surface,
|
||||
D3DLOCKED_RECT *locked,
|
||||
const RECT *rect,
|
||||
DWORD flags)
|
||||
{
|
||||
D3D::PixelJar::Lock2DSurface(surface, D3DCUBEMAP_FACE_POSITIVE_X, 0, locked, rect, flags);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DVolume_GetDesc(
|
||||
D3DVolume *volume,
|
||||
D3DVOLUME_DESC *desc)
|
||||
{
|
||||
D3D::PixelJar::Get3DSurfaceDesc(volume, 0, desc);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DVolume_LockBox(
|
||||
D3DVolume *volume,
|
||||
D3DLOCKED_BOX *locked,
|
||||
const D3DBOX *box,
|
||||
DWORD flags)
|
||||
{
|
||||
D3D::PixelJar::Lock3DSurface(volume, 0, locked, box, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
HRESULT WINAPI CreateSurfaceOfTexture(
|
||||
DWORD format,
|
||||
DWORD size,
|
||||
D3DBaseTexture *texture,
|
||||
void *data,
|
||||
D3DSurface **result)
|
||||
{
|
||||
D3DSurface *surface = (D3DSurface *)LocalAlloc(LMEM_ZEROINIT, sizeof(*surface));
|
||||
if (!surface) return E_OUTOFMEMORY;
|
||||
surface->Data = (DWORD)data & 0x03ffffff;
|
||||
surface->Common = 0x01050001;
|
||||
surface->Format = format;
|
||||
surface->Size = size;
|
||||
surface->Parent = texture;
|
||||
surface->Lock = 0;
|
||||
texture->AddRef();
|
||||
*result = surface;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI CreateVolumeOfTexture(
|
||||
DWORD format,
|
||||
D3DBaseTexture *texture,
|
||||
void *data,
|
||||
D3DVolume **result)
|
||||
{
|
||||
D3DVolume *volume = (D3DVolume *)LocalAlloc(LMEM_ZEROINIT, sizeof(*volume));
|
||||
if (!volume) return E_OUTOFMEMORY;
|
||||
volume->Data = (DWORD)data & 0x03ffffff;
|
||||
volume->Common = 0x01050001;
|
||||
volume->Format = format;
|
||||
volume->Size = 0;
|
||||
volume->Parent = texture;
|
||||
volume->Lock = 0;
|
||||
texture->AddRef();
|
||||
*result = volume;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT WINAPI CreateStandAloneSurface(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
D3DFORMAT format,
|
||||
bool renderTarget,
|
||||
D3DSurface **result)
|
||||
{
|
||||
DWORD encodedFormat, encodedSize;
|
||||
DWORD allocationSize = PixelJar::EncodeFormat(width, height, 1, 1, format, 0,
|
||||
renderTarget, false, false, &encodedFormat, &encodedSize);
|
||||
D3DSurface *surface = (D3DSurface *)LocalAlloc(LMEM_ZEROINIT, sizeof(*surface));
|
||||
if (!surface) return E_OUTOFMEMORY;
|
||||
void *memory = MmAllocateContiguousMemoryEx(allocationSize, 0, 0x03ffb000, 64,
|
||||
PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (!memory)
|
||||
{
|
||||
LocalFree(surface);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
surface->Data = (DWORD)memory & 0x03ffffff;
|
||||
surface->Common = 0x81050001;
|
||||
surface->Format = encodedFormat;
|
||||
surface->Size = encodedSize;
|
||||
surface->Parent = NULL;
|
||||
surface->Lock = 0;
|
||||
*result = surface;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI InitializeSurface(
|
||||
D3DSurface *surface,
|
||||
DWORD format,
|
||||
DWORD size,
|
||||
void *memory)
|
||||
{
|
||||
surface->Data = (DWORD)memory & 0x03ffffff;
|
||||
surface->Size = size;
|
||||
surface->Common = D3DCOMMON_D3DCREATED | D3DCOMMON_TYPE_SURFACE | 1;
|
||||
surface->Format = format;
|
||||
surface->Parent = NULL;
|
||||
surface->Lock = 0;
|
||||
return;
|
||||
}
|
||||
HRESULT WINAPI CreateSurfaceWithContiguousHeader(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
D3DFORMAT format,
|
||||
D3DSurface **result)
|
||||
{
|
||||
DWORD encodedFormat, encodedSize;
|
||||
DWORD allocationSize = PixelJar::EncodeFormat(width, height, 1, 1,
|
||||
format, 0, true, false, false, &encodedFormat, &encodedSize);
|
||||
/* The original allocation reserves an aligned 64-byte header prefix.
|
||||
* The returned surface occupies only the first sizeof(D3DSurface) bytes. */
|
||||
D3DSurface *surface = (D3DSurface *)MmAllocateContiguousMemoryEx(
|
||||
allocationSize + SURFACE_CONTIGUOUS_HEADER_BYTES, 0, 0x03ffb000,
|
||||
D3DSURFACE_ALIGNMENT, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (!surface)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
void *pixels = (BYTE *)surface + SURFACE_CONTIGUOUS_HEADER_BYTES;
|
||||
surface->Common = D3DCOMMON_D3DCREATED | D3DCOMMON_TYPE_SURFACE | D3DSURFACE_OWNSMEMORY | 1;
|
||||
surface->Data = (DWORD)pixels & 0x03ffffff;
|
||||
surface->Format = encodedFormat;
|
||||
surface->Size = encodedSize;
|
||||
surface->Parent = NULL;
|
||||
surface->Lock = 0;
|
||||
*result = surface;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
HRESULT WINAPI D3DSurface_GetContainer(
|
||||
D3DSurface *surface,
|
||||
D3DBaseTexture **container)
|
||||
{
|
||||
*container = surface->Parent;
|
||||
if (*container)
|
||||
{
|
||||
(*container)->AddRef();
|
||||
}
|
||||
return *container ? S_OK : E_FAIL;
|
||||
}
|
||||
HRESULT WINAPI D3DVolume_GetContainer(
|
||||
D3DVolume *volume,
|
||||
D3DBaseTexture **container)
|
||||
{
|
||||
*container = volume->Parent;
|
||||
if (*container)
|
||||
{
|
||||
(*container)->AddRef();
|
||||
}
|
||||
return *container ? S_OK : E_FAIL;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HALO_D3D8_SURFACE_INTERNAL_H
|
||||
#define HALO_D3D8_SURFACE_INTERNAL_H
|
||||
#include <xtl.h>
|
||||
namespace D3D
|
||||
{
|
||||
/* The January contiguous allocation reserves a 64-byte prefix for its header. */
|
||||
enum { SURFACE_CONTIGUOUS_HEADER_BYTES = 64 };
|
||||
void WINAPI InitializeSurface(
|
||||
D3DSurface *surface,
|
||||
DWORD format,
|
||||
DWORD size,
|
||||
void *memory);
|
||||
HRESULT WINAPI CreateSurfaceWithContiguousHeader(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
D3DFORMAT format,
|
||||
D3DSurface **result);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "pixeljar.h"
|
||||
#include "kernel_memory.h"
|
||||
#pragma code_seg("D3D")
|
||||
void WINAPI D3DTexture_GetLevelDesc(
|
||||
D3DTexture *texture,
|
||||
UINT level,
|
||||
D3DSURFACE_DESC *desc)
|
||||
{
|
||||
D3D::PixelJar::Get2DSurfaceDesc(texture, level, desc);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DCubeTexture_GetLevelDesc(
|
||||
D3DCubeTexture *texture,
|
||||
UINT level,
|
||||
D3DSURFACE_DESC *desc)
|
||||
{
|
||||
D3D::PixelJar::Get2DSurfaceDesc(texture, level, desc);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DVolumeTexture_GetLevelDesc(
|
||||
D3DVolumeTexture *texture,
|
||||
UINT level,
|
||||
D3DVOLUME_DESC *desc)
|
||||
{
|
||||
D3D::PixelJar::Get3DSurfaceDesc(texture, level, desc);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DTexture_LockRect(
|
||||
D3DTexture *texture,
|
||||
UINT level,
|
||||
D3DLOCKED_RECT *locked,
|
||||
const RECT *rect,
|
||||
DWORD flags)
|
||||
{
|
||||
D3D::PixelJar::Lock2DSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, level, locked, rect, flags);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DCubeTexture_LockRect(
|
||||
D3DCubeTexture *texture,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
D3DLOCKED_RECT *locked,
|
||||
const RECT *rect,
|
||||
DWORD flags)
|
||||
{
|
||||
D3D::PixelJar::Lock2DSurface(texture, face, level, locked, rect, flags);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DVolumeTexture_LockBox(
|
||||
D3DVolumeTexture *texture,
|
||||
UINT level,
|
||||
D3DLOCKED_BOX *locked,
|
||||
const D3DBOX *box,
|
||||
DWORD flags)
|
||||
{
|
||||
D3D::PixelJar::Lock3DSurface(texture, level, locked, box, flags);
|
||||
return;
|
||||
}
|
||||
DWORD WINAPI D3DBaseTexture_GetLevelCount(
|
||||
D3DBaseTexture *texture)
|
||||
{
|
||||
return (texture->Format & D3DFORMAT_MIPMAP_MASK) >> D3DFORMAT_MIPMAP_SHIFT;
|
||||
}
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
HRESULT WINAPI CreateTexture(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
DWORD depth,
|
||||
DWORD levels,
|
||||
DWORD usage,
|
||||
D3DFORMAT format,
|
||||
bool cubeMap,
|
||||
bool volume,
|
||||
D3DBaseTexture **result)
|
||||
{
|
||||
DWORD encodedFormat, encodedSize;
|
||||
*result = NULL;
|
||||
DWORD allocationSize = PixelJar::EncodeFormat(width, height, depth, levels,
|
||||
format, 0, true, cubeMap, volume, &encodedFormat, &encodedSize);
|
||||
if (usage & 0x10000) encodedFormat &= ~D3DFORMAT_BORDERSOURCE_COLOR;
|
||||
D3DBaseTexture *texture = (D3DBaseTexture *)LocalAlloc(LMEM_ZEROINIT, sizeof(*texture));
|
||||
if (!texture) return E_OUTOFMEMORY;
|
||||
void *memory = MmAllocateContiguousMemoryEx(allocationSize, 0, 0x03ffb000,
|
||||
128, PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (!memory)
|
||||
{
|
||||
LocalFree(texture);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
texture->Data = (DWORD)memory & 0x03ffffff;
|
||||
texture->Common = 0x01040001;
|
||||
texture->Format = encodedFormat;
|
||||
texture->Size = encodedSize;
|
||||
texture->Lock = 0;
|
||||
*result = texture;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DTexture_GetSurfaceLevel(
|
||||
D3DTexture *texture,
|
||||
UINT level,
|
||||
D3DSurface **surface)
|
||||
{
|
||||
BYTE *data;
|
||||
DWORD rowPitch, slicePitch, format, size;
|
||||
D3D::PixelJar::FindSurfaceWithinTexture(texture, D3DCUBEMAP_FACE_POSITIVE_X,
|
||||
level, &data, &rowPitch, &slicePitch, &format, &size);
|
||||
return D3D::CreateSurfaceOfTexture(format, size, texture, data, surface);
|
||||
}
|
||||
HRESULT WINAPI D3DCubeTexture_GetCubeMapSurface(
|
||||
D3DCubeTexture *texture,
|
||||
D3DCUBEMAP_FACES face,
|
||||
UINT level,
|
||||
D3DSurface **surface)
|
||||
{
|
||||
BYTE *data;
|
||||
DWORD rowPitch, slicePitch, format, size;
|
||||
D3D::PixelJar::FindSurfaceWithinTexture(texture, face, level,
|
||||
&data, &rowPitch, &slicePitch, &format, &size);
|
||||
return D3D::CreateSurfaceOfTexture(format, size, texture, data, surface);
|
||||
}
|
||||
HRESULT WINAPI D3DVolumeTexture_GetVolumeLevel(
|
||||
D3DVolumeTexture *texture,
|
||||
UINT level,
|
||||
D3DVolume **volume)
|
||||
{
|
||||
BYTE *data;
|
||||
DWORD rowPitch, slicePitch, format, size;
|
||||
D3D::PixelJar::FindSurfaceWithinTexture(texture, D3DCUBEMAP_FACE_POSITIVE_X,
|
||||
level, &data, &rowPitch, &slicePitch, &format, &size);
|
||||
return D3D::CreateVolumeOfTexture(format, texture, data, volume);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef D3D8_VISIBILITY_INTERNAL_H
|
||||
#define D3D8_VISIBILITY_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
/* January report payload: timestamp @0, samples @8, completion status @12.
|
||||
* The GPU writes the status asynchronously; this qualifier describes actual
|
||||
* device-shared storage rather than an instruction-selection workaround. */
|
||||
struct VisibilityReport
|
||||
{
|
||||
unsigned __int64 TimeStamp;
|
||||
DWORD Samples;
|
||||
volatile DWORD Status;
|
||||
};
|
||||
typedef char visibility_report_size[sizeof(VisibilityReport) == 16 ? 1 : -1];
|
||||
BYTE *WINAPI GetVisibilityAddress(
|
||||
DWORD index);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,730 @@
|
||||
/* Shader parsing/loading adapted from RXDK-Libs (2026 Team Resurgent).
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* January layouts, field encodings and behavior remain target-authoritative.
|
||||
* See libs/d3d8/PROVENANCE.md. */
|
||||
#include "vshader_internal.h"
|
||||
#include "push_internal.h"
|
||||
#include "resource_internal.h"
|
||||
#include "state_internal.h"
|
||||
#include "math_internal.h"
|
||||
#pragma code_seg("D3D")
|
||||
namespace D3D
|
||||
{
|
||||
void WINAPI InitializeVertexShaderFromFvf(
|
||||
VertexShader *shader,
|
||||
DWORD fvf)
|
||||
{
|
||||
DWORD offset, position, i, weights;
|
||||
memset(shader, 0, sizeof(*shader));
|
||||
for (i = 0; i < 16; i++) shader->Slot[i].SizeAndType = SIZEANDTYPE_DISABLED;
|
||||
position = fvf & D3DFVF_POSITION_MASK;
|
||||
offset = 0;
|
||||
if (position == D3DFVF_XYZRHW)
|
||||
{
|
||||
shader->Flags |= VERTEXSHADER_PASSTHROUGH;
|
||||
shader->Slot[SLOT_POSITION].SizeAndType = 0x42;
|
||||
offset = 4 * sizeof(float);
|
||||
}
|
||||
else if (position != 0)
|
||||
{
|
||||
shader->Slot[SLOT_POSITION].SizeAndType = 0x32;
|
||||
offset = 3 * sizeof(float);
|
||||
if (position >= D3DFVF_XYZB1)
|
||||
{
|
||||
weights = ((position - D3DFVF_XYZB1) >> 1) + 1;
|
||||
shader->Slot[SLOT_WEIGHT].Offset = offset;
|
||||
shader->Slot[SLOT_WEIGHT].SizeAndType = (weights << 4) | 2;
|
||||
offset += weights * sizeof(float);
|
||||
}
|
||||
}
|
||||
if (fvf & D3DFVF_NORMAL)
|
||||
{
|
||||
shader->Slot[SLOT_NORMAL].Offset = offset;
|
||||
shader->Slot[SLOT_NORMAL].SizeAndType = 0x32;
|
||||
offset += 3 * sizeof(float);
|
||||
}
|
||||
if (fvf & D3DFVF_DIFFUSE)
|
||||
{
|
||||
shader->Slot[SLOT_DIFFUSE].Offset = offset;
|
||||
shader->Slot[SLOT_DIFFUSE].SizeAndType = 0x40;
|
||||
shader->Flags |= VERTEXSHADER_HASDIFFUSE;
|
||||
offset += sizeof(DWORD);
|
||||
}
|
||||
if (fvf & D3DFVF_SPECULAR)
|
||||
{
|
||||
shader->Slot[SLOT_SPECULAR].Offset = offset;
|
||||
shader->Slot[SLOT_SPECULAR].SizeAndType = 0x40;
|
||||
shader->Flags |= VERTEXSHADER_HASSPECULAR;
|
||||
offset += sizeof(DWORD);
|
||||
}
|
||||
DWORD numTextures = (fvf >> 8) & 15;
|
||||
DWORD textureFormats = fvf >> 16;
|
||||
shader->TextureCount = numTextures;
|
||||
for (i = 0; i < numTextures; i++, textureFormats >>= 2)
|
||||
{
|
||||
DWORD count = g_TextureCount[textureFormats & 3];
|
||||
DWORD size = count << 2;
|
||||
shader->Slot[i + SLOT_TEXTURE0].Offset = offset;
|
||||
shader->Slot[i + SLOT_TEXTURE0].SizeAndType = (count << 4) | 2;
|
||||
shader->Dimensionality[i] = count;
|
||||
offset += size;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI ValidateFVF(
|
||||
DWORD fvf)
|
||||
{
|
||||
/* This linked non-debug library has no emitted validation body. */
|
||||
return;
|
||||
}
|
||||
void WINAPI ShadowVertexShaderState(
|
||||
VertexShader *shader,
|
||||
DWORD address)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *program = shader->ProgramAndConstants;
|
||||
DWORD *slots = &device->m_VertexShaderProgramSlots[address][0];
|
||||
/* Valid command streams select the constant destination before loading it. */
|
||||
float *constants;
|
||||
DWORD constantSlot;
|
||||
do
|
||||
{
|
||||
DWORD method = *program++;
|
||||
DWORD count = method >> 18;
|
||||
if (count == 1)
|
||||
{
|
||||
constantSlot = *program;
|
||||
constants = &device->m_VertexShaderConstants[constantSlot][0];
|
||||
}
|
||||
else if ((method & 0xffff) == 0x0b00)
|
||||
{
|
||||
memcpy(slots, program, count * sizeof(DWORD));
|
||||
slots += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(constants, program, count * sizeof(DWORD));
|
||||
constants += count;
|
||||
}
|
||||
program += count;
|
||||
} while (*program != 0);
|
||||
return;
|
||||
}
|
||||
DWORD *WINAPI ParseProgram(
|
||||
DWORD *destination,
|
||||
const DWORD *program,
|
||||
DWORD dwords)
|
||||
{
|
||||
DWORD batch;
|
||||
DWORD *push = destination;
|
||||
do
|
||||
{
|
||||
batch = min(dwords, 4 * VSHADER_BATCH_LIMIT);
|
||||
*push = 0x0b00 + (batch << 18);
|
||||
memcpy(push + 1, program, batch * sizeof(DWORD));
|
||||
program += batch;
|
||||
push += batch + 1;
|
||||
} while ((dwords -= batch) != 0);
|
||||
return push;
|
||||
}
|
||||
void WINAPI ParseDeclarationStream(
|
||||
VertexShader *shader,
|
||||
const DWORD *declaration,
|
||||
BOOL fixedFunction)
|
||||
{
|
||||
DWORD offset = 0;
|
||||
DWORD streamIndex = 0;
|
||||
DWORD count, sizeAndType, dimensionality, reg, slot;
|
||||
while (TRUE)
|
||||
{
|
||||
DWORD token = *declaration++;
|
||||
switch (token & D3DVSD_TOKENTYPEMASK)
|
||||
{
|
||||
case D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_STREAM):
|
||||
streamIndex = token & 15;
|
||||
offset = 0;
|
||||
break;
|
||||
case D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_STREAMDATA):
|
||||
if (token & 0x10000000)
|
||||
{
|
||||
count = (token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT;
|
||||
if (!(token & 0x08000000)) count <<= 2;
|
||||
offset += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeAndType = (token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT;
|
||||
reg = (token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT;
|
||||
slot = reg;
|
||||
if (fixedFunction && reg >= D3DVSDE_TEXCOORD0 && reg <= D3DVSDE_TEXCOORD3)
|
||||
{
|
||||
slot = reg + SLOT_TEXTURE0 - D3DVSDE_TEXCOORD0;
|
||||
}
|
||||
shader->Slot[slot].StreamIndex = streamIndex;
|
||||
shader->Slot[slot].Offset = offset;
|
||||
shader->Slot[slot].Flags = 0;
|
||||
shader->Slot[slot].SizeAndType = sizeAndType;
|
||||
if (fixedFunction)
|
||||
{
|
||||
if (reg >= D3DVSDE_TEXCOORD0 && reg <= D3DVSDE_TEXCOORD3)
|
||||
{
|
||||
dimensionality = (sizeAndType & 0xf0) >> 4;
|
||||
if (dimensionality == 7) dimensionality = 4;
|
||||
else if (sizeAndType == D3DVSDT_NORMPACKED3) dimensionality = 3;
|
||||
shader->TextureCount++;
|
||||
shader->Dimensionality[reg - D3DVSDE_TEXCOORD0] = dimensionality;
|
||||
}
|
||||
if (reg == D3DVSDE_DIFFUSE) shader->Flags |= VERTEXSHADER_HASDIFFUSE;
|
||||
if (reg == D3DVSDE_SPECULAR) shader->Flags |= VERTEXSHADER_HASSPECULAR;
|
||||
if (reg == D3DVSDE_BACKDIFFUSE) shader->Flags |= VERTEXSHADER_HASBACKDIFFUSE;
|
||||
if (reg == D3DVSDE_BACKSPECULAR) shader->Flags |= VERTEXSHADER_HASBACKSPECULAR;
|
||||
}
|
||||
offset += g_UnitsOfElement[(sizeAndType & 0xf0) >> 4] * g_BytesPerUnit[sizeAndType & 15];
|
||||
}
|
||||
break;
|
||||
case D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_TESSELLATOR):
|
||||
reg = (token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT;
|
||||
shader->Slot[reg].Offset = 0;
|
||||
shader->Slot[reg].StreamIndex = 0;
|
||||
shader->Slot[reg].SizeAndType = SIZEANDTYPE_DISABLED;
|
||||
shader->Slot[reg].Source = (BYTE)((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT);
|
||||
if (token & 0x10000000) shader->Slot[reg].Flags = 2;
|
||||
else shader->Slot[reg].Flags = 1;
|
||||
break;
|
||||
case D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_CONSTMEM):
|
||||
count = (token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT;
|
||||
declaration += 4 * count;
|
||||
break;
|
||||
case D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_END):
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DWORD WINAPI ParseDeclarationConstants(
|
||||
const DWORD *declaration,
|
||||
DWORD *start)
|
||||
{
|
||||
DWORD *push = start;
|
||||
DWORD oldAddress = 0xdeadbeef;
|
||||
DWORD size = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
DWORD token = *declaration++;
|
||||
if (token == D3DVSD_END()) return size;
|
||||
if ((token & D3DVSD_TOKENTYPEMASK) == D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_CONSTMEM))
|
||||
{
|
||||
DWORD count = (token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT;
|
||||
DWORD address = (token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT;
|
||||
if (address != oldAddress + 1)
|
||||
{
|
||||
if (push)
|
||||
{
|
||||
push[0] = 0x00041ea4;
|
||||
push[1] = address;
|
||||
push += 2;
|
||||
}
|
||||
size += 2;
|
||||
}
|
||||
oldAddress = address;
|
||||
DWORD batch;
|
||||
do
|
||||
{
|
||||
batch = min(count, VSHADER_BATCH_LIMIT);
|
||||
if (push)
|
||||
{
|
||||
*push++ = 0x0b80 + ((4 * batch) << 18);
|
||||
memcpy(push, declaration, 4 * batch * sizeof(DWORD));
|
||||
push += 4 * batch;
|
||||
}
|
||||
declaration += 4 * batch;
|
||||
size += 4 * batch + 1;
|
||||
address += batch;
|
||||
} while ((count -= batch) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
void WINAPI RestoreVertexShaders(
|
||||
const DWORD *program,
|
||||
DWORD dwords)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1e9c, 0);
|
||||
push = ParseProgram(push + 2, program, dwords);
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
}
|
||||
using namespace D3D;
|
||||
void WINAPI D3DDevice_SetStreamSource(
|
||||
UINT stream,
|
||||
D3DVertexBuffer *buffer,
|
||||
UINT stride)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (buffer) InternalAddRef(buffer);
|
||||
if (g_Stream[stream].pVertexBuffer)
|
||||
{
|
||||
device->RecordResourceReadPush(g_Stream[stream].pVertexBuffer);
|
||||
InternalRelease(g_Stream[stream].pVertexBuffer);
|
||||
}
|
||||
if (stride == g_Stream[stream].Stride) device->m_DirtyFlags |= 0x200;
|
||||
else device->m_DirtyFlags |= 0x280;
|
||||
g_Stream[stream].pVertexBuffer = buffer;
|
||||
g_Stream[stream].Stride = stride;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetStreamSource(
|
||||
UINT stream,
|
||||
D3DVertexBuffer **buffer,
|
||||
UINT *stride)
|
||||
{
|
||||
D3DVertexBuffer *vertexBuffer = g_Stream[stream].pVertexBuffer;
|
||||
if (vertexBuffer)
|
||||
{
|
||||
vertexBuffer->AddRef();
|
||||
*buffer = vertexBuffer;
|
||||
*stride = g_Stream[stream].Stride;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer = NULL;
|
||||
*stride = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_RunVertexStateShader(
|
||||
DWORD address,
|
||||
const float *data)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD *push = device->StartPush();
|
||||
if (data)
|
||||
{
|
||||
Push4f(push, 0x1e80, data[0], data[1], data[2], data[3]);
|
||||
push += 5;
|
||||
}
|
||||
Push1(push, 0x1e90, address);
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_LoadVertexShader(
|
||||
DWORD handle,
|
||||
DWORD address)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
if (!(device->m_StateFlags & 0x10)) ShadowVertexShaderState(shader, address);
|
||||
DWORD dwords = shader->ProgramAndConstantsDwords;
|
||||
DWORD *push = device->StartPush(dwords + 2);
|
||||
Push1(push, 0x1e9c, address);
|
||||
memcpy(push + 2, shader->ProgramAndConstants, 4 * dwords);
|
||||
device->EndPush(push + dwords + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_LoadVertexShaderProgram(
|
||||
DWORD *function,
|
||||
DWORD address)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD length = (function[0] >> 16);
|
||||
DWORD dwords = length * 4;
|
||||
if (!(device->m_StateFlags & 0x10))
|
||||
{
|
||||
memcpy(&device->m_VertexShaderProgramSlots[address][0], function + 1, dwords * sizeof(DWORD));
|
||||
}
|
||||
DWORD *push = device->StartPush(dwords + 2 + VSHADER_PROGRAM_SLOTS / VSHADER_BATCH_LIMIT);
|
||||
Push1(push, 0x1e9c, address);
|
||||
push = ParseProgram(push + 2, function + 1, dwords);
|
||||
device->EndPush(push);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetShaderConstantMode(
|
||||
D3DSHADERCONSTANTMODE *mode)
|
||||
{
|
||||
*mode = g_pDevice->m_ConstantMode;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetVertexShader(
|
||||
DWORD *handle)
|
||||
{
|
||||
*handle = g_pDevice->m_VertexShaderHandle;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetVertexShaderSize(
|
||||
DWORD handle,
|
||||
UINT *size)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
if (size) *size = shader->ProgramSize;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetVertexShaderType(
|
||||
DWORD handle,
|
||||
DWORD *type)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
DWORD value;
|
||||
if (shader->Flags & VERTEXSHADER_STATE) value = D3DSMT_VERTEXSTATESHADER;
|
||||
else if (shader->Flags & VERTEXSHADER_WRITE) value = D3DSMT_READWRITE_VERTEXSHADER;
|
||||
else value = D3DSMT_VERTEXSHADER;
|
||||
if (type) *type = value;
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_GetVertexShaderConstant(
|
||||
INT index,
|
||||
void *data,
|
||||
DWORD count)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
memcpy(data, &device->m_VertexShaderConstants[index + VSHADER_CONSTANT_BIAS][0], count * 4 * sizeof(float));
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_DeleteVertexShader(
|
||||
DWORD handle)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
if (--shader->RefCount == 0) LocalFree(shader);
|
||||
return;
|
||||
}
|
||||
HRESULT WINAPI D3DDevice_CreateVertexShader(
|
||||
const DWORD *declaration,
|
||||
const DWORD *function,
|
||||
DWORD *handle,
|
||||
DWORD usage)
|
||||
{
|
||||
DWORD shaderType, shaderLength;
|
||||
if (function)
|
||||
{
|
||||
WORD typeWord, lengthWord;
|
||||
memcpy(&typeWord, function, sizeof(typeWord));
|
||||
memcpy(&lengthWord, (const BYTE *)function + sizeof(typeWord), sizeof(lengthWord));
|
||||
shaderType = typeWord;
|
||||
shaderLength = lengthWord;
|
||||
}
|
||||
DWORD programSize = 0;
|
||||
if (function)
|
||||
{
|
||||
programSize = 16 * shaderLength;
|
||||
programSize += 4 * ((programSize + 127) / 128);
|
||||
}
|
||||
DWORD constantSize = 0;
|
||||
if (declaration) constantSize = 4 * ParseDeclarationConstants(declaration, NULL);
|
||||
DWORD byteSize = programSize + constantSize;
|
||||
VertexShader *shader = (VertexShader *)LocalAlloc(0, sizeof(*shader) + byteSize);
|
||||
if (!shader) return E_OUTOFMEMORY;
|
||||
memset(shader, 0, sizeof(*shader));
|
||||
shader->RefCount = 1;
|
||||
shader->Flags = usage;
|
||||
for (DWORD i = 0; i < VERTEXSHADER_SLOTS; i++) shader->Slot[i].SizeAndType = SIZEANDTYPE_DISABLED;
|
||||
if (declaration) ParseDeclarationStream(shader, declaration, function == NULL);
|
||||
DWORD functionDwords = 0;
|
||||
if (function)
|
||||
{
|
||||
shader->Flags |= VERTEXSHADER_PROGRAM;
|
||||
if (shaderType != 0x2078) shader->Flags |= VERTEXSHADER_WRITE;
|
||||
if (shaderType == 0x7378) shader->Flags |= VERTEXSHADER_STATE;
|
||||
shader->ProgramSize = shaderLength;
|
||||
DWORD *program = shader->ProgramAndConstants;
|
||||
functionDwords = ParseProgram(program, function + 1, 4 * shaderLength) - program;
|
||||
}
|
||||
if (declaration) ParseDeclarationConstants(declaration, shader->ProgramAndConstants + functionDwords);
|
||||
DWORD dwords = byteSize >> 2;
|
||||
shader->ProgramAndConstantsDwords = dwords;
|
||||
shader->ProgramAndConstants[dwords] = 0;
|
||||
*handle = (DWORD)shader | D3DFVF_RESERVED0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DDevice_GetVertexShaderDeclaration(
|
||||
DWORD handle,
|
||||
void *data,
|
||||
DWORD *sizeOfData)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
if (shader->Flags & VERTEXSHADER_STATE)
|
||||
{
|
||||
*sizeOfData = 0;
|
||||
return S_OK;
|
||||
}
|
||||
DWORD *destination = NULL;
|
||||
for (;;)
|
||||
{
|
||||
DWORD currentStream = 0xffffffff;
|
||||
DWORD index = 0;
|
||||
DWORD slot;
|
||||
for (DWORD stream = 0; stream < 16; stream++)
|
||||
{
|
||||
DWORD currentEndOffset = 0;
|
||||
for (;;)
|
||||
{
|
||||
DWORD offset = 0xffffffff;
|
||||
DWORD i = VERTEXSHADER_SLOTS - 1;
|
||||
do
|
||||
{
|
||||
if ((shader->Slot[i].StreamIndex == stream) &&
|
||||
(shader->Slot[i].Offset < offset) &&
|
||||
(shader->Slot[i].Offset >= currentEndOffset) &&
|
||||
(shader->Slot[i].Flags == 0) &&
|
||||
(shader->Slot[i].SizeAndType != SIZEANDTYPE_DISABLED))
|
||||
{
|
||||
offset = shader->Slot[i].Offset;
|
||||
slot = i;
|
||||
}
|
||||
} while (i-- != 0);
|
||||
if (offset == 0xffffffff) break;
|
||||
if (stream != currentStream)
|
||||
{
|
||||
currentStream = stream;
|
||||
if (destination) destination[index] = D3DVSD_STREAM(stream);
|
||||
index++;
|
||||
}
|
||||
DWORD padding = offset - currentEndOffset;
|
||||
while (padding > 0)
|
||||
{
|
||||
DWORD batchSize = min(padding, 15);
|
||||
if (destination) destination[index] = D3DVSD_SKIPBYTES(batchSize);
|
||||
index++;
|
||||
padding -= batchSize;
|
||||
}
|
||||
DWORD sizeAndType = shader->Slot[slot].SizeAndType;
|
||||
if (destination)
|
||||
{
|
||||
DWORD reg = slot < SLOT_TEXTURE0 ? slot : slot - 7;
|
||||
destination[index] = D3DVSD_REG(reg, sizeAndType);
|
||||
}
|
||||
index++;
|
||||
currentEndOffset = offset + g_UnitsOfElement[(sizeAndType & 0xf0) >> 4]
|
||||
* g_BytesPerUnit[sizeAndType & 0xf];
|
||||
}
|
||||
}
|
||||
for (slot = 0; slot < VERTEXSHADER_SLOTS; slot++)
|
||||
{
|
||||
if (shader->Slot[slot].Flags == 2)
|
||||
{
|
||||
if (destination) destination[index] = D3DVSD_TESSUV(slot);
|
||||
index++;
|
||||
}
|
||||
else if (shader->Slot[slot].Flags == 1)
|
||||
{
|
||||
if (destination) destination[index] = D3DVSD_TESSNORMAL(shader->Slot[slot].Source, slot);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
DWORD *programAndConstants = shader->ProgramAndConstants;
|
||||
DWORD constantSlot;
|
||||
DWORD methodEncode;
|
||||
while ((methodEncode = *programAndConstants++) != 0)
|
||||
{
|
||||
DWORD count = methodEncode >> 18;
|
||||
if (count == 1) constantSlot = *programAndConstants;
|
||||
else if ((methodEncode & 0xffff) == 0xb80)
|
||||
{
|
||||
if (destination)
|
||||
{
|
||||
DWORD slotCount = count >> 2;
|
||||
destination[index] = D3DVSD_CONST(constantSlot - VSHADER_CONSTANT_BIAS, slotCount);
|
||||
memcpy(&destination[index + 1], programAndConstants, count * sizeof(DWORD));
|
||||
}
|
||||
index += 1 + count;
|
||||
}
|
||||
programAndConstants += count;
|
||||
}
|
||||
if (destination) destination[index] = D3DVSD_END();
|
||||
index++;
|
||||
if (destination) return S_OK;
|
||||
DWORD size = index * sizeof(DWORD);
|
||||
if (size > *sizeOfData)
|
||||
{
|
||||
*sizeOfData = size;
|
||||
return data == NULL ? S_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
*sizeOfData = size;
|
||||
if (data == NULL) return S_OK;
|
||||
destination = (DWORD *)data;
|
||||
}
|
||||
}
|
||||
HRESULT WINAPI D3DDevice_GetVertexShaderFunction(
|
||||
DWORD handle,
|
||||
void *data,
|
||||
DWORD *sizeOfData)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
if (!(shader->Flags & VERTEXSHADER_PROGRAM))
|
||||
{
|
||||
*sizeOfData = 0;
|
||||
return S_OK;
|
||||
}
|
||||
DWORD size = 16 * shader->ProgramSize;
|
||||
DWORD required = 4 + size;
|
||||
if (required > *sizeOfData)
|
||||
{
|
||||
*sizeOfData = required;
|
||||
return data == NULL ? S_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
*sizeOfData = required;
|
||||
if (data == NULL) return S_OK;
|
||||
BYTE *source = (BYTE *)(shader->ProgramAndConstants + 1);
|
||||
BYTE *destination = (BYTE *)data;
|
||||
DWORD type = 0x2078;
|
||||
if (shader->Flags & VERTEXSHADER_STATE) type = 0x7378;
|
||||
else if (shader->Flags & VERTEXSHADER_WRITE) type = 0x7778;
|
||||
*((DWORD *)destination) = type | (shader->ProgramSize << 16);
|
||||
destination += sizeof(DWORD);
|
||||
DWORD batchSize;
|
||||
do
|
||||
{
|
||||
batchSize = min(size, 16 * VSHADER_BATCH_LIMIT);
|
||||
memcpy(destination, source, batchSize);
|
||||
destination += batchSize;
|
||||
source += batchSize + sizeof(DWORD);
|
||||
} while ((size -= batchSize) != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT WINAPI D3DDevice_GetVertexShaderInput(
|
||||
DWORD *handle,
|
||||
UINT *streamCount,
|
||||
D3DSTREAM_INPUT *streamInputs)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (streamCount) *streamCount = device->m_VertexShaderInputCount;
|
||||
if (handle) *handle = device->m_VertexShaderInputHandle;
|
||||
if (streamInputs)
|
||||
memcpy(streamInputs, device->m_VertexShaderInputStream,
|
||||
device->m_VertexShaderInputCount * sizeof(streamInputs[0]));
|
||||
return (device->m_DirtyFlags & 0x40000000) ? S_OK : S_FALSE;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexShaderInput(
|
||||
DWORD handle,
|
||||
UINT streamCount,
|
||||
const D3DSTREAM_INPUT *streamInputs)
|
||||
{
|
||||
DWORD i;
|
||||
CDevice *device = g_pDevice;
|
||||
if (handle == 0)
|
||||
{
|
||||
/* January clears direct-input state here without releasing the saved
|
||||
* stream references; later implementations have additional cleanup. */
|
||||
device->m_DirtyFlags &= ~0x40000000;
|
||||
device->m_DirtyFlags |= 0x380;
|
||||
return;
|
||||
}
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
for (i = 0; i < streamCount; i++) InternalAddRef(streamInputs[i].VertexBuffer);
|
||||
for (i = 0; i < device->m_VertexShaderInputCount; i++)
|
||||
{
|
||||
D3DVertexBuffer *buffer = device->m_VertexShaderInputStream[i].VertexBuffer;
|
||||
device->RecordResourceReadPush(buffer);
|
||||
InternalRelease(buffer);
|
||||
}
|
||||
device->m_DirtyFlags &= ~0x380;
|
||||
device->m_DirtyFlags |= 0x40000000;
|
||||
device->m_VertexShaderInputHandle = handle;
|
||||
device->m_VertexShaderInputCount = streamCount;
|
||||
memcpy(device->m_VertexShaderInputStream, streamInputs, streamCount * sizeof(streamInputs[0]));
|
||||
DWORD *push = device->StartPush();
|
||||
PushCount(push, 0x1720, 16);
|
||||
PushCount(push + 17, 0x1760, 16);
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
VertexShaderSlot *slot = &shader->Slot[i];
|
||||
if (!(shader->Flags & VERTEXSHADER_PROGRAM) &&
|
||||
(i >= D3DVSDE_TEXCOORD0) && (i <= D3DVSDE_TEXCOORD3))
|
||||
slot = &shader->Slot[i + SLOT_TEXTURE0 - D3DVSDE_TEXCOORD0];
|
||||
const D3DSTREAM_INPUT *input = &streamInputs[slot->StreamIndex];
|
||||
DWORD offset = input->VertexBuffer->Data + input->Offset + slot->Offset;
|
||||
push[1 + i] = offset;
|
||||
push[18 + i] = (input->Stride << 8) + slot->SizeAndType;
|
||||
}
|
||||
device->EndPush(push + 34);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SelectVertexShader(
|
||||
DWORD handle,
|
||||
DWORD address)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (handle != 0)
|
||||
{
|
||||
VertexShader *shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
device->m_pVertexShader = shader;
|
||||
device->m_VertexShaderHandle = handle;
|
||||
device->m_DirtyFlags |= 0x3a0;
|
||||
DWORD *push = device->StartPush();
|
||||
Push2(push, 0x1e94, 6, shader->Flags & VERTEXSHADER_WRITE);
|
||||
push = CommonSetViewport(device, push + 3);
|
||||
device->EndPush(push);
|
||||
}
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1ea0, address);
|
||||
device->EndPush(push + 2);
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetShaderConstantMode(
|
||||
D3DSHADERCONSTANTMODE mode)
|
||||
{
|
||||
CDevice *device = g_pDevice;
|
||||
if (mode & D3DSCM_NORESERVEDCONSTANTS) device->m_StateFlags |= 0x200;
|
||||
else device->m_StateFlags &= ~0x200;
|
||||
mode = (D3DSHADERCONSTANTMODE)(mode & ~D3DSCM_NORESERVEDCONSTANTS);
|
||||
device->m_ConstantMode = mode;
|
||||
if (mode == D3DSCM_96CONSTANTS)
|
||||
{
|
||||
device->m_DirtyFlags |= 0x26;
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1ea4, 60);
|
||||
PushCount(push + 2, 0xb80, sizeof(g_FixedFunctionPipelineConstants) / 4);
|
||||
memcpy(push + 3, g_FixedFunctionPipelineConstants, sizeof(g_FixedFunctionPipelineConstants));
|
||||
push += 3 + sizeof(g_FixedFunctionPipelineConstants) / 4;
|
||||
DumpMatrixTransposed(push, 0x400840, &g_IdentityMatrix);
|
||||
DumpMatrixTransposed(push + 17, 0x400880, &g_IdentityMatrix);
|
||||
DumpMatrixTransposed(push + 34, 0x4008c0, &g_IdentityMatrix);
|
||||
DumpMatrixTransposed(push + 51, 0x400900, &g_IdentityMatrix);
|
||||
Push4f(push + 68, 0x9d0, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
device->EndPush(push + 73);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void WINAPI D3DDevice_SetVertexShader(
|
||||
DWORD handle)
|
||||
{
|
||||
VertexShader *shader;
|
||||
CDevice *device = g_pDevice;
|
||||
DWORD previousFlags = device->m_pVertexShader->Flags;
|
||||
if (handle & D3DFVF_RESERVED0) shader = (VertexShader *)(handle - D3DFVF_RESERVED0);
|
||||
else
|
||||
{
|
||||
shader = &g_FvfVertexShader;
|
||||
InitializeVertexShaderFromFvf(shader, handle);
|
||||
}
|
||||
device->m_DirtyFlags |= 0x3a4;
|
||||
if (previousFlags != shader->Flags) device->m_DirtyFlags |= 2;
|
||||
device->m_pVertexShader = shader;
|
||||
device->m_VertexShaderHandle = handle;
|
||||
if (shader->Flags & VERTEXSHADER_PROGRAM)
|
||||
{
|
||||
D3DDevice_LoadVertexShader(handle, 0);
|
||||
D3DDevice_SelectVertexShader(handle, 0);
|
||||
}
|
||||
else if (shader->Flags & VERTEXSHADER_PASSTHROUGH)
|
||||
{
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1ea0, 0);
|
||||
Push2(push + 2, 0x1e94, 6, 0);
|
||||
push = CommonSetViewport(device, push + 5);
|
||||
device->EndPush(push);
|
||||
CommonSetPassthroughProgram(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD *push = device->StartPush();
|
||||
Push1(push, 0x1e94, 4);
|
||||
push = CommonSetViewport(device, push + 2);
|
||||
device->EndPush(push);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/* Shader state layouts from the supplied January PDB. */
|
||||
#ifndef D3D8_VSHADER_INTERNAL_H
|
||||
#define D3D8_VSHADER_INTERNAL_H
|
||||
#include "device_layout.h"
|
||||
namespace D3D
|
||||
{
|
||||
struct VertexShaderSlot
|
||||
{
|
||||
unsigned long StreamIndex; /* +0x0 */
|
||||
unsigned long Offset; /* +0x4 */
|
||||
unsigned long SizeAndType; /* +0x8 */
|
||||
unsigned char Flags; /* +0xc */
|
||||
unsigned char Source; /* +0xd */
|
||||
};
|
||||
typedef char VertexShaderSlot_size_check[sizeof(VertexShaderSlot) == 16 ? 1 : -1];
|
||||
struct VertexShader
|
||||
{
|
||||
unsigned long RefCount; /* +0x0 */
|
||||
unsigned long Flags; /* +0x4 */
|
||||
unsigned long MaxSlot; /* +0x8 */
|
||||
unsigned long TextureCount; /* +0xc */
|
||||
unsigned long ProgramSize; /* +0x10 */
|
||||
unsigned long ProgramAndConstantsDwords; /* +0x14 */
|
||||
unsigned long Dimensionality[4]; /* +0x18 */
|
||||
D3D::VertexShaderSlot Slot[20]; /* +0x28 */
|
||||
unsigned long ProgramAndConstants[1]; /* +0x168 */
|
||||
};
|
||||
typedef char VertexShader_size_check[sizeof(VertexShader) == 364 ? 1 : -1];
|
||||
struct Stream
|
||||
{
|
||||
unsigned long Stride; /* +0x0 */
|
||||
unsigned long Offset; /* +0x4 */
|
||||
D3DVertexBuffer *pVertexBuffer; /* +0x8 */
|
||||
};
|
||||
typedef char Stream_size_check[sizeof(Stream) == 12 ? 1 : -1];
|
||||
extern VertexShader g_FvfVertexShader;
|
||||
extern Stream g_Stream[16];
|
||||
extern const DWORD g_TextureCount[4];
|
||||
extern const DWORD g_FixedFunctionPipelineConstants[12];
|
||||
extern const BYTE g_UnitsOfElement[];
|
||||
extern const BYTE g_BytesPerUnit[];
|
||||
enum
|
||||
{
|
||||
VERTEXSHADER_WRITE = 1,
|
||||
VERTEXSHADER_PASSTHROUGH = 2,
|
||||
VERTEXSHADER_PROGRAM = 4,
|
||||
VERTEXSHADER_STATE = 8,
|
||||
VERTEXSHADER_HASDIFFUSE = 0x400,
|
||||
VERTEXSHADER_HASSPECULAR = 0x800,
|
||||
VERTEXSHADER_HASBACKDIFFUSE = 0x1000,
|
||||
VERTEXSHADER_HASBACKSPECULAR = 0x2000,
|
||||
SIZEANDTYPE_DISABLED = 2,
|
||||
VSHADER_BATCH_LIMIT = 8,
|
||||
VSHADER_PROGRAM_SLOTS = 136,
|
||||
VSHADER_CONSTANT_BIAS = 96,
|
||||
VERTEXSHADER_SLOTS = 20,
|
||||
SLOT_POSITION = 0,
|
||||
SLOT_WEIGHT = 1,
|
||||
SLOT_NORMAL = 2,
|
||||
SLOT_DIFFUSE = 3,
|
||||
SLOT_SPECULAR = 4,
|
||||
SLOT_TEXTURE0 = 16
|
||||
};
|
||||
void WINAPI InitializeVertexShaderFromFvf(
|
||||
VertexShader *shader,
|
||||
DWORD fvf);
|
||||
void WINAPI ShadowVertexShaderState(
|
||||
VertexShader *shader,
|
||||
DWORD address);
|
||||
DWORD *WINAPI ParseProgram(
|
||||
DWORD *push,
|
||||
const DWORD *program,
|
||||
DWORD dwords);
|
||||
void WINAPI ParseDeclarationStream(
|
||||
VertexShader *shader,
|
||||
const DWORD *declaration,
|
||||
BOOL fixedFunction);
|
||||
DWORD WINAPI ParseDeclarationConstants(
|
||||
const DWORD *declaration,
|
||||
DWORD *push);
|
||||
void WINAPI RestoreVertexShaders(
|
||||
const DWORD *program,
|
||||
DWORD dwords);
|
||||
void __fastcall CommonSetPassthroughProgram(
|
||||
CDevice *device);
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user