From 301b797093967f1a0f18afc6166b9f3bf5909bb4 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Tue, 15 Mar 2022 12:11:32 -0700 Subject: [PATCH] Integrate nxdk_pgraph_tests --- .github/workflows/build_docker_image.yml | 4 + .gitmodules | 3 + Dockerfile | 35 +- README.md | 5 +- setup.py | 2 +- test-pgraph/README.md | 12 + test-pgraph/config.cnf | 994 +++++++++++++++++++++++ test-pgraph/nxdk_pgraph_tests | 1 + xemutest/__main__.py | 2 + xemutest/test_base.py | 100 ++- xemutest/test_nxdk_pgraph_tests.py | 69 ++ xemutest/test_xbe.py | 3 +- 12 files changed, 1199 insertions(+), 31 deletions(-) create mode 100644 .gitmodules create mode 100644 test-pgraph/README.md create mode 100644 test-pgraph/config.cnf create mode 160000 test-pgraph/nxdk_pgraph_tests create mode 100644 xemutest/test_nxdk_pgraph_tests.py diff --git a/.github/workflows/build_docker_image.yml b/.github/workflows/build_docker_image.yml index fdb0cb6..f5fba06 100644 --- a/.github/workflows/build_docker_image.yml +++ b/.github/workflows/build_docker_image.yml @@ -15,6 +15,8 @@ jobs: steps: - name: Clone Tree uses: actions/checkout@v2 + with: + submodules: recursive - name: Extract image metadata (tags, labels) id: meta @@ -51,6 +53,8 @@ jobs: - name: Clone Tree uses: actions/checkout@v2 + with: + submodules: recursive - name: Build Test Data run: bash ./scripts/build_test_data.sh diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5a1b37c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "nxdk_pgraph_tests"] + path = test-pgraph/nxdk_pgraph_tests + url = https://github.com/abaire/nxdk_pgraph_tests.git diff --git a/Dockerfile b/Dockerfile index 2328e5d..bf88efa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,35 @@ RUN mkdir /data/TestXBE RUN /usr/src/nxdk/docker_entry.sh make -C /test-xbe RUN cp /test-xbe/tester.iso /data/TestXBE/ +# The nxdk_pgraph_tests includes its own copy of the nxdk which needs more build +# infrastructure than the nxdk-runbase used for other tests. +FROM ubuntu:20.04 AS pgraph-buildbase +ENV DEBIAN_FRONTEND noninteractive +RUN set -xe; \ + apt-get -qy update \ + && apt-get -qy install \ + bison \ + clang \ + cmake \ + flex \ + lld \ + llvm \ + make + +FROM pgraph-buildbase AS pgraph-data +RUN mkdir -p /data/TestNXDKPgraphTests +COPY test-pgraph /test-pgraph +RUN make -C /test-pgraph/nxdk_pgraph_tests \ + AUTORUN_IMMEDIATELY=y \ + ENABLE_SHUTDOWN=y \ + FALLBACK_OUTPUT_ROOT_PATH="c:" \ + RUNTIME_CONFIG_PATH="c:/pgraph_tests.cnf" \ + CC=clang CXX=clang++ \ + -j$(numproc) +RUN cp /test-pgraph/nxdk_pgraph_tests/nxdk_pgraph_tests.iso /data/TestNXDKPgraphTests/ +RUN cp /test-pgraph/config.cnf /data/TestNXDKPgraphTests/ + + # # Build base test container image # @@ -37,6 +66,7 @@ RUN set -xe; \ libsdl2-2.0-0 \ libssl1.1 \ libstdc++6 \ + perceptualdiff \ zlib1g \ ; @@ -53,8 +83,11 @@ EXPOSE 5900 RUN mkdir /work WORKDIR /work COPY scripts/docker_entry.sh /docker_entry.sh -COPY . /work/xemu-test +COPY ./scripts /work/xemu-test/scripts/ +COPY ./xemutest /work/xemu-test/xemutest/ +COPY ./setup.py /work/xemu-test COPY --from=data /data /work/xemu-test/xemutest/data +COPY --from=pgraph-data /data/TestNXDKPgraphTests /work/xemu-test/xemutest/data/TestNXDKPgraphTests RUN pip install /work/xemu-test ENTRYPOINT ["/docker_entry.sh"] CMD ["/usr/bin/python3", "-m", "xemutest", "/work/private", "/work/results"] diff --git a/README.md b/README.md index 79b842f..318d09a 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ xemu Automated Testing ====================== Performs a suite of tests against a build of xemu, capturing test results and -footage of the runs. Currently that suite consists of 1 test: boot to a custom -executable that writes a file to the disk. This is a useful test, but -there are many tests left to add, and you can help! Pull requests welcome. +footage of the runs. There are many tests left to add, and you can help! Pull requests +welcome. This is primarily used for automated testing of xemu pull requests. The xemu CI system uses this repository for testing. The goal is to have a large set of diff --git a/setup.py b/setup.py index 8a9358b..b55abcf 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setup(name='xemutest', include_package_data=True, package_data={'xemutest': ['data/**/*']}, install_requires=[ - 'pyfatx', + 'pyfatx >= 0.0.6', 'pywinauto; sys_platform == "win32"' ], python_requires='>=3.6' diff --git a/test-pgraph/README.md b/test-pgraph/README.md new file mode 100644 index 0000000..828e006 --- /dev/null +++ b/test-pgraph/README.md @@ -0,0 +1,12 @@ +# test-pgraph + +Runs the [nxdk_pgraph_tests](https://github.com/abaire/nxdk_pgraph_tests) suite and +validates the generated images against golden expectation files. + +# Configuration + +The subset of `nxdk_pgraph_tests` that will be executed is determined by the +`config.cnf` file in this directory. A default version of this file may be generated +using the appropriate build flag in the `nxdk_pgraph_tests` project and then copied +from the HDD. See the relevant build parameter in the Makefile to trigger config file +generation. diff --git a/test-pgraph/config.cnf b/test-pgraph/config.cnf new file mode 100644 index 0000000..05f4af5 --- /dev/null +++ b/test-pgraph/config.cnf @@ -0,0 +1,994 @@ +# pgraph test suite configuration + +Lighting normals +# NoNormal +# NoNormal-inlinearrays +# NoNormal-inlinebuf +# NoNormal-inlineelements +# Nz_-100 +# Nz_-100-inlinearrays +# Nz_-100-inlinebuf +# Nz_-100-inlineelements +# Nz_0 +# Nz_0-inlinearrays +# Nz_0-inlinebuf +# Nz_0-inlineelements +# Nz_100 +# Nz_100-inlinearrays +# Nz_100-inlinebuf +# Nz_100-inlineelements +# Nz_31 +# Nz_31-inlinearrays +# Nz_31-inlinebuf +# Nz_31-inlineelements +# Nz_70 +# Nz_70-inlinearrays +# Nz_70-inlinebuf +# Nz_70-inlineelements +# Nz_97 +# Nz_97-inlinearrays +# Nz_97-inlinebuf +# Nz_97-inlineelements + + +#Attrib carryover +# L-d0.0_0.0_1.0_1.0-da +# L-d0.2_0.0_0.6_1.0-ie +# L-d0.5_0.0_0.0_1.0-ia +# L-d0.8_0.0_0.0_1.0-ib +# L-n0.0_0.0_1.0_1.0-da +# L-n0.2_0.0_0.6_1.0-ie +# L-n0.5_0.0_0.0_1.0-ia +# L-n0.8_0.0_0.0_1.0-ib +# L-s0.0_0.0_1.0_1.0-da +# L-s0.2_0.0_0.6_1.0-ie +# L-s0.5_0.0_0.0_1.0-ia +# L-s0.8_0.0_0.0_1.0-ib +# L-t00.0_0.0_1.0_1.0-da +# L-t00.2_0.0_0.6_1.0-ie +# L-t00.5_0.0_0.0_1.0-ia +# L-t00.8_0.0_0.0_1.0-ib +# L-t10.0_0.0_1.0_1.0-da +# L-t10.2_0.0_0.6_1.0-ie +# L-t10.5_0.0_0.0_1.0-ia +# L-t10.8_0.0_0.0_1.0-ib +# L-t20.0_0.0_1.0_1.0-da +# L-t20.2_0.0_0.6_1.0-ie +# L-t20.5_0.0_0.0_1.0-ia +# L-t20.8_0.0_0.0_1.0-ib +# L-t30.0_0.0_1.0_1.0-da +# L-t30.2_0.0_0.6_1.0-ie +# L-t30.5_0.0_0.0_1.0-ia +# L-t30.8_0.0_0.0_1.0-ib +# T-d0.0_0.0_1.0_1.0-da +# T-d0.2_0.0_0.6_1.0-ie +# T-d0.5_0.0_0.0_1.0-ia +# T-d0.8_0.0_0.0_1.0-ib +# T-n0.0_0.0_1.0_1.0-da +# T-n0.2_0.0_0.6_1.0-ie +# T-n0.5_0.0_0.0_1.0-ia +# T-n0.8_0.0_0.0_1.0-ib +# T-s0.0_0.0_1.0_1.0-da +# T-s0.2_0.0_0.6_1.0-ie +# T-s0.5_0.0_0.0_1.0-ia +# T-s0.8_0.0_0.0_1.0-ib +# T-t00.0_0.0_1.0_1.0-da +# T-t00.2_0.0_0.6_1.0-ie +# T-t00.5_0.0_0.0_1.0-ia +# T-t00.8_0.0_0.0_1.0-ib +# T-t10.0_0.0_1.0_1.0-da +# T-t10.2_0.0_0.6_1.0-ie +# T-t10.5_0.0_0.0_1.0-ia +# T-t10.8_0.0_0.0_1.0-ib +# T-t20.0_0.0_1.0_1.0-da +# T-t20.2_0.0_0.6_1.0-ie +# T-t20.5_0.0_0.0_1.0-ia +# T-t20.8_0.0_0.0_1.0-ib +# T-t30.0_0.0_1.0_1.0-da +# T-t30.2_0.0_0.6_1.0-ie +# T-t30.5_0.0_0.0_1.0-ia +# T-t30.8_0.0_0.0_1.0-ib + +#Attrib setter +# Setters-alpha +# Setters-visible + +#Clear +# C00000000_Depth_n +# C00000000_Depth_y +# C00000001_Depth_n +# C00000001_Depth_y +# C00000100_Depth_n +# C00000100_Depth_y +# C00010000_Depth_n +# C00010000_Depth_y +# C01000000_Depth_n +# C01000000_Depth_y +# C01010101_Depth_n +# C01010101_Depth_y + +#Combiner +# Flags +# Independence +# Mux + +#Fog +# AFF-exp-planar +# AFF-exp2-planar +# AFF-exp2_abs-planar +# AFF-exp_abs-planar +# AFF-linear-planar +# AFF-linear_abs-planar + +#Fog vsh +# AFF-exp-planar +# AFF-exp2-planar +# AFF-exp2_abs-planar +# AFF-exp_abs-planar +# AFF-linear-planar +# AFF-linear_abs-planar + +#Fog inf coord +# AFF-exp-planar +# AFF-exp2-planar +# AFF-exp2_abs-planar +# AFF-exp_abs-planar +# AFF-linear-planar +# AFF-linear_abs-planar + +#Fog coord vec4 +# W-0.00_0.25_0.00_0.00 +# W-0.30_0.30_0.30_1.00 +# W-0.50_0.50_0.00_0.00 +# W-1.00_0.00_0.00_0.50 +# WX-0.25_0.00_0.00_0.50 +# WX-0.65_0.00_0.00_0.00 +# WY-0.00_0.75_0.75_0.25 +# WY-1.00_0.00_1.00_0.75 +# WZYX-0.25_0.50_0.75_1.00 +# WZYX-1.00_0.75_0.50_0.25 +# X-0.00_0.00_0.00_0.00 +# X-0.90_0.00_0.00_0.00 +# XYZW-0.00_0.33_0.66_0.90 +# XYZW-1.00_0.25_0.75_0.50 +# Y-0.00_0.00_0.00_0.00 +# Y-0.00_0.10_0.00_0.00 +# Y-0.00_0.60_0.00_0.00 +# Z-0.00_0.00_0.00_0.00 +# Z-0.00_0.00_0.20_0.00 +# Z-0.00_0.00_0.80_0.00 + +#Front face +# FrontFace_0_CF_B +# FrontFace_0_CF_F +# FrontFace_0_CF_FaB +# FrontFace_63_CF_B +# FrontFace_63_CF_F +# FrontFace_63_CF_FaB +# FrontFace_CCW_CF_B +# FrontFace_CCW_CF_F +# FrontFace_CCW_CF_FaB +# FrontFace_CW_CF_B +# FrontFace_CW_CF_F +# FrontFace_CW_CF_FaB + +#Depth buffer +# DepthFmt_z16_Cn_FZn_M00003f +# DepthFmt_z16_Cn_FZn_M00043e +# DepthFmt_z16_Cn_FZn_M00083d +# DepthFmt_z16_Cn_FZn_M000c3c +# DepthFmt_z16_Cn_FZn_M00103b +# DepthFmt_z16_Cn_FZn_M00143a +# DepthFmt_z16_Cn_FZn_M001839 +# DepthFmt_z16_Cn_FZn_M001c38 +# DepthFmt_z16_Cn_FZn_M002037 +# DepthFmt_z16_Cn_FZn_M002436 +# DepthFmt_z16_Cn_FZn_M002835 +# DepthFmt_z16_Cn_FZn_M002c34 +# DepthFmt_z16_Cn_FZn_M003033 +# DepthFmt_z16_Cn_FZn_M003432 +# DepthFmt_z16_Cn_FZn_M003831 +# DepthFmt_z16_Cn_FZn_M003c30 +# DepthFmt_z16_Cn_FZn_M00402f +# DepthFmt_z16_Cn_FZn_M00442e +# DepthFmt_z16_Cn_FZn_M00482d +# DepthFmt_z16_Cn_FZn_M004c2c +# DepthFmt_z16_Cn_FZn_M00502b +# DepthFmt_z16_Cn_FZn_M00542a +# DepthFmt_z16_Cn_FZn_M005829 +# DepthFmt_z16_Cn_FZn_M005c28 +# DepthFmt_z16_Cn_FZn_M006027 +# DepthFmt_z16_Cn_FZn_M006426 +# DepthFmt_z16_Cn_FZn_M006825 +# DepthFmt_z16_Cn_FZn_M006c24 +# DepthFmt_z16_Cn_FZn_M007023 +# DepthFmt_z16_Cn_FZn_M007422 +# DepthFmt_z16_Cn_FZn_M007821 +# DepthFmt_z16_Cn_FZn_M007c20 +# DepthFmt_z16_Cn_FZn_M00801f +# DepthFmt_z16_Cn_FZn_M00841e +# DepthFmt_z16_Cn_FZn_M00881d +# DepthFmt_z16_Cn_FZn_M008c1c +# DepthFmt_z16_Cn_FZn_M00901b +# DepthFmt_z16_Cn_FZn_M00941a +# DepthFmt_z16_Cn_FZn_M009819 +# DepthFmt_z16_Cn_FZn_M009c18 +# DepthFmt_z16_Cn_FZn_M00a017 +# DepthFmt_z16_Cn_FZn_M00a416 +# DepthFmt_z16_Cn_FZn_M00a815 +# DepthFmt_z16_Cn_FZn_M00ac14 +# DepthFmt_z16_Cn_FZn_M00b013 +# DepthFmt_z16_Cn_FZn_M00b412 +# DepthFmt_z16_Cn_FZn_M00b811 +# DepthFmt_z16_Cn_FZn_M00bc10 +# DepthFmt_z16_Cn_FZn_M00c00f +# DepthFmt_z16_Cn_FZn_M00c40e +# DepthFmt_z16_Cn_FZn_M00c80d +# DepthFmt_z16_Cn_FZn_M00cc0c +# DepthFmt_z16_Cn_FZn_M00d00b +# DepthFmt_z16_Cn_FZn_M00d40a +# DepthFmt_z16_Cn_FZn_M00d809 +# DepthFmt_z16_Cn_FZn_M00dc08 +# DepthFmt_z16_Cn_FZn_M00e007 +# DepthFmt_z16_Cn_FZn_M00e406 +# DepthFmt_z16_Cn_FZn_M00e805 +# DepthFmt_z16_Cn_FZn_M00ec04 +# DepthFmt_z16_Cn_FZn_M00f003 +# DepthFmt_z16_Cn_FZn_M00f402 +# DepthFmt_z16_Cn_FZn_M00f801 +# DepthFmt_z16_Cn_FZn_M00fc00 +# DepthFmt_z16_Cn_FZn_M00ffff +# DepthFmt_z16_Cn_FZy_M00003f +# DepthFmt_z16_Cn_FZy_M00043e +# DepthFmt_z16_Cn_FZy_M00083d +# DepthFmt_z16_Cn_FZy_M000c3c +# DepthFmt_z16_Cn_FZy_M00103b +# DepthFmt_z16_Cn_FZy_M00143a +# DepthFmt_z16_Cn_FZy_M001839 +# DepthFmt_z16_Cn_FZy_M001c38 +# DepthFmt_z16_Cn_FZy_M002037 +# DepthFmt_z16_Cn_FZy_M002436 +# DepthFmt_z16_Cn_FZy_M002835 +# DepthFmt_z16_Cn_FZy_M002c34 +# DepthFmt_z16_Cn_FZy_M003033 +# DepthFmt_z16_Cn_FZy_M003432 +# DepthFmt_z16_Cn_FZy_M003831 +# DepthFmt_z16_Cn_FZy_M003c30 +# DepthFmt_z16_Cn_FZy_M00402f +# DepthFmt_z16_Cn_FZy_M00442e +# DepthFmt_z16_Cn_FZy_M00482d +# DepthFmt_z16_Cn_FZy_M004c2c +# DepthFmt_z16_Cn_FZy_M00502b +# DepthFmt_z16_Cn_FZy_M00542a +# DepthFmt_z16_Cn_FZy_M005829 +# DepthFmt_z16_Cn_FZy_M005c28 +# DepthFmt_z16_Cn_FZy_M006027 +# DepthFmt_z16_Cn_FZy_M006426 +# DepthFmt_z16_Cn_FZy_M006825 +# DepthFmt_z16_Cn_FZy_M006c24 +# DepthFmt_z16_Cn_FZy_M007023 +# DepthFmt_z16_Cn_FZy_M007422 +# DepthFmt_z16_Cn_FZy_M007821 +# DepthFmt_z16_Cn_FZy_M007c20 +# DepthFmt_z16_Cn_FZy_M00801f +# DepthFmt_z16_Cn_FZy_M00841e +# DepthFmt_z16_Cn_FZy_M00881d +# DepthFmt_z16_Cn_FZy_M008c1c +# DepthFmt_z16_Cn_FZy_M00901b +# DepthFmt_z16_Cn_FZy_M00941a +# DepthFmt_z16_Cn_FZy_M009819 +# DepthFmt_z16_Cn_FZy_M009c18 +# DepthFmt_z16_Cn_FZy_M00a017 +# DepthFmt_z16_Cn_FZy_M00a416 +# DepthFmt_z16_Cn_FZy_M00a815 +# DepthFmt_z16_Cn_FZy_M00ac14 +# DepthFmt_z16_Cn_FZy_M00b013 +# DepthFmt_z16_Cn_FZy_M00b412 +# DepthFmt_z16_Cn_FZy_M00b811 +# DepthFmt_z16_Cn_FZy_M00bc10 +# DepthFmt_z16_Cn_FZy_M00c00f +# DepthFmt_z16_Cn_FZy_M00c40e +# DepthFmt_z16_Cn_FZy_M00c80d +# DepthFmt_z16_Cn_FZy_M00cc0c +# DepthFmt_z16_Cn_FZy_M00d00b +# DepthFmt_z16_Cn_FZy_M00d40a +# DepthFmt_z16_Cn_FZy_M00d809 +# DepthFmt_z16_Cn_FZy_M00dc08 +# DepthFmt_z16_Cn_FZy_M00e007 +# DepthFmt_z16_Cn_FZy_M00e406 +# DepthFmt_z16_Cn_FZy_M00e805 +# DepthFmt_z16_Cn_FZy_M00ec04 +# DepthFmt_z16_Cn_FZy_M00f003 +# DepthFmt_z16_Cn_FZy_M00f402 +# DepthFmt_z16_Cn_FZy_M00f801 +# DepthFmt_z16_Cn_FZy_M00fc00 +# DepthFmt_z16_Cn_FZy_M00ffff +# DepthFmt_z16_Cy_FZn_M00003f +# DepthFmt_z16_Cy_FZn_M00043e +# DepthFmt_z16_Cy_FZn_M00083d +# DepthFmt_z16_Cy_FZn_M000c3c +# DepthFmt_z16_Cy_FZn_M00103b +# DepthFmt_z16_Cy_FZn_M00143a +# DepthFmt_z16_Cy_FZn_M001839 +# DepthFmt_z16_Cy_FZn_M001c38 +# DepthFmt_z16_Cy_FZn_M002037 +# DepthFmt_z16_Cy_FZn_M002436 +# DepthFmt_z16_Cy_FZn_M002835 +# DepthFmt_z16_Cy_FZn_M002c34 +# DepthFmt_z16_Cy_FZn_M003033 +# DepthFmt_z16_Cy_FZn_M003432 +# DepthFmt_z16_Cy_FZn_M003831 +# DepthFmt_z16_Cy_FZn_M003c30 +# DepthFmt_z16_Cy_FZn_M00402f +# DepthFmt_z16_Cy_FZn_M00442e +# DepthFmt_z16_Cy_FZn_M00482d +# DepthFmt_z16_Cy_FZn_M004c2c +# DepthFmt_z16_Cy_FZn_M00502b +# DepthFmt_z16_Cy_FZn_M00542a +# DepthFmt_z16_Cy_FZn_M005829 +# DepthFmt_z16_Cy_FZn_M005c28 +# DepthFmt_z16_Cy_FZn_M006027 +# DepthFmt_z16_Cy_FZn_M006426 +# DepthFmt_z16_Cy_FZn_M006825 +# DepthFmt_z16_Cy_FZn_M006c24 +# DepthFmt_z16_Cy_FZn_M007023 +# DepthFmt_z16_Cy_FZn_M007422 +# DepthFmt_z16_Cy_FZn_M007821 +# DepthFmt_z16_Cy_FZn_M007c20 +# DepthFmt_z16_Cy_FZn_M00801f +# DepthFmt_z16_Cy_FZn_M00841e +# DepthFmt_z16_Cy_FZn_M00881d +# DepthFmt_z16_Cy_FZn_M008c1c +# DepthFmt_z16_Cy_FZn_M00901b +# DepthFmt_z16_Cy_FZn_M00941a +# DepthFmt_z16_Cy_FZn_M009819 +# DepthFmt_z16_Cy_FZn_M009c18 +# DepthFmt_z16_Cy_FZn_M00a017 +# DepthFmt_z16_Cy_FZn_M00a416 +# DepthFmt_z16_Cy_FZn_M00a815 +# DepthFmt_z16_Cy_FZn_M00ac14 +# DepthFmt_z16_Cy_FZn_M00b013 +# DepthFmt_z16_Cy_FZn_M00b412 +# DepthFmt_z16_Cy_FZn_M00b811 +# DepthFmt_z16_Cy_FZn_M00bc10 +# DepthFmt_z16_Cy_FZn_M00c00f +# DepthFmt_z16_Cy_FZn_M00c40e +# DepthFmt_z16_Cy_FZn_M00c80d +# DepthFmt_z16_Cy_FZn_M00cc0c +# DepthFmt_z16_Cy_FZn_M00d00b +# DepthFmt_z16_Cy_FZn_M00d40a +# DepthFmt_z16_Cy_FZn_M00d809 +# DepthFmt_z16_Cy_FZn_M00dc08 +# DepthFmt_z16_Cy_FZn_M00e007 +# DepthFmt_z16_Cy_FZn_M00e406 +# DepthFmt_z16_Cy_FZn_M00e805 +# DepthFmt_z16_Cy_FZn_M00ec04 +# DepthFmt_z16_Cy_FZn_M00f003 +# DepthFmt_z16_Cy_FZn_M00f402 +# DepthFmt_z16_Cy_FZn_M00f801 +# DepthFmt_z16_Cy_FZn_M00fc00 +# DepthFmt_z16_Cy_FZn_M00ffff +# DepthFmt_z16_Cy_FZy_M00003f +# DepthFmt_z16_Cy_FZy_M00043e +# DepthFmt_z16_Cy_FZy_M00083d +# DepthFmt_z16_Cy_FZy_M000c3c +# DepthFmt_z16_Cy_FZy_M00103b +# DepthFmt_z16_Cy_FZy_M00143a +# DepthFmt_z16_Cy_FZy_M001839 +# DepthFmt_z16_Cy_FZy_M001c38 +# DepthFmt_z16_Cy_FZy_M002037 +# DepthFmt_z16_Cy_FZy_M002436 +# DepthFmt_z16_Cy_FZy_M002835 +# DepthFmt_z16_Cy_FZy_M002c34 +# DepthFmt_z16_Cy_FZy_M003033 +# DepthFmt_z16_Cy_FZy_M003432 +# DepthFmt_z16_Cy_FZy_M003831 +# DepthFmt_z16_Cy_FZy_M003c30 +# DepthFmt_z16_Cy_FZy_M00402f +# DepthFmt_z16_Cy_FZy_M00442e +# DepthFmt_z16_Cy_FZy_M00482d +# DepthFmt_z16_Cy_FZy_M004c2c +# DepthFmt_z16_Cy_FZy_M00502b +# DepthFmt_z16_Cy_FZy_M00542a +# DepthFmt_z16_Cy_FZy_M005829 +# DepthFmt_z16_Cy_FZy_M005c28 +# DepthFmt_z16_Cy_FZy_M006027 +# DepthFmt_z16_Cy_FZy_M006426 +# DepthFmt_z16_Cy_FZy_M006825 +# DepthFmt_z16_Cy_FZy_M006c24 +# DepthFmt_z16_Cy_FZy_M007023 +# DepthFmt_z16_Cy_FZy_M007422 +# DepthFmt_z16_Cy_FZy_M007821 +# DepthFmt_z16_Cy_FZy_M007c20 +# DepthFmt_z16_Cy_FZy_M00801f +# DepthFmt_z16_Cy_FZy_M00841e +# DepthFmt_z16_Cy_FZy_M00881d +# DepthFmt_z16_Cy_FZy_M008c1c +# DepthFmt_z16_Cy_FZy_M00901b +# DepthFmt_z16_Cy_FZy_M00941a +# DepthFmt_z16_Cy_FZy_M009819 +# DepthFmt_z16_Cy_FZy_M009c18 +# DepthFmt_z16_Cy_FZy_M00a017 +# DepthFmt_z16_Cy_FZy_M00a416 +# DepthFmt_z16_Cy_FZy_M00a815 +# DepthFmt_z16_Cy_FZy_M00ac14 +# DepthFmt_z16_Cy_FZy_M00b013 +# DepthFmt_z16_Cy_FZy_M00b412 +# DepthFmt_z16_Cy_FZy_M00b811 +# DepthFmt_z16_Cy_FZy_M00bc10 +# DepthFmt_z16_Cy_FZy_M00c00f +# DepthFmt_z16_Cy_FZy_M00c40e +# DepthFmt_z16_Cy_FZy_M00c80d +# DepthFmt_z16_Cy_FZy_M00cc0c +# DepthFmt_z16_Cy_FZy_M00d00b +# DepthFmt_z16_Cy_FZy_M00d40a +# DepthFmt_z16_Cy_FZy_M00d809 +# DepthFmt_z16_Cy_FZy_M00dc08 +# DepthFmt_z16_Cy_FZy_M00e007 +# DepthFmt_z16_Cy_FZy_M00e406 +# DepthFmt_z16_Cy_FZy_M00e805 +# DepthFmt_z16_Cy_FZy_M00ec04 +# DepthFmt_z16_Cy_FZy_M00f003 +# DepthFmt_z16_Cy_FZy_M00f402 +# DepthFmt_z16_Cy_FZy_M00f801 +# DepthFmt_z16_Cy_FZy_M00fc00 +# DepthFmt_z16_Cy_FZy_M00ffff +# DepthFmt_z24_Cn_FZn_M00003f +# DepthFmt_z24_Cn_FZn_M04003e +# DepthFmt_z24_Cn_FZn_M08003d +# DepthFmt_z24_Cn_FZn_M0c003c +# DepthFmt_z24_Cn_FZn_M10003b +# DepthFmt_z24_Cn_FZn_M14003a +# DepthFmt_z24_Cn_FZn_M180039 +# DepthFmt_z24_Cn_FZn_M1c0038 +# DepthFmt_z24_Cn_FZn_M200037 +# DepthFmt_z24_Cn_FZn_M240036 +# DepthFmt_z24_Cn_FZn_M280035 +# DepthFmt_z24_Cn_FZn_M2c0034 +# DepthFmt_z24_Cn_FZn_M300033 +# DepthFmt_z24_Cn_FZn_M340032 +# DepthFmt_z24_Cn_FZn_M380031 +# DepthFmt_z24_Cn_FZn_M3c0030 +# DepthFmt_z24_Cn_FZn_M40002f +# DepthFmt_z24_Cn_FZn_M44002e +# DepthFmt_z24_Cn_FZn_M48002d +# DepthFmt_z24_Cn_FZn_M4c002c +# DepthFmt_z24_Cn_FZn_M50002b +# DepthFmt_z24_Cn_FZn_M54002a +# DepthFmt_z24_Cn_FZn_M580029 +# DepthFmt_z24_Cn_FZn_M5c0028 +# DepthFmt_z24_Cn_FZn_M600027 +# DepthFmt_z24_Cn_FZn_M640026 +# DepthFmt_z24_Cn_FZn_M680025 +# DepthFmt_z24_Cn_FZn_M6c0024 +# DepthFmt_z24_Cn_FZn_M700023 +# DepthFmt_z24_Cn_FZn_M740022 +# DepthFmt_z24_Cn_FZn_M780021 +# DepthFmt_z24_Cn_FZn_M7c0020 +# DepthFmt_z24_Cn_FZn_M80001f +# DepthFmt_z24_Cn_FZn_M84001e +# DepthFmt_z24_Cn_FZn_M88001d +# DepthFmt_z24_Cn_FZn_M8c001c +# DepthFmt_z24_Cn_FZn_M90001b +# DepthFmt_z24_Cn_FZn_M94001a +# DepthFmt_z24_Cn_FZn_M980019 +# DepthFmt_z24_Cn_FZn_M9c0018 +# DepthFmt_z24_Cn_FZn_Ma00017 +# DepthFmt_z24_Cn_FZn_Ma40016 +# DepthFmt_z24_Cn_FZn_Ma80015 +# DepthFmt_z24_Cn_FZn_Mac0014 +# DepthFmt_z24_Cn_FZn_Mb00013 +# DepthFmt_z24_Cn_FZn_Mb40012 +# DepthFmt_z24_Cn_FZn_Mb80011 +# DepthFmt_z24_Cn_FZn_Mbc0010 +# DepthFmt_z24_Cn_FZn_Mc0000f +# DepthFmt_z24_Cn_FZn_Mc4000e +# DepthFmt_z24_Cn_FZn_Mc8000d +# DepthFmt_z24_Cn_FZn_Mcc000c +# DepthFmt_z24_Cn_FZn_Md0000b +# DepthFmt_z24_Cn_FZn_Md4000a +# DepthFmt_z24_Cn_FZn_Md80009 +# DepthFmt_z24_Cn_FZn_Mdc0008 +# DepthFmt_z24_Cn_FZn_Me00007 +# DepthFmt_z24_Cn_FZn_Me40006 +# DepthFmt_z24_Cn_FZn_Me80005 +# DepthFmt_z24_Cn_FZn_Mec0004 +# DepthFmt_z24_Cn_FZn_Mf00003 +# DepthFmt_z24_Cn_FZn_Mf40002 +# DepthFmt_z24_Cn_FZn_Mf80001 +# DepthFmt_z24_Cn_FZn_Mfc0000 +# DepthFmt_z24_Cn_FZn_Mffffff +# DepthFmt_z24_Cn_FZy_M00003f +# DepthFmt_z24_Cn_FZy_M03fc3e +# DepthFmt_z24_Cn_FZy_M07f83d +# DepthFmt_z24_Cn_FZy_M0bf43c +# DepthFmt_z24_Cn_FZy_M0ff03b +# DepthFmt_z24_Cn_FZy_M13ec3a +# DepthFmt_z24_Cn_FZy_M17e839 +# DepthFmt_z24_Cn_FZy_M1be438 +# DepthFmt_z24_Cn_FZy_M1fe037 +# DepthFmt_z24_Cn_FZy_M23dc36 +# DepthFmt_z24_Cn_FZy_M27d835 +# DepthFmt_z24_Cn_FZy_M2bd434 +# DepthFmt_z24_Cn_FZy_M2fd033 +# DepthFmt_z24_Cn_FZy_M33cc32 +# DepthFmt_z24_Cn_FZy_M37c831 +# DepthFmt_z24_Cn_FZy_M3bc430 +# DepthFmt_z24_Cn_FZy_M3fc02f +# DepthFmt_z24_Cn_FZy_M43bc2e +# DepthFmt_z24_Cn_FZy_M47b82d +# DepthFmt_z24_Cn_FZy_M4bb42c +# DepthFmt_z24_Cn_FZy_M4fb02b +# DepthFmt_z24_Cn_FZy_M53ac2a +# DepthFmt_z24_Cn_FZy_M57a829 +# DepthFmt_z24_Cn_FZy_M5ba428 +# DepthFmt_z24_Cn_FZy_M5fa027 +# DepthFmt_z24_Cn_FZy_M639c26 +# DepthFmt_z24_Cn_FZy_M679825 +# DepthFmt_z24_Cn_FZy_M6b9424 +# DepthFmt_z24_Cn_FZy_M6f9023 +# DepthFmt_z24_Cn_FZy_M738c22 +# DepthFmt_z24_Cn_FZy_M778821 +# DepthFmt_z24_Cn_FZy_M7b8420 +# DepthFmt_z24_Cn_FZy_M7f801f +# DepthFmt_z24_Cn_FZy_M837c1e +# DepthFmt_z24_Cn_FZy_M87781d +# DepthFmt_z24_Cn_FZy_M8b741c +# DepthFmt_z24_Cn_FZy_M8f701b +# DepthFmt_z24_Cn_FZy_M936c1a +# DepthFmt_z24_Cn_FZy_M976819 +# DepthFmt_z24_Cn_FZy_M9b6418 +# DepthFmt_z24_Cn_FZy_M9f6017 +# DepthFmt_z24_Cn_FZy_Ma35c16 +# DepthFmt_z24_Cn_FZy_Ma75815 +# DepthFmt_z24_Cn_FZy_Mab5414 +# DepthFmt_z24_Cn_FZy_Maf5013 +# DepthFmt_z24_Cn_FZy_Mb34c12 +# DepthFmt_z24_Cn_FZy_Mb74811 +# DepthFmt_z24_Cn_FZy_Mbb4410 +# DepthFmt_z24_Cn_FZy_Mbf400f +# DepthFmt_z24_Cn_FZy_Mc33c0e +# DepthFmt_z24_Cn_FZy_Mc7380d +# DepthFmt_z24_Cn_FZy_Mcb340c +# DepthFmt_z24_Cn_FZy_Mcf300b +# DepthFmt_z24_Cn_FZy_Md32c0a +# DepthFmt_z24_Cn_FZy_Md72809 +# DepthFmt_z24_Cn_FZy_Mdb2408 +# DepthFmt_z24_Cn_FZy_Mdf2007 +# DepthFmt_z24_Cn_FZy_Me31c06 +# DepthFmt_z24_Cn_FZy_Me71805 +# DepthFmt_z24_Cn_FZy_Meb1404 +# DepthFmt_z24_Cn_FZy_Mef1003 +# DepthFmt_z24_Cn_FZy_Mf30c02 +# DepthFmt_z24_Cn_FZy_Mf70801 +# DepthFmt_z24_Cn_FZy_Mfb0400 +# DepthFmt_z24_Cn_FZy_Mfeffff +# DepthFmt_z24_Cy_FZn_M00003f +# DepthFmt_z24_Cy_FZn_M04003e +# DepthFmt_z24_Cy_FZn_M08003d +# DepthFmt_z24_Cy_FZn_M0c003c +# DepthFmt_z24_Cy_FZn_M10003b +# DepthFmt_z24_Cy_FZn_M14003a +# DepthFmt_z24_Cy_FZn_M180039 +# DepthFmt_z24_Cy_FZn_M1c0038 +# DepthFmt_z24_Cy_FZn_M200037 +# DepthFmt_z24_Cy_FZn_M240036 +# DepthFmt_z24_Cy_FZn_M280035 +# DepthFmt_z24_Cy_FZn_M2c0034 +# DepthFmt_z24_Cy_FZn_M300033 +# DepthFmt_z24_Cy_FZn_M340032 +# DepthFmt_z24_Cy_FZn_M380031 +# DepthFmt_z24_Cy_FZn_M3c0030 +# DepthFmt_z24_Cy_FZn_M40002f +# DepthFmt_z24_Cy_FZn_M44002e +# DepthFmt_z24_Cy_FZn_M48002d +# DepthFmt_z24_Cy_FZn_M4c002c +# DepthFmt_z24_Cy_FZn_M50002b +# DepthFmt_z24_Cy_FZn_M54002a +# DepthFmt_z24_Cy_FZn_M580029 +# DepthFmt_z24_Cy_FZn_M5c0028 +# DepthFmt_z24_Cy_FZn_M600027 +# DepthFmt_z24_Cy_FZn_M640026 +# DepthFmt_z24_Cy_FZn_M680025 +# DepthFmt_z24_Cy_FZn_M6c0024 +# DepthFmt_z24_Cy_FZn_M700023 +# DepthFmt_z24_Cy_FZn_M740022 +# DepthFmt_z24_Cy_FZn_M780021 +# DepthFmt_z24_Cy_FZn_M7c0020 +# DepthFmt_z24_Cy_FZn_M80001f +# DepthFmt_z24_Cy_FZn_M84001e +# DepthFmt_z24_Cy_FZn_M88001d +# DepthFmt_z24_Cy_FZn_M8c001c +# DepthFmt_z24_Cy_FZn_M90001b +# DepthFmt_z24_Cy_FZn_M94001a +# DepthFmt_z24_Cy_FZn_M980019 +# DepthFmt_z24_Cy_FZn_M9c0018 +# DepthFmt_z24_Cy_FZn_Ma00017 +# DepthFmt_z24_Cy_FZn_Ma40016 +# DepthFmt_z24_Cy_FZn_Ma80015 +# DepthFmt_z24_Cy_FZn_Mac0014 +# DepthFmt_z24_Cy_FZn_Mb00013 +# DepthFmt_z24_Cy_FZn_Mb40012 +# DepthFmt_z24_Cy_FZn_Mb80011 +# DepthFmt_z24_Cy_FZn_Mbc0010 +# DepthFmt_z24_Cy_FZn_Mc0000f +# DepthFmt_z24_Cy_FZn_Mc4000e +# DepthFmt_z24_Cy_FZn_Mc8000d +# DepthFmt_z24_Cy_FZn_Mcc000c +# DepthFmt_z24_Cy_FZn_Md0000b +# DepthFmt_z24_Cy_FZn_Md4000a +# DepthFmt_z24_Cy_FZn_Md80009 +# DepthFmt_z24_Cy_FZn_Mdc0008 +# DepthFmt_z24_Cy_FZn_Me00007 +# DepthFmt_z24_Cy_FZn_Me40006 +# DepthFmt_z24_Cy_FZn_Me80005 +# DepthFmt_z24_Cy_FZn_Mec0004 +# DepthFmt_z24_Cy_FZn_Mf00003 +# DepthFmt_z24_Cy_FZn_Mf40002 +# DepthFmt_z24_Cy_FZn_Mf80001 +# DepthFmt_z24_Cy_FZn_Mfc0000 +# DepthFmt_z24_Cy_FZn_Mffffff +# DepthFmt_z24_Cy_FZy_M00003f +# DepthFmt_z24_Cy_FZy_M03fc3e +# DepthFmt_z24_Cy_FZy_M07f83d +# DepthFmt_z24_Cy_FZy_M0bf43c +# DepthFmt_z24_Cy_FZy_M0ff03b +# DepthFmt_z24_Cy_FZy_M13ec3a +# DepthFmt_z24_Cy_FZy_M17e839 +# DepthFmt_z24_Cy_FZy_M1be438 +# DepthFmt_z24_Cy_FZy_M1fe037 +# DepthFmt_z24_Cy_FZy_M23dc36 +# DepthFmt_z24_Cy_FZy_M27d835 +# DepthFmt_z24_Cy_FZy_M2bd434 +# DepthFmt_z24_Cy_FZy_M2fd033 +# DepthFmt_z24_Cy_FZy_M33cc32 +# DepthFmt_z24_Cy_FZy_M37c831 +# DepthFmt_z24_Cy_FZy_M3bc430 +# DepthFmt_z24_Cy_FZy_M3fc02f +# DepthFmt_z24_Cy_FZy_M43bc2e +# DepthFmt_z24_Cy_FZy_M47b82d +# DepthFmt_z24_Cy_FZy_M4bb42c +# DepthFmt_z24_Cy_FZy_M4fb02b +# DepthFmt_z24_Cy_FZy_M53ac2a +# DepthFmt_z24_Cy_FZy_M57a829 +# DepthFmt_z24_Cy_FZy_M5ba428 +# DepthFmt_z24_Cy_FZy_M5fa027 +# DepthFmt_z24_Cy_FZy_M639c26 +# DepthFmt_z24_Cy_FZy_M679825 +# DepthFmt_z24_Cy_FZy_M6b9424 +# DepthFmt_z24_Cy_FZy_M6f9023 +# DepthFmt_z24_Cy_FZy_M738c22 +# DepthFmt_z24_Cy_FZy_M778821 +# DepthFmt_z24_Cy_FZy_M7b8420 +# DepthFmt_z24_Cy_FZy_M7f801f +# DepthFmt_z24_Cy_FZy_M837c1e +# DepthFmt_z24_Cy_FZy_M87781d +# DepthFmt_z24_Cy_FZy_M8b741c +# DepthFmt_z24_Cy_FZy_M8f701b +# DepthFmt_z24_Cy_FZy_M936c1a +# DepthFmt_z24_Cy_FZy_M976819 +# DepthFmt_z24_Cy_FZy_M9b6418 +# DepthFmt_z24_Cy_FZy_M9f6017 +# DepthFmt_z24_Cy_FZy_Ma35c16 +# DepthFmt_z24_Cy_FZy_Ma75815 +# DepthFmt_z24_Cy_FZy_Mab5414 +# DepthFmt_z24_Cy_FZy_Maf5013 +# DepthFmt_z24_Cy_FZy_Mb34c12 +# DepthFmt_z24_Cy_FZy_Mb74811 +# DepthFmt_z24_Cy_FZy_Mbb4410 +# DepthFmt_z24_Cy_FZy_Mbf400f +# DepthFmt_z24_Cy_FZy_Mc33c0e +# DepthFmt_z24_Cy_FZy_Mc7380d +# DepthFmt_z24_Cy_FZy_Mcb340c +# DepthFmt_z24_Cy_FZy_Mcf300b +# DepthFmt_z24_Cy_FZy_Md32c0a +# DepthFmt_z24_Cy_FZy_Md72809 +# DepthFmt_z24_Cy_FZy_Mdb2408 +# DepthFmt_z24_Cy_FZy_Mdf2007 +# DepthFmt_z24_Cy_FZy_Me31c06 +# DepthFmt_z24_Cy_FZy_Me71805 +# DepthFmt_z24_Cy_FZy_Meb1404 +# DepthFmt_z24_Cy_FZy_Mef1003 +# DepthFmt_z24_Cy_FZy_Mf30c02 +# DepthFmt_z24_Cy_FZy_Mf70801 +# DepthFmt_z24_Cy_FZy_Mfb0400 +# DepthFmt_z24_Cy_FZy_Mfeffff + +#Image blit +# ImgBlt_BLENDAND_XRGB_B00000000 +# ImgBlt_BLENDAND_XRGB_B007FFFFF +# ImgBlt_BLENDAND_XRGB_B00800000 +# ImgBlt_BLENDAND_XRGB_B00D00000 +# ImgBlt_BLENDAND_XRGB_B03300000 +# ImgBlt_BLENDAND_XRGB_B44400000 +# ImgBlt_BLENDAND_XRGB_B444FFFFF +# ImgBlt_BLENDAND_XRGB_B66800000 +# ImgBlt_BLENDAND_XRGB_B7F800000 +# ImgBlt_BLENDAND_XRGB_B7FFFFFFF +# ImgBlt_BLENDAND_XRGB_B80000000 +# ImgBlt_BLENDAND_XRGB_B8FFFFFFF +# ImgBlt_BLENDAND_ZRGB_B007FFFFF +# ImgBlt_BLENDAND_ZRGB_B00800000 +# ImgBlt_BLENDAND_ZRGB_B00D00000 +# ImgBlt_BLENDAND_ZRGB_B03300000 +# ImgBlt_BLENDAND_ZRGB_B44400000 +# ImgBlt_BLENDAND_ZRGB_B444FFFFF +# ImgBlt_BLENDAND_ZRGB_B66800000 +# ImgBlt_BLENDAND_ZRGB_B7F800000 +# ImgBlt_SRCCOPY_ARGB_B00000000 +# ImgBlt_SRCCOPY_XRGB_B00000000 +# ImgBlt_SRCCOPY_ZRGB_B00000000 + +#Material alpha +# MatA_SMat_A0 +# MatA_SMat_A3D4CCCCD +# MatA_SMat_A3E800000 +# MatA_SMat_A3F000000 +# MatA_SMat_A3F400000 +# MatA_SMat_A3F800000 +# MatA_SMat_A40000000 +# MatA_SMat_ABF800000 +# MatA_SVDiffuse_A0 +# MatA_SVDiffuse_A3D4CCCCD +# MatA_SVDiffuse_A3E800000 +# MatA_SVDiffuse_A3F000000 +# MatA_SVDiffuse_A3F400000 +# MatA_SVDiffuse_A3F800000 +# MatA_SVDiffuse_A40000000 +# MatA_SVDiffuse_ABF800000 +# MatA_SVSpec_A0 +# MatA_SVSpec_A3D4CCCCD +# MatA_SVSpec_A3E800000 +# MatA_SVSpec_A3F000000 +# MatA_SVSpec_A3F400000 +# MatA_SVSpec_A3F800000 +# MatA_SVSpec_A40000000 +# MatA_SVSpec_ABF800000 + +#Material color +# 001_RG0_11 +# 011_rBg_11 +# 011_rG0_B1 +# 301_rG0_11 +# 310_rG0_11 +# 311_rG0_11 + +#Material color source +# FromMaterial +# FromVertexDiffuse +# FromVertexSpecular + +#SetVertexData +# SET_VERTEX_DATA2F_M +# SET_VERTEX_DATA2S-0001 +# SET_VERTEX_DATA2S-7FFF +# SET_VERTEX_DATA4F_M +# SET_VERTEX_DATA4S_M-0001 +# SET_VERTEX_DATA4S_M-7FFF +# SET_VERTEX_DATA4UB + +#Texture border +# 2D + +#Texgen with texture matrix +# Disabled_Arbitrary +# Disabled_Double +# Disabled_Half +# Disabled_Identity +# Disabled_RotateX +# Disabled_RotateY +# Disabled_RotateZ +# Disabled_ShiftHMinus +# Disabled_ShiftHPlus +# Disabled_ShiftVMinus +# Disabled_ShiftVPlus +# EyeLinear_Arbitrary +# EyeLinear_Double +# EyeLinear_Half +# EyeLinear_Identity +# EyeLinear_RotateX +# EyeLinear_RotateY +# EyeLinear_RotateZ +# EyeLinear_ShiftHMinus +# EyeLinear_ShiftHPlus +# EyeLinear_ShiftVMinus +# EyeLinear_ShiftVPlus +# NormalMap_Arbitrary +# NormalMap_Double +# NormalMap_Half +# NormalMap_Identity +# NormalMap_RotateX +# NormalMap_RotateY +# NormalMap_RotateZ +# NormalMap_ShiftHMinus +# NormalMap_ShiftHPlus +# NormalMap_ShiftVMinus +# NormalMap_ShiftVPlus +# ReflectionMap_Arbitrary +# ReflectionMap_Double +# ReflectionMap_Half +# ReflectionMap_Identity +# ReflectionMap_RotateX +# ReflectionMap_RotateY +# ReflectionMap_RotateZ +# ReflectionMap_ShiftHMinus +# ReflectionMap_ShiftHPlus +# ReflectionMap_ShiftVMinus +# ReflectionMap_ShiftVPlus + +#Texgen +# Disabled +# EyeLinear +# NormalMap +# ReflectionMap + +#Texture format +# TexFmt_A1R5G5B5 +# TexFmt_A1R5G5B5_L +# TexFmt_A4R4G4B4 +# TexFmt_A4R4G4B4_L +# TexFmt_A8B8G8R8 +# TexFmt_A8B8G8R8_L +# TexFmt_A8R8G8B8 +# TexFmt_A8R8G8B8_L +# TexFmt_A8Y8 +# TexFmt_AY8 +# TexFmt_AY8_L +# TexFmt_B8G8R8A8 +# TexFmt_B8G8R8A8_L +# TexFmt_DXT1 +# TexFmt_G8B8_L +# TexFmt_R5G6B5 +# TexFmt_R5G6B5_L +# TexFmt_R8G8B8A8 +# TexFmt_R8G8B8A8_L +# TexFmt_SZ_Index8_p128 +# TexFmt_SZ_Index8_p256 +# TexFmt_SZ_Index8_p32 +# TexFmt_SZ_Index8_p64 +# TexFmt_UYVY_L +# TexFmt_X1R5G5B5 +# TexFmt_X1R5G5B5_L +# TexFmt_X8R8G8B8 +# TexFmt_X8R8G8B8_L +# TexFmt_Y8 +# TexFmt_Y8_L +# TexFmt_YUY2_L + +#Texture Matrix +# Arbitrary +# Double +# Half +# Identity +# RotateX +# RotateY +# RotateZ +# ShiftHMinus +# ShiftHPlus +# ShiftVMinus +# ShiftVPlus + +#Texture render target +# TexFmt_A1R5G5B5 +# TexFmt_A1R5G5B5_L +# TexFmt_A4R4G4B4 +# TexFmt_A4R4G4B4_L +# TexFmt_A8B8G8R8 +# TexFmt_A8B8G8R8_L +# TexFmt_A8R8G8B8 +# TexFmt_A8R8G8B8_L +# TexFmt_A8Y8 +# TexFmt_AY8 +# TexFmt_AY8_L +# TexFmt_B8G8R8A8 +# TexFmt_B8G8R8A8_L +# TexFmt_DXT1 +# TexFmt_G8B8_L +# TexFmt_R5G6B5 +# TexFmt_R5G6B5_L +# TexFmt_R8G8B8A8 +# TexFmt_R8G8B8A8_L +# TexFmt_SZ_Index8_p128 +# TexFmt_SZ_Index8_p256 +# TexFmt_SZ_Index8_p32 +# TexFmt_SZ_Index8_p64 +# TexFmt_UYVY_L +# TexFmt_X1R5G5B5 +# TexFmt_X1R5G5B5_L +# TexFmt_X8R8G8B8 +# TexFmt_X8R8G8B8_L +# TexFmt_Y8 +# TexFmt_Y8_L +# TexFmt_YUY2_L + +#3D primitive +# LineLoop +# LineLoop-inlinearrays +# LineLoop-inlinebuf +# LineLoop-inlineelements +# LineStrip +# LineStrip-inlinearrays +# LineStrip-inlinebuf +# LineStrip-inlineelements +# Lines +# Lines-inlinearrays +# Lines-inlinebuf +# Lines-inlineelements +# Points +# Points-inlinearrays +# Points-inlinebuf +# Points-inlineelements +# Polygon +# Polygon-inlinearrays +# Polygon-inlinebuf +# Polygon-inlineelements +# QuadStrip +# QuadStrip-inlinearrays +# QuadStrip-inlinebuf +# QuadStrip-inlineelements +# Quads +# Quads-inlinearrays +# Quads-inlinebuf +# Quads-inlineelements +# TriFan +# TriFan-inlinearrays +# TriFan-inlinebuf +# TriFan-inlineelements +# TriStrip +# TriStrip-inlinearrays +# TriStrip-inlinebuf +# TriStrip-inlineelements +# Triangles +# Triangles-inlinearrays +# Triangles-inlinebuf +# Triangles-inlineelements + +#2D Lines +# 2DLine-R5G5B5-C000003E0-400_200-400_400 +# 2DLine-R5G6B5-C000007E0-400_200-400_400 +# 2DLine-R8G8B8-C00000000-400_200-400_400 +# 2DLine-R8G8B8-C0000FF00-400_200-400_400 +# 2DLine-R8G8B8-C0000FF00-444_222-444_444 +# 2DLine-R8G8B8-C00FF0000-400_200-400_400 +# 2DLine-R8G8B8-C00FFFFFF-0_0-639_479 +# 2DLine-R8G8B8-C00FFFFFF-222_222-222_222 +# 2DLine-R8G8B8-C00FFFFFF-400_0-400_479 +# 2DLine-R8G8B8-C00FFFFFF-400_300-400_301 +# 2DLine-R8G8B8-C00FFFFFF-400_300-401_300 +# 2DLine-R8G8B8-C00FFFFFF-639_479-0_0 +# 2DLine-R8G8B8-CFFFFFFFF-100_100-100_400 + +#Vertex shader rounding tests +# Geometry_0.000000 +# Geometry_0.001000 +# Geometry_0.500000 +# Geometry_0.562400 +# Geometry_0.562500 +# Geometry_0.562600 +# Geometry_0.999000 +# RenderTarget + +#Volume texture +# A1R5G5B5 +# A4R4G4B4 +# A8B8G8R8 +# A8R8G8B8 +# A8Y8 +# AY8 +# B8G8R8A8 +# DXT1 +# R5G6B5 +# R8G8B8A8 +# SZ_Index8 +# X1R5G5B5 +# X8R8G8B8 +# Y8 + +#W param +# w_gaps +# w_neg_strip +# w_pos_strip + +#Zero stride +# DrawArrays +# InlineElements diff --git a/test-pgraph/nxdk_pgraph_tests b/test-pgraph/nxdk_pgraph_tests new file mode 160000 index 0000000..0bfd392 --- /dev/null +++ b/test-pgraph/nxdk_pgraph_tests @@ -0,0 +1 @@ +Subproject commit 0bfd392c216807dd2ce2b7129c90f1bcb990d34a diff --git a/xemutest/__main__.py b/xemutest/__main__.py index ce62797..80e09ac 100644 --- a/xemutest/__main__.py +++ b/xemutest/__main__.py @@ -19,6 +19,7 @@ def main(): ap.add_argument('--xemu', help='Path to the xemu binary') ap.add_argument('--ffmpeg', help='Path to the ffmpeg binary or DISABLE') ap.add_argument('--no-fullscreen', action='store_true', help='Force xemu to run in a window') + ap.add_argument('--perceptualdiff', help='Path to the perceptualdiff binary or DISABLE') args = ap.parse_args() tests = [] @@ -49,6 +50,7 @@ def main(): os.path.abspath(os.path.expanduser(args.private)), args.xemu, args.ffmpeg, + args.perceptualdiff, args.no_fullscreen) for i, (test_name, test_cls) in enumerate(tests): diff --git a/xemutest/test_base.py b/xemutest/test_base.py index 0c14272..08f6dfc 100755 --- a/xemutest/test_base.py +++ b/xemutest/test_base.py @@ -8,8 +8,9 @@ import signal import time import platform import sys -from typing import Optional +from typing import Optional, Tuple +import pyfatx from pyfatx import Fatx @@ -27,6 +28,7 @@ class TestEnvironment: private_path: str, xemu_path: Optional[str], ffmpeg_path: Optional[str], + perceptualdiff_path: Optional[str], disable_fullscreen: bool = False): self.private_path = private_path @@ -40,12 +42,17 @@ class TestEnvironment: self.xemu_path = xemu_path self.ffmpeg_path = ffmpeg_path + self.perceptualdiff_path = perceptualdiff_path self.disable_fullscreen = disable_fullscreen @property def video_capture_enabled(self) -> bool: return self.ffmpeg_path != "DISABLE" + @property + def perceptualdiff_enabled(self) -> bool: + return self.perceptualdiff_path != "DISABLE" + class TestBase: """ @@ -58,7 +65,13 @@ class TestBase: Tester runs in current working directory and will generate some working files. """ - def __init__(self, test_env: TestEnvironment, results_path: str, iso_path: str): + def __init__( + self, + test_env: TestEnvironment, + xbox_results_path: str, + results_out_path: str, + iso_path: str, + timeout: int = 60): cur_dir = os.getcwd() self.flash_path = os.path.join(test_env.private_path, 'bios.bin') @@ -66,10 +79,10 @@ class TestBase: self.hdd_path = os.path.join(cur_dir, 'test.img') self.mount_path = os.path.join(cur_dir, 'xemu-hdd-mount') self.iso_path = iso_path - self.results_in_path = os.path.join(self.mount_path, 'results') - self.results_out_path = results_path + self.results_in_path = os.path.join(self.mount_path, xbox_results_path) + self.results_out_path = results_out_path self.video_capture_path = os.path.join(self.results_out_path, 'capture.mp4') - self.timeout = 60 + self.timeout = timeout self.test_env = test_env self.ffmpeg = None @@ -80,11 +93,13 @@ class TestBase: self.record_w: int = 0 self.record_h: int = 0 - def prepare_roms(self): + shutil.rmtree(results_out_path, True) + + def _prepare_roms(self): log.info('Preparing ROM images') # Nothing to do here yet - def prepare_hdd(self): + def _prepare_hdd(self): log.info('Preparing HDD image') disk_size = 8*1024*1024*1024 if os.path.exists(self.hdd_path): @@ -94,7 +109,9 @@ class TestBase: else: Fatx.create(self.hdd_path, disk_size) - def prepare_config(self): + self.setup_hdd_files(Fatx(self.hdd_path)) + + def _prepare_config(self): config = ( '[system]\n' f'flash_path = {self.flash_path}\n' f'bootrom_path = {self.mcpx_path}\n' @@ -107,7 +124,7 @@ class TestBase: with open('xemu.ini', 'w') as f: f.write(config) - def launch_video_capture(self): + def _launch_video_capture(self): if not self.test_env.video_capture_enabled: return ffmpeg_path = self.test_env.ffmpeg_path @@ -132,13 +149,13 @@ class TestBase: log.info('Launching FFMPEG (capturing to %s) with %s', self.video_capture_path, repr(c)) self.ffmpeg = subprocess.Popen(c, stdin=subprocess.PIPE) - def terminate_video_capture(self): + def _terminate_video_capture(self): if not self.test_env.video_capture_enabled or self.ffmpeg is None: return log.info('Shutting down FFMPEG') self.ffmpeg.communicate(b'q\n', timeout=5) - def launch_xemu(self): + def _launch_xemu(self): if platform.system() == 'Windows': c = [self.test_env.xemu_path, '-config_path', './xemu.ini', '-dvd_path', self.iso_path] @@ -180,7 +197,7 @@ class TestBase: log.exception('Failed to connect to xemu window') self.app = None - self.launch_video_capture() + self._launch_video_capture() while True: status = xemu.poll() @@ -195,9 +212,9 @@ class TestBase: break time.sleep(1) - self.terminate_video_capture() + self._terminate_video_capture() - def mount_hdd(self): + def _mount_hdd(self): log.info('Mounting HDD image') if os.path.exists(self.mount_path): shutil.rmtree(self.mount_path) @@ -206,14 +223,39 @@ class TestBase: # FIXME: Don't need to run here subprocess.run([sys.executable, '-m', 'pyfatx', '-x', self.hdd_path], check=True, cwd=self.mount_path) - def copy_results(self): + def _copy_results(self): log.info('Copying test results...') shutil.copytree(self.results_in_path, self.results_out_path, dirs_exist_ok=True) - def unmount_hdd(self): + def _unmount_hdd(self): log.info('Unmounting HDD image') # Nothing to do + def compare_images(self, expected_path: str, actual_path: str, diff_result_path: Optional[str] = None) -> Tuple[bool, str]: + """Perform a perceptual diff of the given images.""" + if not self.test_env.perceptualdiff_enabled: + return True, '' + + perceptualdiff_path = self.test_env.perceptualdiff_path + if not perceptualdiff_path: + if platform.system() == 'Windows': + perceptualdiff_path = 'perceptualdiff.exe' + else: + perceptualdiff_path = 'perceptualdiff' + + c = [perceptualdiff_path, expected_path, actual_path, '--verbose'] + if diff_result_path: + c.extend(['--output', diff_result_path]) + result = subprocess.run(c, capture_output=True) + return result.returncode == 0, result.stderr.decode('utf-8') + + def setup_hdd_files(self, fs: Fatx): + """Configure any files on the hard disk that are needed for the test. + + This method may be implemented by the subclass. + """ + del fs + def analyze_results(self): """Validate any files retrieved from the HDD. @@ -221,13 +263,23 @@ class TestBase: """ pass + def teardown_hdd_files(self, fs: Fatx): + """Clean up any files on the hard disk that should not outlive the test. + + This method may be implemented by the subclass. + """ + del fs + def run(self): os.makedirs(self.results_out_path, exist_ok=True) - self.prepare_roms() - self.prepare_hdd() - self.prepare_config() - self.launch_xemu() - self.mount_hdd() - self.copy_results() - self.unmount_hdd() - self.analyze_results() + self._prepare_roms() + self._prepare_hdd() + self._prepare_config() + self._launch_xemu() + self._mount_hdd() + self._copy_results() + self._unmount_hdd() + try: + self.analyze_results() + finally: + self.teardown_hdd_files(Fatx(self.hdd_path)) diff --git a/xemutest/test_nxdk_pgraph_tests.py b/xemutest/test_nxdk_pgraph_tests.py new file mode 100644 index 0000000..6c1da1c --- /dev/null +++ b/xemutest/test_nxdk_pgraph_tests.py @@ -0,0 +1,69 @@ +"""Test harness for nxdk_pgraph_tests.""" + +import logging +import os + +from pyfatx import Fatx +import test_base + +log = logging.getLogger(__file__) + +class TestNXDKPgraphTests(test_base.TestBase): + """Runs the nxdk_pgraph_tests suite and validates output.""" + + def __init__(self, test_env: test_base.TestEnvironment, results_path: str, test_data_path: str): + self.config_file_path = os.path.join(test_data_path, 'config.cnf') + if not self.config_file_path: + raise FileNotFoundError( + 'Test data was not installed with the package. You need to copy ' + f'config.cnf to {test_data_path}.') + + iso_path = os.path.join(test_data_path, 'nxdk_pgraph_tests.iso') + if not os.path.isfile(iso_path): + raise FileNotFoundError('Test data was not installed with the package. You need to build it and copy ' + f'to {test_data_path}.') + + self.golden_results_path = os.path.join(test_data_path, "golden_results") + + timeout_seconds = 5 * 60 + super().__init__(test_env, 'nxdk_pgraph_tests', results_path, iso_path, timeout_seconds) + + def setup_hdd_files(self, fs: Fatx): + with open(self.config_file_path, 'r') as config_file: + config_data = config_file.read() + fs.write('/pgraph_tests.cnf', config_data.encode('ascii')) + + def analyze_results(self): + diff_dir = '_diffs' + diff_results_dir = os.path.join(self.results_out_path, diff_dir) + os.makedirs(diff_results_dir, exist_ok=True) + + failed_comparisons = {} + + for root, dirnames, files in os.walk(self.results_out_path): + root = os.path.relpath(root, self.results_out_path) + if diff_dir in dirnames: + dirnames.remove(diff_dir) + + for file in files: + file_path = os.path.join(root, file) + expected_path = os.path.abspath(os.path.join(self.golden_results_path, file_path)) + actual_path = os.path.abspath(file_path) + diff_path = os.path.join(diff_results_dir, file_path) + + if not os.path.isfile(expected_path): + log.warning(f"Missing golden image {expected_path}") + continue + + match, message = self.compare_images(expected_path, actual_path, diff_path) + if not match: + failed_comparisons[file_path] = message + + if failed_comparisons: + raise Exception(f"Failed comparisons: {failed_comparisons}") + + def teardown_hdd_files(self, fs: Fatx): + try: + fs.unlink('/pgraph_tests.cnf') + except AssertionError: + pass diff --git a/xemutest/test_xbe.py b/xemutest/test_xbe.py index db8fcd8..d55f018 100644 --- a/xemutest/test_xbe.py +++ b/xemutest/test_xbe.py @@ -1,7 +1,6 @@ """Test harness for test-xbe.""" import os -from typing import Optional import test_base @@ -14,7 +13,7 @@ class TestXBE(test_base.TestBase): raise FileNotFoundError('Test data was not installed with the package. You need to build it and copy ' f'to {test_data_path}.') - super().__init__(test_env, results_path, iso_path) + super().__init__(test_env, 'results', results_path, iso_path) def analyze_results(self): with open(os.path.join(self.results_out_path, 'results.txt')) as f: