diff --git a/.github/actions/upload_build/action.yml b/.github/actions/upload_build/action.yml index 84f896586..83e7a2fd0 100644 --- a/.github/actions/upload_build/action.yml +++ b/.github/actions/upload_build/action.yml @@ -16,4 +16,5 @@ runs: - uses: actions/upload-artifact@v4 with: name: ${{ inputs.DEST_NAME }} - path: ${{ inputs.SOURCE_FILE }} \ No newline at end of file + path: ${{ inputs.SOURCE_FILE }} + if-no-files-found: error diff --git a/.github/workflows/build_3ds.yml b/.github/workflows/build_3ds.yml index 4bc07d802..7b2ff2d8a 100644 --- a/.github/workflows/build_3ds.yml +++ b/.github/workflows/build_3ds.yml @@ -24,13 +24,6 @@ jobs: run: | make 3ds - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 3DS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -56,3 +49,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: '3ds' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 3DS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml index 1ccca5234..87f63fcf3 100644 --- a/.github/workflows/build_android.yml +++ b/.github/workflows/build_android.yml @@ -99,13 +99,6 @@ jobs: # jarsigner -verbose # create aligned .apk file #$TOOLS_ROOT/zipalign -f 4 cc-signed.apk $ROOT_DIR/src/cc.apk - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile android build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -120,3 +113,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'android' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce android build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_dreamcast.yml b/.github/workflows/build_dreamcast.yml index 059030acf..39a2439e1 100644 --- a/.github/workflows/build_dreamcast.yml +++ b/.github/workflows/build_dreamcast.yml @@ -34,13 +34,6 @@ jobs: export PATH=/opt/toolchains/dc/kos/utils/:$PATH make dreamcast - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Dreamcast build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -66,3 +59,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'dreamcast' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Dreamcast build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_freebsd.yml b/.github/workflows/build_freebsd.yml index 319808665..a34f44c39 100644 --- a/.github/workflows/build_freebsd.yml +++ b/.github/workflows/build_freebsd.yml @@ -43,7 +43,7 @@ jobs: env: LIBS: "-lm -lpthread -lX11 -lXi -lGL -lexecinfo" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" PLAT32_FLAGS: "-fno-pie -fcf-protection=none -I freebsd32/include -L freebsd32/lib" PLAT64_FLAGS: "-fno-pie -fcf-protection=none -I freebsd64/include -L freebsd64/lib" @@ -52,13 +52,6 @@ jobs: i386-freebsd11-clang ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT32_FLAGS }} $LATEST_FLAG -o cc-fbsd32-gl1 ${{ env.LIBS }} x86_64-freebsd11-clang ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT64_FLAGS }} $LATEST_FLAG -o cc-fbsd64-gl1 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile FreeBSD build(s)' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -79,3 +72,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'freebsd' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce FreeBSD build(s)' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_haiku.yml b/.github/workflows/build_haiku.yml index 7d4f05c75..950c879ca 100644 --- a/.github/workflows/build_haiku.yml +++ b/.github/workflows/build_haiku.yml @@ -28,12 +28,6 @@ jobs: COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror" run: | x86_64-unknown-haiku-gcc ${{ env.SRCS }} -o ClassiCube-haiku ${{ env.COMMON_FLAGS }} ${{ env.LIBS }} - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Haiku build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -48,3 +42,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'haiku' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Haiku build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ios.yml b/.github/workflows/build_ios.yml index 63514e3f3..b88d2ce13 100644 --- a/.github/workflows/build_ios.yml +++ b/.github/workflows/build_ios.yml @@ -27,12 +27,6 @@ jobs: mkdir Payload mv ClassiCube.app Payload/ClassiCube.app zip -r cc.ipa Payload - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile iOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -46,3 +40,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ios' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce iOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index e0ab9a074..e06137f79 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -43,20 +43,13 @@ jobs: env: LIBS: "-lX11 -lXi -lpthread -lGL -lm -ldl" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" NIX32_FLAGS: "-no-pie -fno-pie -m32 -fcf-protection=none -L ./lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX32_FLAGS }} $LATEST_FLAG -o cc-nix32-gl1 ${{ env.LIBS }} gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX32_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -o cc-nix32-gl2 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Linux build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -78,6 +71,13 @@ jobs: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'linux32' + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Linux build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + #============================================ # =============== 64 BIT LINUX ============== # =========================================== @@ -107,7 +107,7 @@ jobs: env: LIBS: "-lX11 -lXi -lpthread -lGL -lm -ldl" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" NIX64_FLAGS: "-no-pie -fno-pie -m64 -fcf-protection=none -rdynamic -L ./lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" @@ -115,13 +115,6 @@ jobs: gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -o cc-nix64-gl1 ${{ env.LIBS }} gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -o cc-nix64-gl2 ${{ env.LIBS }} #gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 -o cc-sdl64-gl2 -lSDL2 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Linux build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -136,11 +129,11 @@ jobs: SOURCE_FILE: 'cc-nix64-gl2' DEST_NAME: 'ClassiCube-Linux64-ModernGL' - - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile.outcome == 'success' }} - with: - SOURCE_FILE: 'cc-sdl64-gl2' - DEST_NAME: 'ClassiCube-Linux64-SDL2' +# - uses: ./.github/actions/upload_build +# if: ${{ always() && steps.compile.outcome == 'success' }} +# with: +# SOURCE_FILE: 'cc-sdl64-gl2' +# DEST_NAME: 'ClassiCube-Linux64-SDL2' - uses: ./.github/actions/notify_success @@ -148,3 +141,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'linux64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Linux build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac32.yml b/.github/workflows/build_mac32.yml index 85bf6a32d..0d769852a 100644 --- a/.github/workflows/build_mac32.yml +++ b/.github/workflows/build_mac32.yml @@ -58,12 +58,6 @@ jobs: run: | PATH=$PATH:/usr/local/compiler/target/bin i386-apple-darwin8-lipo -create -output cc-mac32-universal cc-mac32-gl1 cc-mac32-ppc - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit macOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -96,3 +90,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'mac32' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit macOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac64.yml b/.github/workflows/build_mac64.yml index 072ae60f1..91bb8954e 100644 --- a/.github/workflows/build_mac64.yml +++ b/.github/workflows/build_mac64.yml @@ -36,12 +36,6 @@ jobs: clang ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.ARM64_FLAGS }} $LATEST_FLAG -o cc-mac-arm64 ${{ env.LIBS }} # https://wiki.freepascal.org/Code_Signing_for_macOS#Ad_hoc_signing - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit macOS builds' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -68,3 +62,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'mac64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit macOS builds' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_macclassic.yml b/.github/workflows/build_macclassic.yml index ecca53229..6b8656efc 100644 --- a/.github/workflows/build_macclassic.yml +++ b/.github/workflows/build_macclassic.yml @@ -27,13 +27,6 @@ jobs: make macclassic_68k RETRO68=/Retro68-build/toolchain ARCH_68040=1 - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Mac Classic build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -58,3 +51,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'macclassic' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Mac Classic build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_msdos.yml b/.github/workflows/build_msdos.yml index a6a80e141..55c72b565 100644 --- a/.github/workflows/build_msdos.yml +++ b/.github/workflows/build_msdos.yml @@ -27,20 +27,13 @@ jobs: - name: Compile MS dos build id: compile run: | - make CC=gcc dos RELEASE=1 - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile MS DOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + make CC=gcc dos - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'ClassiCube.exe' + SOURCE_FILE: 'CCDOS.EXE' DEST_NAME: 'ClassiCube.exe' @@ -49,3 +42,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'msdos' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce MS DOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_n64.yml b/.github/workflows/build_n64.yml index 524264208..e13f8b794 100644 --- a/.github/workflows/build_n64.yml +++ b/.github/workflows/build_n64.yml @@ -35,13 +35,6 @@ jobs: make tools-install cd $REAL_DIR make n64 - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile N64 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -62,3 +55,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'n64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce N64 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_nds.yml b/.github/workflows/build_nds.yml index 9ffd175fd..00830a6e1 100644 --- a/.github/workflows/build_nds.yml +++ b/.github/workflows/build_nds.yml @@ -30,13 +30,6 @@ jobs: make ds export BUILD_DSI=1 make ds - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile NDS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -48,7 +41,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-nds/cc-arm9.elf' + SOURCE_FILE: 'build/nds/cc-arm9.elf' DEST_NAME: 'ClassiCube-nds.elf' - uses: ./.github/actions/upload_build @@ -60,7 +53,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-dsi/cc-arm9.elf' + SOURCE_FILE: 'build/dsi/cc-arm9.elf' DEST_NAME: 'ClassiCube-dsi.elf' @@ -69,3 +62,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'nds' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce NDS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_netbsd.yml b/.github/workflows/build_netbsd.yml index 4d264f5cf..786301cc4 100644 --- a/.github/workflows/build_netbsd.yml +++ b/.github/workflows/build_netbsd.yml @@ -37,19 +37,12 @@ jobs: env: LIBS: "-lm -lpthread -lX11 -lXi -lGL -lexecinfo" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -Wl,-R/usr/X11R7/lib -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -Wl,-R/usr/X11R7/lib -fvisibility=hidden -rdynamic -Werror" PLAT64_FLAGS: "-fno-pie -fcf-protection=none -I netbsd64/include -L netbsd64/lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" x86_64-unknown-netbsd-gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT64_FLAGS }} $LATEST_FLAG -o cc-netbsd64-gl1 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile NetBSD build(s)' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -64,3 +57,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'netbsd' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce NetBSD build(s)' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps1.yml b/.github/workflows/build_ps1.yml index f96be84bf..9ab7c8e48 100644 --- a/.github/workflows/build_ps1.yml +++ b/.github/workflows/build_ps1.yml @@ -31,17 +31,10 @@ jobs: make ps1 - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile PS1 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-ps1/ClassiCube-PS1.elf' + SOURCE_FILE: 'build/ps1/ClassiCube-ps1.elf' DEST_NAME: 'ClassiCube-PS1.elf' - uses: ./.github/actions/upload_build @@ -68,3 +61,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps1' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS1 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps2.yml b/.github/workflows/build_ps2.yml index 432b0b374..d2d1c670d 100644 --- a/.github/workflows/build_ps2.yml +++ b/.github/workflows/build_ps2.yml @@ -28,13 +28,6 @@ jobs: run: | make ps2 - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile PS2 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -54,3 +47,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps2' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS2 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps3.yml b/.github/workflows/build_ps3.yml index 69bcba4af..84f8adfd7 100644 --- a/.github/workflows/build_ps3.yml +++ b/.github/workflows/build_ps3.yml @@ -34,13 +34,6 @@ jobs: make ps3 - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile PS3 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -65,3 +58,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps3' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS3 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_psp.yml b/.github/workflows/build_psp.yml index f87effee4..2488824f1 100644 --- a/.github/workflows/build_psp.yml +++ b/.github/workflows/build_psp.yml @@ -28,13 +28,6 @@ jobs: run: | make psp - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile PSP build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -54,3 +47,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'psp' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PSP build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_rpi.yml b/.github/workflows/build_rpi.yml index d1b3ff769..2bfcd84f8 100644 --- a/.github/workflows/build_rpi.yml +++ b/.github/workflows/build_rpi.yml @@ -41,13 +41,6 @@ jobs: LATEST_FLAG=-DCC_COMMIT_SHA=\"$GITHUB_SHA\" $CC ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.RPI32_FLAGS }} $LATEST_FLAG -o cc-rpi32 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile RPI 32 bit build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -64,6 +57,13 @@ jobs: WORKFLOW_NAME: 'rpi32' + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce RPI 32 bit build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + + #============================================ # ================ 64 BIT RPI =============== # =========================================== @@ -93,13 +93,6 @@ jobs: LATEST_FLAG=-DCC_COMMIT_SHA=\"$GITHUB_SHA\" $CC ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.RPI64_FLAGS }} $LATEST_FLAG -o cc-rpi64 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile RPI 64 bit build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -114,3 +107,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'rpi64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce RPI 64 bit build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index dba9c85b2..7ea0af117 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -16,30 +16,24 @@ jobs: timeout-minutes: 10 runs-on: ubuntu-latest container: - image: ijacquez/yaul:1.0.10 + image: ijacquez/yaul:latest steps: - uses: actions/checkout@v4 - name: Install prerequisites run: | - apt-get update - apt-get -y install curl + apt-get --allow-releaseinfo-change update + apt-get install -y curl - name: Compile Saturn build id: compile run: | make saturn - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Saturn build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-saturn/ClassiCube-saturn.elf' + SOURCE_FILE: 'build/saturn/ClassiCube-saturn.elf' DEST_NAME: 'ClassiCube-saturn.elf' - uses: ./.github/actions/upload_build @@ -60,3 +54,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'saturn' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Saturn build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_switch.yml b/.github/workflows/build_switch.yml index 73ae6a02b..510c45f51 100644 --- a/.github/workflows/build_switch.yml +++ b/.github/workflows/build_switch.yml @@ -24,13 +24,6 @@ jobs: run: | make switch - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Switch build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -50,3 +43,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'switch' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Switch build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_symbian.yml b/.github/workflows/build_symbian.yml index 92c41a744..b9eacf77a 100644 --- a/.github/workflows/build_symbian.yml +++ b/.github/workflows/build_symbian.yml @@ -42,15 +42,16 @@ jobs: SOURCE_FILE: 'misc/symbian/ClassiCube.sis' DEST_NAME: 'ClassiCube-Symbian.sis' - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Symbian build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/notify_success if: ${{ always() && steps.compile.outcome == 'success' }} with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'symbian' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Symbian build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_vita.yml b/.github/workflows/build_vita.yml index e79e5ee52..6c9ccc6b4 100644 --- a/.github/workflows/build_vita.yml +++ b/.github/workflows/build_vita.yml @@ -24,13 +24,6 @@ jobs: run: | make vita - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Vita build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -50,3 +43,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'vita' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Vita build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_webclient.yml b/.github/workflows/build_webclient.yml index 01f2746dd..60ea87dc5 100644 --- a/.github/workflows/build_webclient.yml +++ b/.github/workflows/build_webclient.yml @@ -26,12 +26,6 @@ jobs: run: | emcc ${{ env.SRCS }} -o ClassiCube.js -s WASM=0 -s NO_EXIT_RUNTIME=1 -s LEGACY_VM_SUPPORT=1 -s ALLOW_MEMORY_GROWTH=1 -s ABORTING_MALLOC=0 -s ENVIRONMENT=web -s TOTAL_STACK=256Kb --js-library src/webclient/interop_web.js -Os -g2 -s SINGLE_FILE sed -i 's#eventHandler.useCapture);#{ useCapture: eventHandler.useCapture, passive: false });#g' ClassiCube.js - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Webclient' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -45,3 +39,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'webclient' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Webclient' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_wiigc.yml b/.github/workflows/build_wiigc.yml index 3d6a6deb5..e65ff0d05 100644 --- a/.github/workflows/build_wiigc.yml +++ b/.github/workflows/build_wiigc.yml @@ -31,13 +31,6 @@ jobs: cp ClassiCube-wii.dol wiitest/apps/ClassiCube/boot.dol cp misc/wii/icon.png wiitest/apps/ClassiCube/icon.png cp misc/wii/meta.xml wiitest/apps/ClassiCube/meta.xml - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Wii/Gamecube build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -76,3 +69,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'wiigc' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Wii/Gamecube build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_wiiu.yml b/.github/workflows/build_wiiu.yml index 9e50194fa..5b219a359 100644 --- a/.github/workflows/build_wiiu.yml +++ b/.github/workflows/build_wiiu.yml @@ -23,13 +23,6 @@ jobs: id: compile run: | make wiiu - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile WiiU build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -56,3 +49,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'wiiu' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce WiiU build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_win-arm.yml b/.github/workflows/build_win-arm.yml index df06567fa..648c3ff08 100644 --- a/.github/workflows/build_win-arm.yml +++ b/.github/workflows/build_win-arm.yml @@ -35,18 +35,18 @@ jobs: armv7-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-arm32-d3d11.exe $LATEST_FLAG ${{ env.LIBS }} - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'cc-arm32-d3d11.exe' DEST_NAME: 'ClassiCube-arm32-Direct3D11.exe' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows-ARM build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' #============================================ # ============== ARM64 WINDOWS ============== # =========================================== @@ -72,13 +72,21 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Windows build' + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'cc-arm64-d3d11.exe' - DEST_NAME: 'ClassiCube-arm64-Direct3D11.exe' + DEST_NAME: 'ClassiCube-arm64-Direct3D11.exe' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows-ARM build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index aeb5f0719..6b7d23825 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -46,13 +46,6 @@ jobs: # mingw defaults to i686, but some really old CPUs only support i586 i686-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -march=i586 -o cc-w9x-ogl.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL1 -DCC_BUILD_NOSTDLIB ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -85,6 +78,13 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'win32' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' #============================================ @@ -118,13 +118,6 @@ jobs: x86_64-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d11.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 ${{ env.LIBS }} - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -149,3 +142,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'win64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox.yml b/.github/workflows/build_xbox.yml index 523ab31e0..4bec2f29f 100644 --- a/.github/workflows/build_xbox.yml +++ b/.github/workflows/build_xbox.yml @@ -29,13 +29,6 @@ jobs: eval $(/usr/src/nxdk/bin/activate -s) make xbox - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Xbox build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -55,3 +48,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'xbox' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Xbox build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox360.yml b/.github/workflows/build_xbox360.yml index e562895d6..8bae230c4 100644 --- a/.github/workflows/build_xbox360.yml +++ b/.github/workflows/build_xbox360.yml @@ -31,12 +31,6 @@ jobs: export DEVKITXENON=/usr/local/xenon export PATH=$PATH:$DEVKITXENON/bin:$DEVKITXENON/usr/bin make xbox360 - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to compile Xbox 360 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -57,3 +51,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'xbox360' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Xbox 360 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4aa09d71..121f0855b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -113,13 +113,6 @@ jobs: make_unix_tar cc-linux32.tar.gz cc-linux-32 make_unix_tar cc-linux64.tar.gz cc-linux-64 - - - - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} - with: - NOTIFY_MESSAGE: 'Failed to produce release' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' # Generate Linux release files @@ -218,4 +211,12 @@ jobs: if: ${{ always() && steps.compile.outcome == 'success' }} with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' - WORKFLOW_NAME: 'release' \ No newline at end of file + WORKFLOW_NAME: 'release' + + + # Log any failure + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce release' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.gitignore b/.gitignore index 7e03f9bf7..43116c055 100644 --- a/.gitignore +++ b/.gitignore @@ -26,23 +26,14 @@ project.xcworkspace/ xcuserdata/ # Nintendo Console build results -build-3ds/ build-nds/ build-dsi/ build-n64/ -build-gc/ -build-wii/ -build-wiiu/ -build-switch/ classicube.nds # SEGA console build results -build-32x/ -build-saturn/ -build-dc/ IP.BIN ISO_FILES/ -third_party/gldc/libGLdc.a cd/ # Microsoft console build results @@ -55,20 +46,12 @@ misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl # Sony console build results -build-ps2/ -build-ps3/ -build-ps4/ -build-psp/ -build-vita/ EBOOT.PBP PARAM.SFO param.sfo eboot.bin pkg.gp4 -# Desktop build results -build-amiga-68k/ - # Build results [Dd]ebug/ [Rr]elease/ @@ -107,13 +90,19 @@ fontscache.txt CWSDPMI.EXE CWSDPMI.SWP OPTIONS.TXT +CCDOS.EXE # Android source files need to be included !android/app/src/main/java/com/classicube -# Flatpak wrapper which needs to be included +# Flatpak wrapper needs to be included !misc/flatpak/ClassiCubeLauncher +# UWP files needs to be included +!misc/UWP/ClassiCube-UWP.sln +!misc/UWP/ClassiCube-UWP.vcxproj +!misc/UWP/ClassiCube-UWP.vcxproj.filters + # CMake files CMakeFiles/ CMakeCache.txt diff --git a/Makefile b/Makefile index e48ba190a..77d385442 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ LDFLAGS = -g -rdynamic ENAME = ClassiCube # Name of the final target file # (usually this is the executable, but e.g. is the app bundle on macOS) -TARGET := $(ENAME) +TARGET := $(ENAME) # Enables dependency tracking (https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/) # This ensures that changing a .h file automatically results in the .c files using it being auto recompiled when next running make @@ -88,15 +88,16 @@ endif ifeq ($(PLAT),hp-ux) CC = gcc + CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_DEFAULT_SOURCE -D_BSD_SOURCE LDFLAGS = - LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib -lGL -lpthread + LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib/hpux32 -lGL -lpthread BUILD_DIR = build/hpux endif ifeq ($(PLAT),darwin) OBJECTS += $(BUILD_DIR)/src/Window_cocoa.o LIBS = - LDFLAGS = -rdynamic -framework Cocoa -framework OpenGL -framework IOKit -lobjc + LDFLAGS = -rdynamic -framework Security -framework Cocoa -framework OpenGL -framework IOKit -lobjc BUILD_DIR = build/macos TARGET = $(ENAME).app endif @@ -172,28 +173,24 @@ ifeq ($(PLAT),riscos) BUILD_DIR = build/riscos endif -ifeq ($(PLAT),dos) - CC = i586-pc-msdosdjgpp-gcc - LIBS = - LDFLAGS = -g +ifeq ($(PLAT),wince) + CC = arm-mingw32ce-gcc OEXT = .exe - BUILD_DIR = build/dos - BEARSSL = 0 - - BUILD_DIRS += $(BUILD_DIR)/src/msdos - C_SOURCES += $(wildcard src/msdos/*.c) + CFLAGS += -march=armv5tej -mcpu=arm926ej-s -DUNICODE -D_WIN32_WCE + LDFLAGS = -g + LIBS = -lcoredll -lws2 + BUILD_DIR = build/wince endif - -ifdef SDL2 +ifdef BUILD_SDL2 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 LIBS += -lSDL2 endif -ifdef SDL3 +ifdef BUILD_SDL3 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL3 LIBS += -lSDL3 endif -ifdef TERMINAL +ifdef BUILD_TERMINAL CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_TERMINAL -DCC_GFX_BACKEND=CC_GFX_BACKEND_SOFTGPU LIBS := $(subst mwindows,mconsole,$(LIBS)) endif @@ -241,16 +238,16 @@ serenityos: irix: $(MAKE) $(TARGET) PLAT=irix riscos: - $(MAKE) $(TARGET) PLAT=riscos -dos: - $(MAKE) $(TARGET) PLAT=dos + $(MAKE) $(TARGET) PLAT=riscos +wince: + $(MAKE) $(TARGET) PLAT=wince # Default overrides sdl2: - $(MAKE) $(TARGET) SDL2=1 + $(MAKE) $(TARGET) BUILD_SDL2=1 sdl3: - $(MAKE) $(TARGET) SDL3=1 + $(MAKE) $(TARGET) BUILD_SDL3=1 terminal: - $(MAKE) $(TARGET) TERMINAL=1 + $(MAKE) $(TARGET) BUILD_TERMINAL=1 release: $(MAKE) $(TARGET) RELEASE=1 @@ -283,7 +280,7 @@ n64: gba: $(MAKE) -f misc/gba/Makefile ds: - $(MAKE) -f misc/ds/Makefile + $(MAKE) -f misc/nds/Makefile 3ds: $(MAKE) -f misc/3ds/Makefile gamecube: @@ -296,14 +293,18 @@ switch: $(MAKE) -f misc/switch/Makefile os/2: $(MAKE) -f misc/os2/Makefile +dos: + $(MAKE) -f misc/msdos/Makefile macclassic_68k: $(MAKE) -f misc/macclassic/Makefile_68k macclassic_ppc: $(MAKE) -f misc/macclassic/Makefile_ppc -amiga_68k: +amiga_gcc: $(MAKE) -f misc/amiga/Makefile_68k -amiga_ppc: - $(MAKE) -f misc/amiga/Makefile_ppc +amiga: + $(MAKE) -f misc/amiga/Makefile +atari_st: + $(MAKE) -f misc/atari_st/Makefile # Cleans up all build .o files clean: diff --git a/misc/32x/32x.h b/misc/32x/32x.h index 1d45a3f3d..faad402cd 100644 --- a/misc/32x/32x.h +++ b/misc/32x/32x.h @@ -122,7 +122,6 @@ extern "C" { extern void fast_memcpy(void *dst, void *src, int len); extern void CacheControl(int mode); extern void CacheClearLine(void* ptr); -extern void ScreenStretch(int src, int width, int height, int interp); #ifdef __cplusplus } diff --git a/misc/32x/sh2_crt0.s b/misc/32x/sh2_crt0.s index 020718f72..45a1d141f 100644 --- a/misc/32x/sh2_crt0.s +++ b/misc/32x/sh2_crt0.s @@ -29,19 +29,19 @@ ! Master Vector Base Table at 0x06000000 - .long mstart /* Cold Start PC */ - .long 0x0603FC00 /* Cold Start SP */ - .long mstart /* Manual Reset PC */ - .long 0x0603FC00 /* Manual Reset SP */ - .long main_err /* Illegal instruction */ - .long 0x00000000 /* reserved */ - .long main_err /* Invalid slot instruction */ - .long 0x20100400 /* reserved */ - .long 0x20100420 /* reserved */ - .long main_err /* CPU address error */ - .long main_err /* DMA address error */ - .long main_err /* NMI vector */ - .long main_err /* User break vector */ + .long mstart /* 0, Cold Start PC */ + .long 0x0603FC00 /* 1, Cold Start SP */ + .long mstart /* 2, Manual Reset PC */ + .long 0x0603FC00 /* 3, Manual Reset SP */ + .long main_err /* 4, Illegal instruction */ + .long _wdt_handler/* 5, reserved - repurposed for WDT */ + .long main_err /* 6, Invalid slot instruction */ + .long 0x20100400 /* 7, reserved */ + .long 0x20100420 /* 8, reserved */ + .long main_err /* 9, CPU address error */ + .long main_err /* 10, DMA address error */ + .long main_err /* 11, NMI vector */ + .long main_err /* 12, User break vector */ .space 76 /* reserved */ .long main_err /* TRAPA #32 */ .long main_err /* TRAPA #33 */ @@ -637,81 +637,6 @@ _CacheControl: _sh2_cctl: .long 0xFFFFFE92 -! void ScreenStretch(int src, int width, int height, int interp); -! On entry: r4 = src pointer, r5 = width, r6 = height, r7 = interpolate - - .align 4 - .global _ScreenStretch -_ScreenStretch: - cmp/pl r7 - bt ss_interp - -! stretch screen without interpolation - -0: - mov r5,r3 - shll r3 - mov r3,r2 - shll r2 - add r4,r3 - add r4,r2 -1: - add #-2,r3 - mov.w @r3,r0 - extu.w r0,r1 - shll16 r0 - or r1,r0 - mov.l r0,@-r2 - cmp/eq r3,r4 - bf 1b - - /* next line */ - mov.w ss_pitch,r0 - dt r6 - bf/s 0b - add r0,r4 - rts - nop - -ss_interp: - -! stretch screen with interpolation - -0: - mov r5,r3 - shll r3 - mov r3,r2 - shll r2 - add r4,r3 - add r4,r2 - mov #0,r7 -1: - add #-2,r3 - mov.w @r3,r0 - mov.w ss_mask,r1 - and r0,r1 /* masked curr pixel */ - shll16 r0 - add r1,r7 /* add to masked prev pixel */ - shlr r7 /* blended pixel */ - or r7,r0 /* curr pixel << 16 | blended pixel */ - mov r1,r7 /* masked prev pixel = masked curr pixel */ - mov.l r0,@-r2 - cmp/eq r3,r4 - bf 1b - - /* next line */ - mov.w ss_pitch,r0 - dt r6 - bf/s 0b - add r0,r4 - rts - nop - -ss_mask: - .word 0x7BDE -ss_pitch: - .word 640 - .align 2 .text diff --git a/misc/3ds/Makefile b/misc/3ds/Makefile index 902b47195..9b3005e47 100644 --- a/misc/3ds/Makefile +++ b/misc/3ds/Makefile @@ -46,7 +46,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- ARCH = -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS = -g -Wall -O2 -mword-relocations -ffunction-sections $(ARCH) $(INCLUDE) -D__3DS__ +CFLAGS = -g -Wall -O2 -mword-relocations -ffunction-sections $(ARCH) $(INCLUDE) -D__3DS__ -DPLAT_3DS ASFLAGS = -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) @@ -121,7 +121,7 @@ $(BUILD_DIR)/%.shbin: misc/3ds/%.v.pica $(PICASSO) $< -o $@ $(BUILD_DIR)/%.shbin.o: $(BUILD_DIR)/%.shbin - $(BIN2S) $< | $(ARM_AS) -o $@ + $(BIN2S) $< | $(ARM_CC) -x assembler-with-cpp -c - -o $@ #--------------------------------------------------------------------------------- diff --git a/misc/3ds/README.md b/misc/3ds/README.md new file mode 100644 index 000000000..e3bd113ad --- /dev/null +++ b/misc/3ds/README.md @@ -0,0 +1,15 @@ +To see debug log messages in Citra: + +1) Make sure log level set to "Debug.Emulated:Debug" + +--- + +Commands used to generate the .bin files: + +`bannertool makebanner -i banner.png -a audio.wav -o banner.bin` + +`bannertool makesmdh -s ClassiCube -l ClassiCube -p UnknownShadow200 -i icon.png -o icon.bin` + +---- + +Debug log messages output to debug service, so may be possible to see from console via remote gdb diff --git a/misc/3ds/coloured.v.pica b/misc/3ds/coloured.v.pica index d0b374ddf..44e4a3202 100644 --- a/misc/3ds/coloured.v.pica +++ b/misc/3ds/coloured.v.pica @@ -1,11 +1,15 @@ ; Vertex shader for rendering coloured vertices for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -16,14 +20,11 @@ .alias in_col v1 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col diff --git a/misc/3ds/offset.v.pica b/misc/3ds/offset.v.pica index 948143c2f..a42afe5ba 100644 --- a/misc/3ds/offset.v.pica +++ b/misc/3ds/offset.v.pica @@ -1,12 +1,15 @@ ; Vertex shader for rendering textured vertices with an offset for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; -.fvec tex_offset; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -19,19 +22,16 @@ .alias in_tex v2 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col ; out_tex = in_tex + tex_offset - add out_tex, tex_offset, in_tex + add out_tex, TEX_OFFSET, in_tex end .end diff --git a/misc/3ds/readme.md b/misc/3ds/readme.md deleted file mode 100644 index 85bc067e0..000000000 --- a/misc/3ds/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -Commands used to generate the .bin files: - -`bannertool makebanner -i banner.png -a audio.wav -o banner.bin` - -`bannertool makesmdh -s ClassiCube -l ClassiCube -p UnknownShadow200 -i icon.png -o icon.bin` \ No newline at end of file diff --git a/misc/3ds/textured.v.pica b/misc/3ds/textured.v.pica index 66aa92791..d398f2a15 100644 --- a/misc/3ds/textured.v.pica +++ b/misc/3ds/textured.v.pica @@ -1,11 +1,15 @@ ; Vertex shader for rendering textured vertices for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -18,14 +22,11 @@ .alias in_tex v2 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col diff --git a/misc/UWP/ClassiCube-UWP.sln b/misc/UWP/ClassiCube-UWP.sln new file mode 100644 index 000000000..080a57bff --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32002.261 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassiCube-UWP", "ClassiCube-UWP.vcxproj", "{A901236D-C8EF-4041-966F-46F17511E342}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.ActiveCfg = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.Build.0 = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.Deploy.0 = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.Build.0 = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.ActiveCfg = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.Build.0 = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.Deploy.0 = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.ActiveCfg = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.Build.0 = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.Deploy.0 = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.ActiveCfg = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.Build.0 = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.Deploy.0 = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.ActiveCfg = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.Build.0 = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.Deploy.0 = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.ActiveCfg = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.Build.0 = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.Deploy.0 = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.ActiveCfg = Release|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.Build.0 = Release|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AB4A9C28-F91F-439E-8D2E-E54273138ADC} + EndGlobalSection +EndGlobal diff --git a/misc/UWP/ClassiCube-UWP.vcxproj b/misc/UWP/ClassiCube-UWP.vcxproj new file mode 100644 index 000000000..eee893422 --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.vcxproj @@ -0,0 +1,432 @@ + + + + {a901236d-c8ef-4041-966f-46f17511e342} + ClassiCube_UWP + en-US + 14.0 + true + Windows Store + 10.0.20348.0 + 10.0.10240.0 + 10.0 + false + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + + + + + + + + + + + + + + + + + + + + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + + + + \ No newline at end of file diff --git a/misc/UWP/ClassiCube-UWP.vcxproj.filters b/misc/UWP/ClassiCube-UWP.vcxproj.filters new file mode 100644 index 000000000..5656b770d --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.vcxproj.filters @@ -0,0 +1,445 @@ + + + + + a901236d-c8ef-4041-966f-46f17511e342 + + + {93fa4266-80e4-4bbf-a7fa-c47e07da5098} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + + + + + \ No newline at end of file diff --git a/misc/amiga/Makefile b/misc/amiga/Makefile new file mode 100644 index 000000000..0d5ee083c --- /dev/null +++ b/misc/amiga/Makefile @@ -0,0 +1,42 @@ +TARGET := ClassiCube-amiga +BUILD_DIR := build/amiga +SOURCE_DIRS := src src/amiga + +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) + + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +CC = vc +aos68k +CFLAGS = -rmcfg-amiga-softfloat -O1 -DPLAT_AMIGA + +AS = vasmm68k_mot +ASFLAGS = -Fvobj -m68000 -no-fpu + +LDFLAGS = $(CFLAGS) +LDLIBS = -lamiga -lmsoft + + +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) -final -o $@ $^ $(LDLIBS) + + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/%.o : src/amiga/%.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/misc/amiga/Makefile_68k b/misc/amiga/Makefile_68k index 43276ca2a..207b76f71 100644 --- a/misc/amiga/Makefile_68k +++ b/misc/amiga/Makefile_68k @@ -1,20 +1,23 @@ -AS=m68k-amigaos-as -CC=m68k-amigaos-gcc -CXX=m68k-amigaos-g++ +TARGET := ClassiCube-amiga +BUILD_DIR := build/amiga_68k +SOURCE_DIRS := src src/amiga -CFLAGS :=-O1 -fno-math-errno -DPLAT_AMIGA -DCC_BUILD_NOFPU -TARGET := ClassiCube-68k -BUILD_DIR := build-amiga-68k -SOURCE_DIR := src -LDFLAGS := +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -C_SOURCES := $(wildcard $(SOURCE_DIR)/*.c) -C_ASSEMS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.S, $(C_SOURCES)) -C_OBJECTS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(C_SOURCES)) + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +AS := m68k-amigaos-as +CC := m68k-amigaos-gcc +CXX := m68k-amigaos-g++ +CFLAGS := -O1 -fno-math-errno -DPLAT_AMIGA -DCC_BUILD_NOFPU # Dependency tracking DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d -DEPFILES := $(C_OBJECTS:%.o=%.d) +DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- @@ -32,10 +35,13 @@ $(TARGET).exe: $(C_OBJECTS) #--------------------------------------------------------------------------------- # object generation #--------------------------------------------------------------------------------- -$(C_OBJECTS): $(BUILD_DIR)/%.o : $(BUILD_DIR)/%.S +$(BUILD_DIR)/%.o : src/amiga/%.S $(AS) $< -o $@ -$(C_ASSEMS): $(BUILD_DIR)/%.S : $(SOURCE_DIR)/%.c +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ + +$(BUILD_DIR)/%.o : src/amiga/%.c $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ # Dependency tracking diff --git a/misc/atari_st/Makefile b/misc/atari_st/Makefile new file mode 100644 index 000000000..a415dc85d --- /dev/null +++ b/misc/atari_st/Makefile @@ -0,0 +1,42 @@ +TARGET := ClassiCube-atari +BUILD_DIR := build/atari_st +SOURCE_DIRS := src src/atari_st + +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) + + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +CC = vc +tos +CFLAGS = -O1 -DPLAT_ATARIOS + +AS = vasmm68k_mot +ASFLAGS = -Fvobj -m68000 -no-fpu + +LDFLAGS = $(CFLAGS) +LDLIBS = -lm + + +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).tos + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(TARGET).tos: $(OBJS) + $(CC) $(LDFLAGS) -final -o $@ $^ $(LDLIBS) + + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/%.o : src/atari_st/%.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/misc/dreamcast/Makefile b/misc/dreamcast/Makefile index 93ec9566e..b2c135503 100644 --- a/misc/dreamcast/Makefile +++ b/misc/dreamcast/Makefile @@ -31,7 +31,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -DNDEBUG -O3 -fipa-pta -fno-pie -flto=auto -fomit-frame-pointer -fbuiltin -ffast-math -ffp-contract=fast -mfsrra -mfsca -pipe -fno-math-errno +CFLAGS = -g -DNDEBUG -O3 -fipa-pta -fno-pie -flto=auto -fomit-frame-pointer -fbuiltin -ffast-math -ffp-contract=fast -mfsrra -mfsca -pipe -fno-math-errno -DPLAT_DREAMCAST LDFLAGS = -g # Additional libraries to link against diff --git a/misc/gba/README.md b/misc/gba/README.md new file mode 100644 index 000000000..64b04c9c5 --- /dev/null +++ b/misc/gba/README.md @@ -0,0 +1,3 @@ +To see debug log messages in mGBA: + +1) In the UI, make sure in Tools > Logging, that Debugger is enabled diff --git a/misc/gc/Makefile b/misc/gc/Makefile index 3d5179f72..f1d1d03bc 100644 --- a/misc/gc/Makefile +++ b/misc/gc/Makefile @@ -33,7 +33,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- MACHDEP = -DGEKKO -mogc -mcpu=750 -meabi -mhard-float -CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include +CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include -DPLAT_GCWII LDFLAGS = -g $(MACHDEP) -L$(DEVKITPRO)/libogc/lib/cube # Additional libraries to link against diff --git a/misc/gc/README.md b/misc/gc/README.md new file mode 100644 index 000000000..ba317114e --- /dev/null +++ b/misc/gc/README.md @@ -0,0 +1,5 @@ +To see debug log messages in Dolphin: + +1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu +2) Make sure "OSReport EXI (OSREPORT)" log type is enabled +3) In the UI, make sure 'Show log' checkbox is checked in View menu diff --git a/misc/ios/Info.plist b/misc/ios/Info.plist index a4b063668..695b3943a 100644 --- a/misc/ios/Info.plist +++ b/misc/ios/Info.plist @@ -18,6 +18,16 @@ 1.0 CFBundleVersion 1 + LSApplicationCategoryType + public.app-category.games + GCSupportsGameMode + + LSSupportsGameMode + + UIFileSharingEnabled + + LSSupportsOpeningDocumentsInPlace + LSRequiresIPhoneOS NSPhotoLibraryAddUsageDescription @@ -138,4 +148,4 @@ - \ No newline at end of file + diff --git a/misc/macOS/info.plist b/misc/macOS/info.plist index 21fe5b85d..b14b52894 100644 --- a/misc/macOS/info.plist +++ b/misc/macOS/info.plist @@ -16,5 +16,11 @@ APPL CFBundleDisplayName ClassiCube + LSApplicationCategoryType + public.app-category.games + GCSupportsGameMode + + LSSupportsGameMode + diff --git a/misc/macclassic/Makefile_68k b/misc/macclassic/Makefile_68k index 070a6ba64..4c8d88342 100644 --- a/misc/macclassic/Makefile_68k +++ b/misc/macclassic/Makefile_68k @@ -19,7 +19,7 @@ ifdef ARCH_68040 else TARGET := ClassiCube-68k BUILD_DIR := build/mac_68k - CFLAGS += -DCC_BUILD_NOFPU -DCC_BUILD_TINYMEM + CFLAGS += -DCC_BUILD_NOFPU -DCC_BUILD_TINYMEM -DCC_GFX_BACKEND=CC_GFX_BACKEND_SOFTMIN endif SOURCE_DIR := src diff --git a/misc/msdos/Makefile b/misc/msdos/Makefile new file mode 100644 index 000000000..d4f5fb978 --- /dev/null +++ b/misc/msdos/Makefile @@ -0,0 +1,49 @@ +CC=i586-pc-msdosdjgpp-gcc + +CFLAGS =-O1 -fno-math-errno -Werror -Wno-error=missing-braces -Wno-error=strict-aliasing +LDFLAGS=-g + +TARGET := CCDOS +BUILD_DIR := build/msdos +SOURCE_DIRS := src src/msdos + +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o))) + +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(C_OBJECTS:%.o=%.d) + + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).EXE + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# executable generation +#--------------------------------------------------------------------------------- +$(TARGET).EXE: $(OBJS) + $(CC) $(OBJS) -o $@ $(LDFLAGS) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o : src/msdos/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +# Dependency tracking +$(DEPFILES): + +include $(wildcard $(DEPFILES)) diff --git a/misc/n64/Makefile b/misc/n64/Makefile index c243c55fd..ee958fc66 100644 --- a/misc/n64/Makefile +++ b/misc/n64/Makefile @@ -4,16 +4,24 @@ N64_ROM_TITLE = "ClassiCube" N64_ROM_RTC = true TARGET = ClassiCube-n64 N64_MKDFS_ROOT = "misc/n64/files" +SRC_DIRS = CFILES := $(notdir $(wildcard src/*.c)) OFILES := $(CFILES:.c=.o) rsp_gpu.o OBJS := $(addprefix $(BUILD_DIR)/,$(OFILES)) -CFLAGS := -Wno-error=missing-braces -Wno-error=strict-aliasing -Wno-error=incompatible-pointer-types +CFLAGS := -Wno-error=missing-braces -Wno-error=strict-aliasing -Wno-error=incompatible-pointer-types -DPLAT_N64 + + +default: $(BUILD_DIR) $(TARGET).z64 + +clean: + rm -rf $(BUILD_DIR) $(TARGET).z64 + +$(BUILD_DIR): + mkdir -p $@ -default: $(TARGET).z64 $(BUILD_DIR)/%.o: src/%.c - @mkdir -p $(dir $@) @echo " [CC] $<" $(CC) -c $(CFLAGS) -o $@ $< @@ -26,8 +34,4 @@ $(BUILD_DIR)/filesystem.dfs: misc/n64/files/default.zip $(BUILD_DIR)/ClassiCube-n64.elf: $(OBJS) -clean: - rm -rf $(BUILD_DIR) $(TARGET).z64 -.PHONY: clean - -include $(wildcard $(BUILD_DIR)/*.d) diff --git a/misc/n64/rsp_gpu.S b/misc/n64/rsp_gpu.S index 569918b80..1f9f2e1b0 100644 --- a/misc/n64/rsp_gpu.S +++ b/misc/n64/rsp_gpu.S @@ -294,14 +294,17 @@ GL_TnL: ssv vcspos_i.W, SCREEN_VTX_W+0, vtx2 ssv vcspos_f.W, SCREEN_VTX_W+2, vtx2 + // Perspective division vmudl v___, vcspos_f, vinvw_f.wwwwWWWW vmadm v___, vcspos_i, vinvw_f.wwwwWWWW vmadn vscreenpos_f, vcspos_f, vinvw_i.wwwwWWWW vmadh vscreenpos_i, vcspos_i, vinvw_i.wwwwWWWW + // Clip against guard planes vch v___, vguard_i, vguard_i.wwwwWWWW vcl v___, vguard_f, vguard_f.wwwwWWWW + // Viewport transform vmudn v___, vscreenpos_f, vviewscale vmadh v___, vscreenpos_i, vviewscale vmadh vscreenpos_i, vviewoff, K1 diff --git a/misc/ds/Makefile b/misc/nds/Makefile similarity index 81% rename from misc/ds/Makefile rename to misc/nds/Makefile index 3c1871503..b10e01386 100644 --- a/misc/ds/Makefile +++ b/misc/nds/Makefile @@ -7,7 +7,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external GAME_TITLE := ClassiCube GAME_SUBTITLE := Built with BlocksDS GAME_AUTHOR := ClassiCube team -GAME_ICON := misc/ds/icon.bmp +GAME_ICON := misc/nds/icon.bmp GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_SUBTITLE);$(GAME_AUTHOR) @@ -36,15 +36,15 @@ endif all: $(ROM) clean: - $(MAKE) -f Makefile.arm9 clean --no-print-directory - $(MAKE) -f Makefile.arm7 clean --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm9 clean --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm7 clean --no-print-directory $(RM) $(ROM) $(BUILDDIR) $(SDIMAGE) arm9: - $(MAKE) -f misc/ds/Makefile.arm9 --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm9 --no-print-directory arm7: - $(MAKE) -f misc/ds/Makefile.arm7 --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm7 --no-print-directory $(ROM): arm9 arm7 diff --git a/misc/ds/Makefile.arm7 b/misc/nds/Makefile.arm7 similarity index 99% rename from misc/ds/Makefile.arm7 rename to misc/nds/Makefile.arm7 index b486d323b..6deb6c42c 100644 --- a/misc/ds/Makefile.arm7 +++ b/misc/nds/Makefile.arm7 @@ -6,7 +6,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external export WONDERFUL_TOOLCHAIN ?= /opt/wonderful ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/ -SOURCEDIRS := misc/ds +SOURCEDIRS := misc/nds INCLUDEDIRS := DSIWIFI := third_party/dsiwifi diff --git a/misc/ds/Makefile.arm9 b/misc/nds/Makefile.arm9 similarity index 99% rename from misc/ds/Makefile.arm9 rename to misc/nds/Makefile.arm9 index 4a5dd7403..4fef37065 100644 --- a/misc/ds/Makefile.arm9 +++ b/misc/nds/Makefile.arm9 @@ -6,7 +6,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external export WONDERFUL_TOOLCHAIN ?= /opt/wonderful ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/ -SOURCEDIRS := src +SOURCEDIRS := src src/nds INCLUDEDIRS := DSIWIFI := third_party/dsiwifi diff --git a/misc/ds/icon.bmp b/misc/nds/icon.bmp similarity index 100% rename from misc/ds/icon.bmp rename to misc/nds/icon.bmp diff --git a/misc/ds/main_arm7.c b/misc/nds/main_arm7.c similarity index 100% rename from misc/ds/main_arm7.c rename to misc/nds/main_arm7.c diff --git a/misc/opengl/GLCommon.h b/misc/opengl/GLCommon.h index 9c8b6f0ee..207c7328d 100644 --- a/misc/opengl/GLCommon.h +++ b/misc/opengl/GLCommon.h @@ -42,6 +42,8 @@ typedef cc_uintptr GLpointer; #define GL_TRIANGLES 0x0004 #define GL_QUADS 0x0007 +#define GL_ZERO 0 +#define GL_ONE 1 #define GL_BLEND 0x0BE2 #define GL_SRC_ALPHA 0x0302 #define GL_ONE_MINUS_SRC_ALPHA 0x0303 diff --git a/misc/ps3/Makefile b/misc/ps3/Makefile index 9064a20e3..370863e02 100644 --- a/misc/ps3/Makefile +++ b/misc/ps3/Makefile @@ -139,6 +139,10 @@ $(BUILD_DIR)/%.o: src/ps3/%.S $(BUILD_DIR)/%.o: third_party/bearssl/%.c $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +# prevent the .asm files from being deleted +.PRECIOUS: $(BUILD_DIR)/%.vpo $(BUILD_DIR)/%.fpo + $(BUILD_DIR)/%.vpo: $(SHADERS)/%.vcg $(CGCOMP) -v $(CGCFLAGS) $^ $@ $(BUILD_DIR)/%.fpo: $(SHADERS)/%.fcg diff --git a/misc/ps4/Makefile b/misc/ps4/Makefile index bf4983917..9ffbc51ad 100644 --- a/misc/ps4/Makefile +++ b/misc/ps4/Makefile @@ -1,53 +1,76 @@ -# Package metadata. -TITLE := OpenOrbis Hello World Sample +ifeq ($(strip $(OO_PS4_TOOLCHAIN)),) +$(error "Please set OO_PS4_TOOLCHAIN in your environment. export OO_PS4_TOOLCHAIN=") +endif +TOOLCHAIN := $(OO_PS4_TOOLCHAIN) + +.SUFFIXES: + +#--------------------------------------------------------------------------------- +# Configurable options +#--------------------------------------------------------------------------------- +BUILD_DIR = build/ps4 +SOURCE_DIRS = src src/ps4 third_party/bearssl + +TARGET = ClassiCube-PS4 +TITLE := ClassiCube VERSION := 1.00 TITLE_ID := BREW00083 CONTENT_ID := IV0000-BREW00083_00-HELLOWORLD000000 -# Libraries linked into the ELF. +#--------------------------------------------------------------------------------- +# Compilable files +#--------------------------------------------------------------------------------- +CPP_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.cpp)) +C_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(CPP_FILES:%.cpp=%.o))) + +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(OBJS:%.o=%.d) + +#--------------------------------------------------------------------------------- +# Code generation +#-------------------------------------------------------------------------------- LIBS := -lc -lkernel -lc++ -lSceVideoOut -lSceNet -# Additional compile flags. -#EXTRAFLAGS := - -# Asset and module directories. -LIBMODULES := $(wildcard sce_module/*) - -# You likely won't need to touch anything below this point. - -# Root vars -TOOLCHAIN := $(OO_PS4_TOOLCHAIN) -PROJDIR := src -INTDIR := build-ps4 - -# Define objects to build -CFILES := $(wildcard $(PROJDIR)/*.c) -CPPFILES := $(wildcard $(PROJDIR)/*.cpp) -OBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.o, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.o, $(CPPFILES)) - -# Define final C/C++ flags CFLAGS := --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -c $(EXTRAFLAGS) -isysroot $(TOOLCHAIN) -isystem $(TOOLCHAIN)/include -isystem $(TOOLCHAIN)/include/orbis -DPLAT_PS4 CXXFLAGS := $(CFLAGS) -isystem $(TOOLCHAIN)/include/c++/v1 LDFLAGS := -m elf_x86_64 -pie --script $(TOOLCHAIN)/link.x --eh-frame-hdr -L$(TOOLCHAIN)/lib $(LIBS) $(TOOLCHAIN)/lib/crt1.o -# Create the intermediate directory incase it doesn't already exist. -_unused := $(shell mkdir -p $(INTDIR)) +#--------------------------------------------------------------------------------- +# Compiler tools +#--------------------------------------------------------------------------------- CC := clang CCX := clang++ LD := ld.lld CDIR := linux -all: $(CONTENT_ID).pkg +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +all: $(BUILD_DIR) $(CONTENT_ID).pkg + +clean: + rm -f $(CONTENT_ID).pkg pkg.gp4 pkg/sce_sys/param.sfo eboot.bin \ + $(BUILD_DIR)/$(PROJDIR).elf $(BUILD_DIR)/$(PROJDIR).oelf $(OBJS) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# Executable generation +#--------------------------------------------------------------------------------- $(CONTENT_ID).pkg: pkg.gp4 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core pkg_build $< . -pkg.gp4: eboot.bin - cd misc/ps4 - $(TOOLCHAIN)/bin/$(CDIR)/create-gp4 -out $@ --content-id=$(CONTENT_ID) --files "sce_sys/about/right.sprx sce_sys/param.sfo sce_sys/icon0.png" +pkg.gp4: eboot.bin $(BUILD_DIR)/sce_sys/param.sfo + $(TOOLCHAIN)/bin/$(CDIR)/create-gp4 -out $@ --content-id=$(CONTENT_ID) --files "eboot.bin sce_sys/about/right.sprx sce_sys/param.sfo sce_sys/icon0.png" -misc/ps4/sce_sys/param.sfo: Makefile +$(BUILD_DIR)/sce_sys/param.sfo: + mkdir -p $(BUILD_DIR)/sce_sys $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_new $@ $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_TYPE --type Integer --maxsize 4 --value 1 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_VER --type Utf8 --maxsize 8 --value '$(VERSION)' @@ -60,16 +83,32 @@ misc/ps4/sce_sys/param.sfo: Makefile $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ TITLE_ID --type Utf8 --maxsize 12 --value '$(TITLE_ID)' $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ VERSION --type Utf8 --maxsize 8 --value '$(VERSION)' -eboot.bin: $(INTDIR) $(OBJS) - $(LD) $(INTDIR)/*.o -o $(INTDIR)/$(PROJDIR).elf $(LDFLAGS) - $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --eboot "eboot.bin" --paid 0x3800000000000011 +$(BUILD_DIR)/$(TARGET).elf: $(OBJS) + $(LD) $(OBJS) -o $(BUILD_DIR)/$(TARGET).elf $(LDFLAGS) -$(INTDIR)/%.o: $(PROJDIR)/%.c - $(CC) $(CFLAGS) -o $@ $< +eboot.bin: $(BUILD_DIR)/$(TARGET).elf + $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(BUILD_DIR)/$(TARGET).elf -out=$(BUILD_DIR)/$(TARGET).oelf --eboot "eboot.bin" --paid 0x3800000000000011 -$(INTDIR)/%.o: $(PROJDIR)/%.cpp - $(CCX) $(CXXFLAGS) -o $@ $< -clean: - rm -f $(CONTENT_ID).pkg pkg.gp4 pkg/sce_sys/param.sfo eboot.bin \ - $(INTDIR)/$(PROJDIR).elf $(INTDIR)/$(PROJDIR).oelf $(OBJS) +#--------------------------------------------------------------------------------- +# Object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: src/%.cpp + $(CCX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: src/ps4/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: third_party/bearssl/%.c + $(CC) $(CFLAGS) -c $< -o $@ + + +#--------------------------------------------------------------------------------- +# Dependency tracking +#--------------------------------------------------------------------------------- +$(DEPFILES): + +include $(wildcard $(DEPFILES)) diff --git a/misc/psp/Makefile b/misc/psp/Makefile index edd61fa5b..76fd47eb8 100644 --- a/misc/psp/Makefile +++ b/misc/psp/Makefile @@ -18,7 +18,9 @@ SOURCE_DIRS = src src/psp third_party/bearssl # Directory where object files are placed BUILD_DIR = build/psp -PSP_EBOOT_TITLE = ClassiCube +SFO_TITLE = ClassiCube +SFO_DISCID = CUBE02000 + PSP_EBOOT_ICON = misc/psp/ICON0.png PSP_EBOOT_SFO = PARAM.SFO PSP_EBOOT_ICON1 = NULL @@ -36,7 +38,7 @@ S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -CFLAGS := -I$(PSPSDK)/include -g -O1 -fno-math-errno -D_PSP_FW_VERSION=600 +CFLAGS := -I$(PSPSDK)/include -g -O1 -fno-math-errno -D_PSP_FW_VERSION=600 -DPLAT_PSP ASFLAGS := -I$(PSPSDK)/include -g LDFLAGS := -L$(PSPSDK)/lib -specs=$(PSPSDK)/lib/prxspecs -Wl,-q,-T$(PSPSDK)/lib/linkfile.prx -Wl,-zmax-page-size=128 @@ -82,7 +84,7 @@ $(TARGET).prx: $(TARGET).elf $(PRXGEN) $< $@ $(PSP_EBOOT_SFO): - $(MKSFO) -d MEMSIZE=1 '$(PSP_EBOOT_TITLE)' $@ + $(MKSFO) -d MEMSIZE=1 -s DISC_ID="$(SFO_DISCID)" '$(SFO_TITLE)' $@ $(PSP_EBOOT): $(TARGET).prx $(PSP_EBOOT_SFO) $(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ diff --git a/misc/psp/README.md b/misc/psp/README.md new file mode 100644 index 000000000..d9ae102a4 --- /dev/null +++ b/misc/psp/README.md @@ -0,0 +1,4 @@ +To see debug log messages in PPSSPP: + +1) Make sure 'printf' log level in Logging Channels is set to "Debug" + diff --git a/misc/switch/Makefile b/misc/switch/Makefile index 05fc33a4e..9845d025c 100644 --- a/misc/switch/Makefile +++ b/misc/switch/Makefile @@ -37,7 +37,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- ARCH = -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -CFLAGS = -g -Wall -O2 -ffunction-sections $(ARCH) -D__SWITCH__ +CFLAGS = -g -Wall -O2 -ffunction-sections $(ARCH) -D__SWITCH__ -DPLAT_SWITCH ASFLAGS = -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) diff --git a/misc/symbian/ClassiCube.pkg b/misc/symbian/ClassiCube.pkg index d2c1e7201..8b3f46a25 100644 --- a/misc/symbian/ClassiCube.pkg +++ b/misc/symbian/ClassiCube.pkg @@ -10,7 +10,7 @@ :"ClassiCube" ; Check OpenC versions -IF( version(0x20009a80, <, 1, 5, 0) ) AND NOT (EXISTS("Z:\sys\bin\libc.dll") OR EXISTS("C:\sys\bin\libc.dll")) +IF version(0x20009a80, <, 1, 5, 0) AND NOT EXISTS("C:\sys\bin\libc.dll") "incompatible_openc.txt"-"", FT, FORCEABORT ENDIF diff --git a/misc/vita/Makefile b/misc/vita/Makefile index afbcbfac1..02a411cac 100644 --- a/misc/vita/Makefile +++ b/misc/vita/Makefile @@ -17,8 +17,8 @@ SOURCE_DIRS = src src/psvita third_party/bearssl # Directory where object files are placed BUILD_DIR = build/vita -PROJECT_TITLE = ClassiCube -PROJECT_TITLEID = CUBE00200 +SFO_TITLE = ClassiCube +SFO_TITLEID = CUBE00200 #--------------------------------------------------------------------------------- @@ -35,7 +35,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- -CFLAGS = -O1 +CFLAGS = -O1 -DPLAT_VITA -fno-math-errno LDFLAGS = -Wl,-q LIBS = -lm -lSceDisplay_stub -lSceCtrl_stub -lSceTouch_stub -lSceGxm_stub -lSceCommonDialog_stub -lSceAppUtil_stub @@ -78,7 +78,7 @@ eboot.bin: $(TARGET).velf $(MAKE_FSELF) $(TARGET).velf eboot.bin param.sfo: - $(MKSOFEX) -s TITLE_ID="$(PROJECT_TITLEID)" "$(PROJECT_TITLE)" param.sfo + $(MKSOFEX) -s TITLE_ID="$(SFO_TITLEID)" "$(SFO_TITLE)" param.sfo $(TARGET).velf: $(TARGET).elf $(VITA_STRIP) -g $< diff --git a/misc/wii/Makefile b/misc/wii/Makefile index 79ba6a1d6..b7b585c9a 100644 --- a/misc/wii/Makefile +++ b/misc/wii/Makefile @@ -32,7 +32,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float -CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include +CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include -DPLAT_GCWII LDFLAGS = -g $(MACHDEP) -L$(DEVKITPRO)/libogc/lib/wii # Additional libraries to link against diff --git a/misc/wii/README.md b/misc/wii/README.md new file mode 100644 index 000000000..ba317114e --- /dev/null +++ b/misc/wii/README.md @@ -0,0 +1,5 @@ +To see debug log messages in Dolphin: + +1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu +2) Make sure "OSReport EXI (OSREPORT)" log type is enabled +3) In the UI, make sure 'Show log' checkbox is checked in View menu diff --git a/misc/wiiu/Makefile b/misc/wiiu/Makefile index 5e8424dea..5e1967036 100644 --- a/misc/wiiu/Makefile +++ b/misc/wiiu/Makefile @@ -1,170 +1,123 @@ -#------------------------------------------------------------------------------- -.SUFFIXES: -#------------------------------------------------------------------------------- - ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro) endif -TOPDIR ?= $(CURDIR) +.SUFFIXES: -#------------------------------------------------------------------------------- -# APP_NAME sets the long name of the application -# APP_SHORTNAME sets the short name of the application -# APP_AUTHOR sets the author of the application -#------------------------------------------------------------------------------- -APP_NAME := ClassiCube -APP_SHORTNAME := ClassiCube -APP_AUTHOR := ClassiCube team -include $(DEVKITPRO)/wut/share/wut_rules +#--------------------------------------------------------------------------------- +# Configurable options +#--------------------------------------------------------------------------------- +# Name of the final output +TARGET = ClassiCube-wiiu +# List of directories containing source code +SOURCE_DIRS = src src/wiiu third_party/bearssl +# Directory where object files are placed +BUILD_DIR = build/wiiu +# Directory where shader files are +SHADERS = misc/wiiu -#------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -# CONTENT is the path to the bundled folder that will be mounted as /vol/content/ -# ICON is the game icon, leave blank to use default rule -# TV_SPLASH is the image displayed during bootup on the TV, leave blank to use default rule -# DRC_SPLASH is the image displayed during bootup on the DRC, leave blank to use default rule -#------------------------------------------------------------------------------- -TARGET := ClassiCube-wiiu -BUILD := build-wiiu -SOURCES := src third_party/bearssl -SHADERS := misc/wiiu -DATA := data -INCLUDES := -CONTENT := -ICON := -TV_SPLASH := -DRC_SPLASH := +WUHB_OPTIONS = \ + --name "ClassiCube" \ + --short-name "ClassiCube" \ + --author "ClassiCube team" \ + --icon=misc/wiiu/icon.png -#------------------------------------------------------------------------------- -# options for code generation -#------------------------------------------------------------------------------- -CFLAGS := -g -Wall -O2 -ffunction-sections -fno-math-errno \ - $(MACHDEP) +#WUHB_OPTIONS += --tv-image=misc/wiiu/tv_splash.png +#WUHB_OPTIONS += --drc-image=misc/wiiu/drc_splash.png -CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -CXXFLAGS := $(CFLAGS) +#--------------------------------------------------------------------------------- +# Compilable files +#--------------------------------------------------------------------------------- +S_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) - -LIBS := -lwut -lm - -#------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level -# containing include and lib -#------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUT_ROOT) - -#------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(SHADERS),$(notdir $(wildcard $(dir)/*.gsh))) - -export LD := $(CC) +BINFILES := $(foreach dir,$(SHADERS),$(wildcard $(dir)/*.gsh)) +OBJS += $(addprefix $(BUILD_DIR)/, $(notdir $(BINFILES:%.gsh=%.gsh.o))) export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(OBJS:%.o=%.d) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -ifneq (,$(strip $(CONTENT))) - export APP_CONTENT := $(TOPDIR)/$(CONTENT) -endif +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +MACHDEP = -DESPRESSO -mcpu=750 -meabi -mhard-float +CFLAGS = -g -Wall -O2 -ffunction-sections -fno-math-errno $(MACHDEP) \ + -I $(DEVKITPRO)/wut/include \ + -D__WIIU__ -D__WUT__ -DPLAT_WIIU -ifneq (,$(strip $(ICON))) - export APP_ICON := $(TOPDIR)/$(ICON) -else ifneq (,$(wildcard $(TOPDIR)/$(TARGET).png)) - export APP_ICON := $(TOPDIR)/$(TARGET).png -else ifneq (,$(wildcard $(TOPDIR)/icon.png)) - export APP_ICON := $(TOPDIR)/icon.png -endif +LDFLAGS = -g $(MACHDEP) -specs=$(DEVKITPRO)/wut/share/wut.specs \ + -L $(DEVKITPRO)/wut/lib +# Additional libraries to link against +LIBS = -lwut -lm -ifneq (,$(strip $(TV_SPLASH))) - export APP_TV_SPLASH := $(TOPDIR)/$(TV_SPLASH) -else ifneq (,$(wildcard $(TOPDIR)/tv-splash.png)) - export APP_TV_SPLASH := $(TOPDIR)/tv-splash.png -else ifneq (,$(wildcard $(TOPDIR)/splash.png)) - export APP_TV_SPLASH := $(TOPDIR)/splash.png -endif -ifneq (,$(strip $(DRC_SPLASH))) - export APP_DRC_SPLASH := $(TOPDIR)/$(DRC_SPLASH) -else ifneq (,$(wildcard $(TOPDIR)/drc-splash.png)) - export APP_DRC_SPLASH := $(TOPDIR)/drc-splash.png -else ifneq (,$(wildcard $(TOPDIR)/splash.png)) - export APP_DRC_SPLASH := $(TOPDIR)/splash.png -endif +#--------------------------------------------------------------------------------- +# Compiler tools +#--------------------------------------------------------------------------------- +PREFIX := $(DEVKITPRO)/devkitPPC/bin/powerpc-eabi- +PPC_AS := $(PREFIX)as +PPC_CC := $(PREFIX)gcc +PPC_CXX := $(PREFIX)g++ -.PHONY: $(BUILD) clean all +ELF2RPL := $(DEVKITPRO)/tools/bin/elf2rpl +WUHBTOOL := $(DEVKITPRO)/tools/bin/wuhbtool +BIN2S := $(DEVKITPRO)/tools/bin/bin2s -#------------------------------------------------------------------------------- -all: $(BUILD) -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/misc/wiiu/Makefile +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).wuhb -#------------------------------------------------------------------------------- clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).wuhb $(TARGET).rpx $(TARGET).elf + rm $(TARGET).wuhb $(TARGET).rpx $(TARGET).elf $(OBJS) -#------------------------------------------------------------------------------- -else -.PHONY: all +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) -DEPENDS := $(OFILES:.o=.d) -#------------------------------------------------------------------------------- -# main targets -#------------------------------------------------------------------------------- -all : $(OUTPUT).wuhb +#--------------------------------------------------------------------------------- +# Executable generation +#--------------------------------------------------------------------------------- +$(TARGET).elf: $(OBJS) + $(PPC_CC) $(LDFLAGS) $^ -o $@ $(LIBS) + +$(TARGET).rpx: $(TARGET).elf + $(ELF2RPL) $< $@ + +$(TARGET).wuhb: $(TARGET).rpx + $(WUHBTOOL) $< $@ $(WUHB_OPTIONS) -$(OUTPUT).wuhb : $(OUTPUT).rpx -$(OUTPUT).rpx : $(OUTPUT).elf -$(OUTPUT).elf : $(OFILES) -# you need a rule like this for each extension you use as binary data -#------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) -#------------------------------------------------------------------------------- -%.gsh.o %_gsh.h : ../misc/wiiu/%.gsh -#------------------------------------------------------------------------------- - echo $(notdir $<) - $(bin2o) +#--------------------------------------------------------------------------------- +# Object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/%.c + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ --include $(DEPENDS) +$(BUILD_DIR)/%.o: src/wiiu/%.S + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ -#------------------------------------------------------------------------------- -endif -#------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/wiiu/%.c + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: third_party/bearssl/%.c + $(PPC_CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.gsh.o : misc/wiiu/%.gsh + $(BIN2S) $< | $(PPC_CC) -x assembler-with-cpp -c - -o $@ + + +#--------------------------------------------------------------------------------- +# Dependency tracking +#--------------------------------------------------------------------------------- +$(DEPFILES): + +include $(wildcard $(DEPFILES)) diff --git a/misc/wiiu/icon.png b/misc/wiiu/icon.png new file mode 100644 index 000000000..767910413 Binary files /dev/null and b/misc/wiiu/icon.png differ diff --git a/misc/xbox/Makefile b/misc/xbox/Makefile index 3c696494b..c996ef87a 100644 --- a/misc/xbox/Makefile +++ b/misc/xbox/Makefile @@ -15,7 +15,7 @@ XBE_TITLE = ClassiCube # List of directories containing source code SOURCE_DIRS = src src/xbox third_party/bearssl # Shader objects -SHADER_OBJS = misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl misc/xbox/ps_coloured.inl misc/xbox/ps_textured.inl +SHADER_OBJS = misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl misc/xbox/vs_offset.inl misc/xbox/ps_coloured.inl misc/xbox/ps_textured.inl # Directory where object files are placed BUILD_DIR = build/xbox @@ -82,7 +82,7 @@ $(BUILD_DIR): #--------------------------------------------------------------------------------- # Executable generation #--------------------------------------------------------------------------------- -$(OBJS) : $(SHADER_OBJS) +$(BUILD_DIR)/Graphics_Xbox.o : $(SHADER_OBJS) $(TARGET).iso: $(TARGET).xbe mkdir -p $(BUILD_DIR)/cd @@ -111,15 +111,21 @@ $(BUILD_DIR)/%.o: src/xbox/%.S $(BUILD_DIR)/%.o: third_party/bearssl/%.c nxdk-cc $(NXDK_CFLAGS) $(CFLAGS) -c $< -o $@ -%.inl: %.vs.cg - $(CGC) -profile vp20 -o $@.$$$$ $< && \ - $(VP20COMPILER) $@.$$$$ > $@ && \ - rm -rf $@.$$$$ -%.inl: %.ps.cg - $(CGC) -profile fp20 -o $@.$$$$ $< && \ - $(FP20COMPILER) $@.$$$$ > $@ && \ - rm -rf $@.$$$$ +# prevent the .asm files from being deleted +.PRECIOUS: vs_%.asm ps_%.asm + +vs_%.inl: vs_%.asm + $(VP20COMPILER) $< > $@ + +vs_%.asm: vs_%.cg + $(CGC) -profile vp20 $< -o $@ + +ps_%.inl: ps_%.asm + $(FP20COMPILER) $< > $@ + +ps_%.asm: ps_%.cg + $(CGC) -profile fp20 $< -o $@ #--------------------------------------------------------------------------------- diff --git a/misc/xbox/README.md b/misc/xbox/README.md new file mode 100644 index 000000000..a813c938b --- /dev/null +++ b/misc/xbox/README.md @@ -0,0 +1,11 @@ +To see debug log messages in Xemu: + +1) Launch Xemu as `xemu -device lpc47m157 -serial stdio` + +---- + +To launch directly, `-dvd_path cc-xbox.iso` + +#### + +The .asm files are auto generated from the .cg files, and shouldn't be manually edited. diff --git a/misc/xbox/ps_coloured.asm b/misc/xbox/ps_coloured.asm new file mode 100644 index 000000000..756815cbe --- /dev/null +++ b/misc/xbox/ps_coloured.asm @@ -0,0 +1,14 @@ +// nvparse 1.0 output generated by NVIDIA Cg compiler +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile fp20 +// source file: misc/xbox/ps_coloured.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile fp20 +//program main +//var float4 input.color : $vin.COLOR : COLOR0 : 0 : 1 +//var float4 main : $vout.COLOR : COLOR : -1 : 1 +!!RC1.0 +out.rgb = unsigned(col0.rgb); +out.a = unsigned(col0.a); +// 0 instructions diff --git a/misc/xbox/ps_coloured.ps.cg b/misc/xbox/ps_coloured.cg similarity index 100% rename from misc/xbox/ps_coloured.ps.cg rename to misc/xbox/ps_coloured.cg diff --git a/misc/xbox/ps_textured.asm b/misc/xbox/ps_textured.asm new file mode 100644 index 000000000..99fc0c06e --- /dev/null +++ b/misc/xbox/ps_textured.asm @@ -0,0 +1,30 @@ +// nvparse 1.0 output generated by NVIDIA Cg compiler +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile fp20 +// source file: misc/xbox/ps_textured.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile fp20 +//program main +//semantic main.tex +//var sampler2D tex : : 0 : 1 : 1 +//var float4 input.color : $vin.COLOR : COLOR0 : 0 : 1 +//var float2 input.tex0 : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1 +//var float4 main : $vout.COLOR : COLOR : -1 : 1 +!!TS1.0 +texture_2d(); +// End of program +!!RC1.0 +{ + rgb + { + col0 = tex0.rgb * col0.rgb; + } + alpha + { + col0 = tex0.a * col0.a; + } +} +out.rgb = unsigned(col0.rgb); +out.a = unsigned(col0.a); +// 3 instructions diff --git a/misc/xbox/ps_textured.ps.cg b/misc/xbox/ps_textured.cg similarity index 100% rename from misc/xbox/ps_textured.ps.cg rename to misc/xbox/ps_textured.cg diff --git a/misc/xbox/vs_coloured.asm b/misc/xbox/vs_coloured.asm new file mode 100644 index 000000000..f3b4462df --- /dev/null +++ b/misc/xbox/vs_coloured.asm @@ -0,0 +1,24 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_coloured.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[COL0], v[3]; +MOV o[HPOS].w, R0; +END +# 8 instructions, 0 R-regs diff --git a/misc/xbox/vs_coloured.vs.cg b/misc/xbox/vs_coloured.cg similarity index 65% rename from misc/xbox/vs_coloured.vs.cg rename to misc/xbox/vs_coloured.cg index 44394436a..f2ceeb356 100644 --- a/misc/xbox/vs_coloured.vs.cg +++ b/misc/xbox/vs_coloured.cg @@ -1,6 +1,6 @@ struct vIn { - float4 color : DIFFUSE; - float4 position : POSITION; + float4 col : DIFFUSE; + float4 pos : POSITION; }; struct vOut { @@ -16,11 +16,11 @@ vOut main( vOut result; float4 position; - position = float4(input.position.xyz, 1.0f); + position = float4(input.pos.xyz, 1.0f); position = mul(position, mvp); position.xyz = position.xyz / position.w; result.pos = position; - result.col = input.color; + result.col = input.col; return result; } diff --git a/misc/xbox/vs_offset.asm b/misc/xbox/vs_offset.asm new file mode 100644 index 000000000..fc0a6d64b --- /dev/null +++ b/misc/xbox/vs_offset.asm @@ -0,0 +1,29 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_offset.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#semantic main.tex_offset +#var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 tex_offset : : c[4] : 2 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[HPOS].w, R0; +MOV o[COL0], v[3]; +ADD o[TEX0], v[8], c[4]; +END +# 9 instructions, 0 R-regs diff --git a/misc/xbox/vs_offset.cg b/misc/xbox/vs_offset.cg new file mode 100644 index 000000000..5eca8588a --- /dev/null +++ b/misc/xbox/vs_offset.cg @@ -0,0 +1,30 @@ +struct vIn { + float4 tex : TEXCOORD; + float4 col : DIFFUSE; + float4 pos : POSITION; +}; + +struct vOut { + float4 pos : POSITION; + float4 col : COLOR; + float4 tex : TEXCOORD0; +}; + +vOut main( + vIn input, + uniform float4x4 mvp, + uniform float4 tex_offset + ) +{ + vOut result; + float4 position; + + position = float4(input.pos.xyz, 1.0f); + position = mul(position, mvp); + position.xyz = position.xyz / position.w; + + result.pos = position; + result.col = input.col; + result.tex = input.tex + tex_offset; + return result; +} diff --git a/misc/xbox/vs_offset.inl b/misc/xbox/vs_offset.inl new file mode 100644 index 000000000..135f1576d --- /dev/null +++ b/misc/xbox/vs_offset.inl @@ -0,0 +1,27 @@ +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile vp20 +// source file: misc/xbox/vs_offset.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile vp20 +//program main +//semantic main.mvp +//semantic main.tex_offset +//var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +//var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +//var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +//var float4x4 mvp : : c[0], 4 : 1 : 1 +//var float4 tex_offset : : c[4] : 2 : 1 +//var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +//var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +//var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +// 9 instructions, 0 R-regs +0x00000000, 0x004c2055, 0x0836186c, 0x2f0007f8, +0x00000000, 0x008c0000, 0x0836186c, 0x1f0007f8, +0x00000000, 0x008c40aa, 0x0836186c, 0x1f0007f8, +0x00000000, 0x006c601b, 0x0436106c, 0x3f0007f8, +0x00000000, 0x0400001b, 0x08361300, 0x101807f8, +0x00000000, 0x0040001b, 0x0400286c, 0x2070e800, +0x00000000, 0x0020001b, 0x0436106c, 0x20701800, +0x00000000, 0x0020061b, 0x0836106c, 0x2070f818, +0x00000000, 0x006c921b, 0x0836106c, 0x3070f849, diff --git a/misc/xbox/vs_textured.asm b/misc/xbox/vs_textured.asm new file mode 100644 index 000000000..aaa6b3740 --- /dev/null +++ b/misc/xbox/vs_textured.asm @@ -0,0 +1,27 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_textured.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[HPOS].w, R0; +MOV o[COL0], v[3]; +MOV o[TEX0], v[8]; +END +# 9 instructions, 0 R-regs diff --git a/misc/xbox/vs_textured.vs.cg b/misc/xbox/vs_textured.cg similarity index 64% rename from misc/xbox/vs_textured.vs.cg rename to misc/xbox/vs_textured.cg index a439d1c52..b4e3742d7 100644 --- a/misc/xbox/vs_textured.vs.cg +++ b/misc/xbox/vs_textured.cg @@ -1,7 +1,7 @@ struct vIn { - float4 tex : TEXCOORD; - float4 color : DIFFUSE; - float4 position : POSITION; + float4 tex : TEXCOORD; + float4 col : DIFFUSE; + float4 pos : POSITION; }; struct vOut { @@ -18,12 +18,12 @@ vOut main( vOut result; float4 position; - position = float4(input.position.xyz, 1.0f); + position = float4(input.pos.xyz, 1.0f); position = mul(position, mvp); position.xyz = position.xyz / position.w; result.pos = position; - result.col = input.color; + result.col = input.col; result.tex = input.tex; return result; } diff --git a/readme.md b/readme.md index cecc55d86..5ad5c02ae 100644 --- a/readme.md +++ b/readme.md @@ -74,6 +74,7 @@ And also runs on: * Haiku - needs openal package (if you have a GitHub account, can [download from here](https://github.com/ClassiCube/ClassiCube/actions/workflows/build_haiku.yml)) * BeOS - untested on actual hardware * IRIX - needs openal packages +* HPUX - tested on 11v3 IA64 * SerenityOS - needs SDL2 * Classic Mac OS (System 7 and later) * Dreamcast - unfinished, but usable (can [download from here](https://www.classicube.net/download/dreamcast)) @@ -110,7 +111,7 @@ If you get a `The Windows SDK version 5.1 was not found` compilation error, [see ##### Using Visual Studio (command line) 1. Use 'Developer Tools for Visual Studio' from Start Menu 2. Navigate to the directory with ClassiCube's source code -3. Run `cl.exe *.c /link user32.lib gdi32.lib winmm.lib dbghelp.lib shell32.lib comdlg32.lib /out:ClassiCube.exe` +3. Run `cl.exe src\*.c third_party\bearssl\*.c /link user32.lib gdi32.lib winmm.lib dbghelp.lib shell32.lib comdlg32.lib /out:ClassiCube.exe` ##### Using MinGW-w64 Assuming that you used the installer from https://sourceforge.net/projects/mingw-w64/ : @@ -138,8 +139,7 @@ Setting up TCC: Compiling with TCC: 1. Navigate to the directory with ClassiCube's source code -2. In `ExtMath.c`, change `fabsf` to `fabs` and `sqrtf` to `sqrt` -3. Run `tcc.exe -o ClassiCube.exe src/*.c third_party/bearssl/*.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
+2. Run `tcc.exe -o ClassiCube.exe src/*.c third_party/bearssl/*.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
(Note: You may need to specify the full path to `tcc.exe` instead of just `tcc.exe`) ## Compiling - Linux @@ -420,7 +420,7 @@ Further information (e.g. style) for ClassiCube's source code can be found in th #### Tips * Press escape (after joining a world) or pause to switch to the pause menu. * Pause menu -> Options -> Controls lists all of the key combinations used by the client. -* Note that toggling 'vsync' to on will minimise CPU usage, while off will maximimise chunk loading speed. +* Note that toggling 'vsync' to on will minimise CPU usage, while off will maximise chunk loading speed. * Press F to cycle view distance. Lower view distances can improve performance. * If the server has disabled hacks, key combinations such as fly and speed will not do anything. @@ -477,3 +477,4 @@ Further information (e.g. style) for ClassiCube's source code can be found in th ## Sound Credits ClassiCube uses sounds from [Freesound.org](https://freesound.org)
Full credits are listed in [doc/sound-credits.md](doc/sound-credits.md) + diff --git a/src/32x/Platform_32x.c b/src/32x/Platform_32x.c index 530d0be51..24bdbdd04 100644 --- a/src/32x/Platform_32x.c +++ b/src/32x/Platform_32x.c @@ -1,4 +1,9 @@ #define OVERRIDE_MEM_FUNCTIONS +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -11,7 +16,6 @@ #include #include -#include "../_PlatformConsole.h" #include "../../misc/32x/32x.h" #include "../../misc/32x/hw_32x.h" @@ -27,24 +31,43 @@ const cc_result ReturnCode_SocketDropped = -1; const char* Platform_AppNameSuffix = " 32x"; cc_bool Platform_ReadonlyFilesystem = true; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; + + +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunGame(); + } + + Window_Free(); + return 0; +} /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" MALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("MALLOCED: %x", &ptr); + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); return ptr; } void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" CALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("CALLOCED: %x", &ptr); + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); if (ptr) Mem_Set(ptr, 0, size); return ptr; @@ -95,13 +118,30 @@ void Process_Abort2(cc_result result, const char* raw_msg) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -cc_uint64 Stopwatch_Measure(void) { - return 0; +#include "../saturn/sh2_wdt.h" + +static void Stopwatch_Init(void) { + wdt_stop(); + + wdt_set_irq_number(5); // hardcoded in sh2_crt0.s + wdt_set_irq_priority(15); + + wdt_enable(); } +cc_uint64 Stopwatch_Measure(void) { + return wdt_total_ticks(); +} + +#define US_PER_SEC 1000000 +#define NTSC_CPU_CLOCK 23011360 // TODO + cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - return 1000 * 1000; + cc_uint64 delta = end - beg; + + // TODO still completely wrong?? PAL detection ??? + return (delta * US_PER_SEC) / (NTSC_CPU_CLOCK / 1024); } @@ -113,6 +153,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ReturnCode_DirectoryExists; } @@ -170,80 +212,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Hw32xDelay(1); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* @@ -259,6 +227,8 @@ void Platform_Init(void) { int size = (int)(heap_end - heap_beg); Platform_Log3("HEAP SIZE: %i bytes (%x -> %x)", &size, &heap_beg, &heap_end); + + Stopwatch_Init(); } void Platform_Free(void) { } @@ -280,3 +250,21 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { _exit(code); } + diff --git a/src/32x/Window_32x.c b/src/32x/Window_32x.c index 6273424c1..acd66d0b0 100644 --- a/src/32x/Window_32x.c +++ b/src/32x/Window_32x.c @@ -94,12 +94,29 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping pad_defaults[BIND_COUNT] = { + [BIND_LOOK_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_LOOK_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_LOOK_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_LOOK_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_FORWARD] = { CCPAD_UP, 0 }, + [BIND_BACK] = { CCPAD_DOWN, 0 }, + [BIND_LEFT] = { CCPAD_LEFT, 0 }, + [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, + [BIND_JUMP] = { CCPAD_1, 0 }, + [BIND_INVENTORY] = { CCPAD_3, 0 }, + [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, + [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_HOTBAR_LEFT] = { CCPAD_4, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_4, CCPAD_RIGHT } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x32, PadBind_Defaults); + int port = Gamepad_Connect(0x32, pad_defaults); int mods = HwMdReadPad(0); Gamepad_SetButton(port, CCPAD_L, mods & SEGA_CTRL_X); diff --git a/src/3ds/Graphics_3DS.c b/src/3ds/Graphics_3DS.c index 9ec7dc877..c3743322a 100644 --- a/src/3ds/Graphics_3DS.c +++ b/src/3ds/Graphics_3DS.c @@ -7,6 +7,13 @@ #define BUFFER_BASE_PADDR OS_VRAM_PADDR // VRAM physical address #include "../../third_party/citro3d.c" +#include "gsp_gpu.h" +#include "pica_gpu.h" +// See the .v.pica shader files in misc/3ds +#define CONST_MVP 0 // c0-c3 +#define CONST_TEX 4 // c4 +#define CONST_255 5 // c5 + // autogenerated from the .v.pica files by Makefile extern const u8 coloured_shbin[]; extern const u32 coloured_shbin_size; @@ -33,17 +40,12 @@ static cc_bool rendering3D; *------------------------------------------------------Vertex shaders-----------------------------------------------------* *#########################################################################################################################*/ #define UNI_MVP_MATRIX (1 << 0) -#define UNI_TEX_OFFSETS (1 << 1) -// cached uniforms (cached for multiple programs) static C3D_Mtx _mvp; -static float texOffsetX, texOffsetY; -static int texOffset; +static int texOffset, dirty_mvp; struct CCShader { DVLB_s* dvlb; shaderProgram_s program; - int uniforms; // which associated uniforms need to be resent to GPU - int locations[2]; // location of uniforms (not constant) }; static struct CCShader* gfx_activeShader; static struct CCShader shaders[3]; @@ -52,9 +54,6 @@ static void Shader_Alloc(struct CCShader* shader, const u8* binData, int binSize shader->dvlb = DVLB_ParseFile((u32*)binData, binSize); shaderProgramInit(&shader->program); shaderProgramSetVsh(&shader->program, &shader->dvlb->DVLE[0]); - - shader->locations[0] = shaderInstanceGetUniformLocation(shader->program.vertexShader, "MVP"); - shader->locations[1] = shaderInstanceGetUniformLocation(shader->program.vertexShader, "tex_offset"); } static void Shader_Free(struct CCShader* shader) { @@ -62,28 +61,14 @@ static void Shader_Free(struct CCShader* shader) { DVLB_Free(shader->dvlb); } -// Marks a uniform as changed on all programs -static void DirtyUniform(int uniform) { - for (int i = 0; i < Array_Elems(shaders); i++) - { - shaders[i].uniforms |= uniform; - } -} - -// Sends changed uniforms to the GPU for current program -static void ReloadUniforms(void) { +static void UpdateMVP(void) { struct CCShader* s = gfx_activeShader; + dirty_mvp = true; if (!s) return; // NULL if context is lost - if (s->uniforms & UNI_MVP_MATRIX) { - C3D_FVUnifMtx4x4(s->locations[0], &_mvp); - s->uniforms &= ~UNI_MVP_MATRIX; - } - - if (s->uniforms & UNI_TEX_OFFSETS) { - C3D_FVUnifSet(s->locations[1], - texOffsetX, texOffsetY, 0.0f, 0.0f); - s->uniforms &= ~UNI_TEX_OFFSETS; + if (dirty_mvp) { + pica_upload_mat4_constant(CONST_MVP, &_mvp); + dirty_mvp = false; } } @@ -101,7 +86,7 @@ static void SwitchProgram(void) { gfx_activeShader = shader; C3D_BindProgram(&shader->program); } - ReloadUniforms(); + UpdateMVP(); } @@ -137,9 +122,7 @@ static aptHookCookie hookCookie; static void AptEventHook(APT_HookType hookType, void* param) { if (hookType == APTHOOK_ONSUSPEND) { C3Di_RenderQueueWaitDone(); - C3Di_RenderQueueDisableVBlank(); } else if (hookType == APTHOOK_ONRESTORE) { - C3Di_RenderQueueEnableVBlank(); C3Di_OnRestore(); } } @@ -169,6 +152,8 @@ static void InitCitro3D(void) { gfxSetDoubleBuffering(GFX_TOP, true); SetDefaultState(); AllocShaders(); + + GSP_setup(); } static GfxResourceID white_square; @@ -201,7 +186,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 8x8 dummy white texture @@ -213,7 +198,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } @@ -563,7 +548,7 @@ void Gfx_SetVSync(cc_bool vsync) { void Gfx_BeginFrame(void) { rendering3D = false; // wait for vblank for both screens TODO move to end? - if (gfx_vsync) C3D_FrameSync(); + if (gfx_vsync) GSP_wait_for_full_vblank(); C3D_FrameBegin(0); topTarget = &topTargetLeft; @@ -571,6 +556,17 @@ void Gfx_BeginFrame(void) { extern void C3Di_UpdateContext(void); C3Di_UpdateContext(); + + static C3D_FVec _1_div_255 = { .x = 1/255.0f, .y = 1/255.0f, .z = 1/255.0f, .w = 1/255.0f }; + pica_upload_vec4_constant(CONST_255, &_1_div_255); + + // NOTE: GPUREG_VERTEX_OFFSET only works when drawing non-indexed arrays + GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0); + + // https://github.com/devkitPro/citro3d/issues/47 + // "Fyi the permutation specifies the order in which the attributes are stored in the buffer, LSB first. So 0x210 indicates attributes 0, 1 & 2." + // This just maps array attrib 0 = vertex attrib 0, array attrib 1 = vertex attrib 1, etc + pica_set_attrib_array0_mapping(0x210); } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -860,8 +856,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { } Mtx_Multiply(&_mvp, &_proj, &_view); - DirtyUniform(UNI_MVP_MATRIX); - ReloadUniforms(); + UpdateMVP(); } @@ -882,9 +877,8 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { Matrix_Mul(&_proj, matrix, &rot); // TODO avoid Matrix_Mul ? } + Mtx_Multiply(&_mvp, &_proj, &_view); UpdateMVP(); - DirtyUniform(UNI_MVP_MATRIX); - ReloadUniforms(); }*/ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { @@ -893,14 +887,16 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma Matrix_Mul(mvp, view, proj); } +static C3D_FVec tex_offset; void Gfx_EnableTextureOffset(float x, float y) { - texOffset = true; - texOffsetX = x; - texOffsetY = y; + texOffset = true; + tex_offset.x = x; + tex_offset.y = y; - shaders[2].uniforms |= UNI_TEX_OFFSETS; SwitchProgram(); + pica_upload_vec4_constant(CONST_TEX, &tex_offset); } + void Gfx_DisableTextureOffset(void) { texOffset = false; SwitchProgram(); @@ -914,17 +910,25 @@ void Gfx_DisableTextureOffset(void) { cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -static void UpdateAttribFormat(VertexFormat fmt) { +static void UpdateAttribFormat(void) { C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // in_pos AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4); // in_col - if (fmt == VERTEX_FORMAT_TEXTURED) { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 2); // in_tex } } +static void UpdateAttribConfig(void) { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + pica_set_attrib_array0_format(3, SIZEOF_VERTEX_TEXTURED); + } else { + pica_set_attrib_array0_format(2, SIZEOF_VERTEX_COLOURED); + } +} + static void UpdateTexEnv(VertexFormat fmt) { int func, source; @@ -951,7 +955,8 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_stride = strideSizes[fmt]; SwitchProgram(); - UpdateAttribFormat(fmt); + UpdateAttribFormat(); + UpdateAttribConfig(); UpdateTexEnv(fmt); } @@ -960,32 +965,10 @@ void Gfx_DrawVb_Lines(int verticesCount) { } static void SetVertexSource(int startVertex) { - // https://github.com/devkitPro/citro3d/issues/47 - // "Fyi the permutation specifies the order in which the attributes are stored in the buffer, LSB first. So 0x210 indicates attributes 0, 1 & 2." - const void* data; - int stride, attribs, permutation; - - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - data = (struct VertexTextured*)gfx_vertices + startVertex; - stride = SIZEOF_VERTEX_TEXTURED; - attribs = 3; - permutation = 0x210; - } else { - data = (struct VertexColoured*)gfx_vertices + startVertex; - stride = SIZEOF_VERTEX_COLOURED; - attribs = 2; - permutation = 0x10; - } + const void* data = (cc_uint8*)gfx_vertices + startVertex * gfx_stride; u32 pa = osConvertVirtToPhys(data); - u32 args[3]; // GPUREG_ATTRIBBUFFER0_OFFSET, GPUREG_ATTRIBBUFFER0_CONFIG1, GPUREG_ATTRIBBUFFER0_CONFIG2 - - args[0] = pa - BUFFER_BASE_PADDR; - args[1] = permutation; - args[2] = (stride << 16) | (attribs << 28); - - GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFER0_OFFSET, args, 3); - // NOTE: Can't use GPUREG_VERTEX_OFFSET, it only works when drawing non-indexed arrays + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_OFFSET, pa - BUFFER_BASE_PADDR); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { diff --git a/src/3ds/Platform_3DS.c b/src/3ds/Platform_3DS.c index dec2bfb58..61977e0f5 100644 --- a/src/3ds/Platform_3DS.c +++ b/src/3ds/Platform_3DS.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -50,7 +53,6 @@ unsigned int __stacksize__ = 256 * 1024; *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ void Platform_Log(const char* msg, int len) { - // output to debug service (visible in Citra with log level set to "Debug.Emulated:Debug", or on console via remote gdb) svcOutputDebugString(msg, len); } @@ -110,6 +112,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, 0666) == -1 ? errno : 0; // FS has no permissions anyways } @@ -451,6 +455,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/3ds/Window_3DS.c b/src/3ds/Window_3DS.c index 75d2e9cfc..ff6bab4fb 100644 --- a/src/3ds/Window_3DS.c +++ b/src/3ds/Window_3DS.c @@ -128,6 +128,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_3ds[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static Result irrst_result; void Gamepads_Init(void) { @@ -167,7 +188,7 @@ static void ProcessCircleInput(int port, int axis, circlePosition* pos, float de void Gamepads_Process(float delta) { u32 mods = hidKeysDown() | hidKeysHeld(); - int port = Gamepad_Connect(0x3D5, PadBind_Defaults); + int port = Gamepad_Connect(0x3D5, defaults_3ds); HandleButtons(port, mods); circlePosition hid_pos; diff --git a/src/3ds/gsp_gpu.h b/src/3ds/gsp_gpu.h new file mode 100644 index 000000000..81c827301 --- /dev/null +++ b/src/3ds/gsp_gpu.h @@ -0,0 +1,25 @@ +static volatile uint32_t vblanks_0; +static volatile uint32_t vblanks_1; + +static void handle_vblank(void* ptr) { + uint32_t* counter = (uint32_t*)ptr; + (*counter)++; +} + +static void GSP_setup(void) { + // Start listening for VBLANK events + gspSetEventCallback(GSPGPU_EVENT_VBlank0, handle_vblank, (void*)&vblanks_0, false); + gspSetEventCallback(GSPGPU_EVENT_VBlank1, handle_vblank, (void*)&vblanks_1, false); +} + +// Waits for VBLANK for both top and bottom screens +static void GSP_wait_for_full_vblank(void) { + uint32_t init0 = vblanks_0; + uint32_t init1 = vblanks_1; + + for (;;) { + gspWaitForAnyEvent(); + if (vblanks_0 != init0 && vblanks_1 != init1) return; + } +} + diff --git a/src/3ds/pica_gpu.h b/src/3ds/pica_gpu.h new file mode 100644 index 000000000..5a8c4b56c --- /dev/null +++ b/src/3ds/pica_gpu.h @@ -0,0 +1,33 @@ +/*########################################################################################################################* +*--------------------------------------------------Vertex attribute config------------------------------------------------* +*#########################################################################################################################*/ + +// https://3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_ATTRIBBUFFERi_CONFIG1 +// Sets how to map first 8 vertex array components to vertex attributes (or padding) +static CC_INLINE void pica_set_attrib_array0_mapping(u32 mapping) { + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG1, mapping); +} + +// https://3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_ATTRIBBUFFERi_CONFIG2 +// Sets how to map last 4 vertex array components to vertex attributes, bytes per vertex, components count +static CC_INLINE void pica_set_attrib_array0_format(u32 num_attribs, u32 stride) { + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG2, (stride << 16) | (num_attribs << 28)); +} + + +/*########################################################################################################################* +*--------------------------------------------------Vertex shader constants------------------------------------------------* +*#########################################################################################################################*/ +// https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_INDEX +// https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_DATAi +#define UPLOAD_TYPE_F32 0x80000000 + +static CC_INLINE void pica_upload_mat4_constant(int offset, C3D_Mtx* value) { + GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, offset | UPLOAD_TYPE_F32); + GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)value, 16); +} + +static CC_INLINE void pica_upload_vec4_constant(int offset, C3D_FVec* value) { + GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, offset | UPLOAD_TYPE_F32); + GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)value, 4); +} diff --git a/src/Bitmap.c b/src/Bitmap.c index 3d445021e..4854a1538 100644 --- a/src/Bitmap.c +++ b/src/Bitmap.c @@ -64,7 +64,7 @@ void Bitmap_Scale(struct Bitmap* dst, struct Bitmap* src, /*########################################################################################################################* -*------------------------------------------------------PNG decoder--------------------------------------------------------* +*------------------------------------------------------PNG common---------------------------------------------------------* *#########################################################################################################################*/ #define PNG_IHDR_SIZE 13 #define PNG_PALETTE 256 @@ -79,7 +79,6 @@ enum PngFilter { PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH }; -typedef void (*Png_RowExpander)(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst); static const cc_uint8 pngSig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 }; /* 5.2 PNG signature */ @@ -87,6 +86,17 @@ cc_bool Png_Detect(const cc_uint8* data, cc_uint32 len) { return len >= PNG_SIG_SIZE && Mem_Equal(data, pngSig, PNG_SIG_SIZE); } + +/*########################################################################################################################* +*------------------------------------------------------PNG decoder--------------------------------------------------------* +*#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { + return ERR_NOT_SUPPORTED; +} +#else +typedef void (*Png_RowExpander)(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst); + /* 9 Filtering */ /* 13.9 Filtering */ static void Png_ReconstructFirst(cc_uint8 type, cc_uint8 bytesPerPixel, cc_uint8* line, cc_uint32 lineLen) { @@ -329,11 +339,6 @@ static BitmapCol ExpandRGB(cc_uint8 bitsPerSample, int r, int g, int b) { return BitmapCol_Make(r, g, b, 0); } -#ifdef CC_BUILD_32X -cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { - return ERR_NOT_SUPPORTED; -} -#else cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { cc_uint8 tmp[64]; cc_uint32 dataSize, fourCC; @@ -559,7 +564,13 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { /*########################################################################################################################* *------------------------------------------------------PNG encoder--------------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_FILESYSTEM +#if !defined CC_BUILD_FILESYSTEM +/* No point including encoding code when can't save screenshots anyways */ +cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, + Png_RowGetter getRow, cc_bool alpha, void* ctx) { + return ERR_NOT_SUPPORTED; +} +#else static void Png_Filter(cc_uint8 filter, const cc_uint8* cur, const cc_uint8* prior, cc_uint8* best, int lineLen, int bpp) { /* 3 bytes per pixel constant */ cc_uint8 a, b, c; @@ -667,7 +678,7 @@ static cc_result Png_EncodeCore(struct Bitmap* bmp, struct Stream* stream, cc_ui cc_uint8* curLine = buffer + (bmp->width * 4) * 1; cc_uint8* bestLine = buffer + (bmp->width * 4) * 2; -#if CC_BUILD_MAXSTACK <= (50 * 1024) +#if CC_BUILD_MAXSTACK <= (64 * 1024) struct ZLibState* zlState = (struct ZLibState*)Mem_TryAlloc(1, sizeof(struct ZLibState)); #else struct ZLibState _zlState; @@ -678,6 +689,7 @@ static cc_result Png_EncodeCore(struct Bitmap* bmp, struct Stream* stream, cc_ui int y, lineSize; cc_result res; + if (!zlState) return ERR_OUT_OF_MEMORY; /* stream may not start at 0 (e.g. when making default.zip) */ if ((res = stream->Position(stream, &stream_beg))) return res; @@ -749,11 +761,5 @@ cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, Mem_Free(buffer); return res; } -#else -/* No point including encoding code when can't save screenshots anyways */ -cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, - Png_RowGetter getRow, cc_bool alpha, void* ctx) { - return ERR_NOT_SUPPORTED; -} #endif diff --git a/src/BlockPhysics.c b/src/BlockPhysics.c index 626cde467..9cc206889 100644 --- a/src/BlockPhysics.c +++ b/src/BlockPhysics.c @@ -249,19 +249,22 @@ static void Physics_HandleSapling(int index, BlockID block) { below = BLOCK_AIR; if (y > 0) below = World.Blocks[index - World.OneY]; - if (below != BLOCK_GRASS) return; + /* Saplings stay alive on dirt */ + if (below == BLOCK_DIRT) return; + + /* Saplings grow if on grass in light, otherwise turn to air */ + Game_UpdateBlock(x, y, z, BLOCK_AIR); + if (below != BLOCK_GRASS || !Lighting.IsLit(x, y, z)) return; height = 5 + Random_Next(&physics_rnd, 3); - Game_UpdateBlock(x, y, z, BLOCK_AIR); - if (TreeGen_CanGrow(x, y, z, height)) { + if (TreeGen_CanGrow(x, y, z, height)) { count = TreeGen_Grow(x, y, z, height, coords, blocks); - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) + { Game_UpdateBlock(coords[i].x, coords[i].y, coords[i].z, blocks[i]); } - } else { - Game_UpdateBlock(x, y, z, BLOCK_SAPLING); } } diff --git a/src/Camera.c b/src/Camera.c index 30d98ab0f..a82a0d875 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -378,7 +378,7 @@ static void OnInit(void) { #ifdef CC_BUILD_WIN Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 40); -#elif defined CC_BUILD_SYMBIAN_3 || defined CC_BUILD_SYMBIAN_S60V5 +#elif defined CC_BUILD_SYMBIAN_3 || defined CC_BUILD_SYMBIAN_S60V5 || defined CC_BUILD_WINCE Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 70); #else Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 30); diff --git a/src/Certs.c b/src/Certs.c index 561dc6858..a9ab018f0 100644 --- a/src/Certs.c +++ b/src/Certs.c @@ -89,7 +89,7 @@ static int (*_X509_STORE_CTX_init)(X509_STORE_CTX* ctx, X509_STORE* store, #if defined CC_BUILD_WIN static const cc_string cryptoLib = String_FromConst("libcrypto.dll"); -#elif defined CC_BUILD_HAIKU +#elif defined CC_BUILD_HAIKU || defined CC_BUILD_LINUX static const cc_string cryptoLib = String_FromConst("libcrypto.so.3"); static const cc_string cryptoAlt = String_FromConst("libcrypto.so"); #else diff --git a/src/Core.h b/src/Core.h index 3dc3cea14..d14569f79 100644 --- a/src/Core.h +++ b/src/Core.h @@ -138,6 +138,7 @@ typedef cc_uint8 cc_bool; #define CC_WIN_BACKEND_COCOA 6 #define CC_WIN_BACKEND_BEOS 7 #define CC_WIN_BACKEND_ANDROID 8 +#define CC_WIN_BACKEND_WIN32CE 9 #define CC_GFX_BACKEND_SOFTGPU 1 #define CC_GFX_BACKEND_GL1 2 @@ -146,6 +147,8 @@ typedef cc_uint8 cc_bool; #define CC_GFX_BACKEND_D3D11 5 #define CC_GFX_BACKEND_VULKAN 6 #define CC_GFX_BACKEND_GL11 7 +#define CC_GFX_BACKEND_SOFTMIN 8 +#define CC_GFX_BACKEND_SOFTFP 9 #define CC_SSL_BACKEND_NONE 1 #define CC_SSL_BACKEND_BEARSSL 2 @@ -170,6 +173,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_PLUGINS #define CC_BUILD_FILESYSTEM #define CC_BUILD_ADVLIGHTING +#define CC_BUILD_COMPRESSION /*#define CC_BUILD_GL11*/ #ifndef CC_BUILD_MANUAL @@ -209,7 +213,8 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_D3D11 #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_OPENAL -#elif defined _WIN32 && !defined __WINSCW__ + #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL +#elif defined _WIN32 && !defined __WINSCW__ && !defined _WIN32_WCE #define CC_BUILD_WIN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL @@ -262,12 +267,42 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_FREETYPE #define CC_BUILD_AMIGA #define CC_BUILD_COOPTHREADED + #define CC_BUILD_TINYMEM #define CC_BUILD_LOWMEM #define CC_BUILD_NOMUSIC #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_RESOURCES + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_NETWORKING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION + #define CC_BUILD_MAXSTACK (32 * 1024) + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU +#elif defined PLAT_ATARIOS + #undef CC_BUILD_FREETYPE + #define CC_BUILD_ATARIOS + #define CC_BUILD_COOPTHREADED + #define CC_BUILD_TINYMEM + #define CC_BUILD_LOWMEM + #define CC_BUILD_NOMUSIC + #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_RESOURCES + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_NETWORKING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION + #define CC_BUILD_MAXSTACK (32 * 1024) + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ + #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL + #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #elif defined __linux__ #define CC_BUILD_LINUX #define CC_BUILD_POSIX @@ -329,6 +364,7 @@ typedef cc_uint8 cc_bool; #define CC_BIG_ENDIAN #define CC_BUILD_NOMUSIC #define CC_BUILD_NOSOUNDS + #define CC_BUILD_GL11_FALLBACK #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 @@ -408,7 +444,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_PLUGINS #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #define CC_DISABLE_LAUNCHER -#elif defined __psp__ +#elif defined PLAT_PSP #define CC_BUILD_PSP #define CC_BUILD_CONSOLE #define CC_BUILD_LOWMEM @@ -416,14 +452,14 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined __3DS__ +#elif defined PLAT_3DS #define CC_BUILD_3DS #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH #define CC_BUILD_DUALSCREEN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined GEKKO +#elif defined PLAT_GCWII #define CC_BUILD_GCWII #define CC_BUILD_CONSOLE #ifndef HW_RVL @@ -433,14 +469,14 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_SPLITSCREEN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined __vita__ +#elif defined PLAT_VITA #define CC_BUILD_PSVITA #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined _arch_dreamcast +#elif defined PLAT_DREAMCAST #define CC_BUILD_DREAMCAST #define CC_BUILD_CONSOLE #define CC_BUILD_LOWMEM @@ -456,7 +492,7 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined N64 +#elif defined PLAT_N64 #define CC_BIG_ENDIAN #define CC_BUILD_N64 #define CC_BUILD_CONSOLE @@ -490,20 +526,20 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOFPU #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI - #undef CC_BUILD_ADVLIGHTING - #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_EXTRA_MODELS - #define SOFTGPU_DISABLE_ZBUFFER #undef CC_VAR #define CC_VAR __attribute__((visibility("default"), section(".ewram"))) #undef CC_BIG_VAR #define CC_BIG_VAR __attribute__((section(".ewram"))) #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL - #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #elif defined PLAT_NDS #define CC_BUILD_NDS #define CC_BUILD_CONSOLE @@ -520,7 +556,7 @@ typedef cc_uint8 cc_bool; #endif #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined __WIIU__ +#elif defined PLAT_WIIU #define CC_BUILD_WIIU #define CC_BUILD_CONSOLE #define CC_BUILD_COOPTHREADED @@ -528,7 +564,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_TOUCH #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined __SWITCH__ +#elif defined PLAT_SWITCH #define CC_BUILD_SWITCH #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH @@ -591,14 +627,14 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOFPU #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI - #undef CC_BUILD_ADVLIGHTING - #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_EXTRA_MODELS - #define SOFTGPU_DISABLE_ZBUFFER - #define CC_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #elif defined __SYMBIAN32__ #define CC_BUILD_SYMBIAN @@ -616,7 +652,23 @@ typedef cc_uint8 cc_bool; #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #else #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define CC_DISABLE_ANIMATIONS #endif +#elif defined _WIN32_WCE + #define CC_BUILD_WINCE + #define CC_BUILD_NOMUSIC + #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FREETYPE + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ + #define CC_BUILD_TOUCH + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_WIN32CE + #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN + #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTFP + #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSS #endif #endif diff --git a/src/Deflate.c b/src/Deflate.c index 89ef37444..3d30f3980 100644 --- a/src/Deflate.c +++ b/src/Deflate.c @@ -141,6 +141,19 @@ cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) { /*########################################################################################################################* *--------------------------------------------------Inflate (decompress)---------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +void Inflate_Init2(struct InflateState* state, struct Stream* source) { + Process_Abort("Should never be called"); +} + +void Inflate_Process(struct InflateState* s) { + Process_Abort("Should never be called"); +} + +void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, struct Stream* underlying) { + Process_Abort("Should never be called"); +} +#else enum INFLATE_STATE_ { INFLATE_STATE_HEADER, INFLATE_STATE_UNCOMPRESSED_HEADER, INFLATE_STATE_UNCOMPRESSED_DATA, INFLATE_STATE_DYNAMIC_HEADER, @@ -787,11 +800,18 @@ void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, stru stream->meta.inflate = state; stream->Read = Inflate_StreamRead; } +#endif /*########################################################################################################################* *---------------------------------------------------Deflate (compress)----------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +void GZip_MakeStream(struct Stream* stream, struct GZipState* state, struct Stream* underlying) { + Process_Abort("Should never be called"); +} +#else + /* these are copies of len_base and dist_base, with UINT16_MAX instead of 0 for sentinel cutoff */ static const cc_uint16 deflate_len[30] = { 3,4,5,6,7,8,9,10,11,13, @@ -1141,11 +1161,19 @@ void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stre stream->Write = ZLib_StreamWriteFirst; stream->Close = ZLib_StreamClose; } +#endif /*########################################################################################################################* *--------------------------------------------------------ZipReader--------------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_ProcessEntry processor, + struct ZipEntry* entries, int maxEntries) { + return ERR_NOT_SUPPORTED; +} +#else + #define ZIP_MAXNAMELEN 512 /* Stores state for reading and processing entries in a .zip archive */ struct ZipState { @@ -1337,3 +1365,5 @@ cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_Proce } return 0; } +#endif + diff --git a/src/Entity.c b/src/Entity.c index 69b0a3ce7..8a7a42903 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -43,6 +43,7 @@ void Entity_Init(struct Entity* e) { e->Flags = ENTITY_FLAG_HAS_MODELVB; e->uScale = 1.0f; e->vScale = 1.0f; + e->PushStrength = 1.0f; e->_skinReqID = 0; e->SkinRaw[0] = '\0'; e->NameRaw[0] = '\0'; @@ -66,15 +67,15 @@ void Entity_GetTransform(struct Entity* e, Vec3 pos, Vec3 scale, struct Matrix* struct Matrix tmp; Matrix_Scale(m, scale.x, scale.y, scale.z); - if (e->RotZ) { + if (e->RotZ != 0.0f) { Matrix_RotateZ( &tmp, -e->RotZ * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } - if (e->RotX) { + if (e->RotX != 0.0f) { Matrix_RotateX( &tmp, -e->RotX * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } - if (e->RotY) { + if (e->RotY != 0.0f) { Matrix_RotateY( &tmp, -e->RotY * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } @@ -206,49 +207,63 @@ cc_bool Entity_TouchesAnyWater(struct Entity* e) { /*########################################################################################################################* *------------------------------------------------------Entity skins-------------------------------------------------------* *#########################################################################################################################*/ -static struct Entity* Entity_FirstOtherWithSameSkinAndFetchedSkin(struct Entity* except) { - struct Entity* e; - cc_string skin, eSkin; - int i; - - skin = String_FromRawArray(except->SkinRaw); - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i] || Entities.List[i] == except) continue; - - e = Entities.List[i]; - eSkin = String_FromRawArray(e->SkinRaw); - if (e->SkinFetchState && String_Equals(&skin, &eSkin)) return e; - } - return NULL; -} - /* Copies skin data from another entity */ static void Entity_CopySkin(struct Entity* dst, struct Entity* src) { - dst->TextureId = src->TextureId; - dst->SkinType = src->SkinType; - dst->uScale = src->uScale; - dst->vScale = src->vScale; - dst->MobTextureId = src->MobTextureId; + dst->TextureId = src->TextureId; + dst->SkinType = src->SkinType; + dst->uScale = src->uScale; + dst->vScale = src->vScale; } /* Resets skin data for the given entity */ static void Entity_ResetSkin(struct Entity* e) { - e->uScale = 1.0f; e->vScale = 1.0f; - e->MobTextureId = 0; e->TextureId = 0; - e->SkinType = SKIN_64x32; + e->uScale = 1.0f; + e->vScale = 1.0f; +} + +static void CheckSkin_Unchecked(struct Entity* e) { + cc_string skin, eSkin; + struct Entity* other; + cc_uint8 flags; + cc_result res; + int i; + + skin = String_FromRawArray(e->SkinRaw); + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + other = Entities.List[i]; + if (!other) continue; + /* Don't bother checking for other == e, as e->state is UNCHECKED anyways */ + if (other->SkinFetchState < SKIN_FETCH_DOWNLOADING) continue; + + eSkin = String_FromRawArray(other->SkinRaw); + if (!String_Equals(&skin, &eSkin)) continue; + + /* Another entity with same skin either finished or is downloading */ + if (other->SkinFetchState == SKIN_FETCH_COMPLETED) { + Entity_CopySkin(e, other); + e->SkinFetchState = SKIN_FETCH_COMPLETED; + } else { + e->SkinFetchState = SKIN_FETCH_WAITINGFOR; + } + return; + } + + flags = e == &LocalPlayer_Instances[0].Base ? HTTP_FLAG_NOCACHE : 0; + e->_skinReqID = Http_AsyncGetSkin(&skin, flags); + e->SkinFetchState = SKIN_FETCH_DOWNLOADING; } /* Copies or resets skin data for all entity with same skin */ static void Entity_SetSkinAll(struct Entity* source, cc_bool reset) { struct Entity* e; cc_string skin, eSkin; + skin = String_FromRawArray(source->SkinRaw); int i; - skin = String_FromRawArray(source->SkinRaw); - source->MobTextureId = Utils_IsUrlPrefix(&skin) ? source->TextureId : 0; - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { if (!Entities.List[i]) continue; e = Entities.List[i]; @@ -326,7 +341,6 @@ static cc_result ApplySkin(struct Entity* e, struct Bitmap* bmp, struct Stream* if ((res = Png_Decode(bmp, src))) return res; Gfx_DeleteTexture(&e->TextureId); - Entity_SetSkinAll(e, true); if ((res = EnsurePow2Skin(e, bmp))) return res; e->SkinType = Utils_CalcSkinType(bmp); @@ -355,49 +369,81 @@ static void LogInvalidSkin(cc_result res, const cc_string* skin, const cc_uint8* Logger_WarnFunc(&msg); } -static void Entity_CheckSkin(struct Entity* e) { - struct Entity* first; +static void CheckSkin_Downloading(struct Entity* e) { struct HttpRequest item; struct Stream mem; struct Bitmap bmp; cc_string skin; - cc_uint8 flags; cc_result res; - /* Don't check skin if don't have to */ - if (!e->Model->usesSkin) return; - if (e->SkinFetchState == SKIN_FETCH_COMPLETED) return; + if (!Http_GetResult(e->_skinReqID, &item)) return; + Entity_SetSkinAll(e, true); + if (!item.success) return; + + Stream_ReadonlyMemory(&mem, item.data, item.size); skin = String_FromRawArray(e->SkinRaw); - if (!e->SkinFetchState) { - first = Entity_FirstOtherWithSameSkinAndFetchedSkin(e); - flags = e == &LocalPlayer_Instances[0].Base ? HTTP_FLAG_NOCACHE : 0; - - if (!first) { - e->_skinReqID = Http_AsyncGetSkin(&skin, flags); - e->SkinFetchState = SKIN_FETCH_DOWNLOADING; - } else { - Entity_CopySkin(e, first); - e->SkinFetchState = SKIN_FETCH_COMPLETED; - return; - } + if ((res = ApplySkin(e, &bmp, &mem, &skin))) { + LogInvalidSkin(res, &skin, item.data, item.size); } - if (!Http_GetResult(e->_skinReqID, &item)) return; - - if (!item.success) { - Entity_SetSkinAll(e, true); - } else { - Stream_ReadonlyMemory(&mem, item.data, item.size); - - if ((res = ApplySkin(e, &bmp, &mem, &skin))) { - LogInvalidSkin(res, &skin, item.data, item.size); - } - Mem_Free(bmp.scan0); - } + Mem_Free(bmp.scan0); HttpRequest_Free(&item); } +static void Entity_CheckSkin(struct Entity* e) { + /* Don't check skin if don't have to */ + if (!e->Model->usesSkin) return; + + switch (e->SkinFetchState) + { + case SKIN_FETCH_UNCHECKED: + CheckSkin_Unchecked(e); return; + case SKIN_FETCH_WAITINGFOR: + return; /* Waiting for another entity to download it */ + case SKIN_FETCH_DOWNLOADING: + CheckSkin_Downloading(e); return; + case SKIN_FETCH_COMPLETED: + return; /* Nothing to do as skin has been downloaded */ + } +} + +/* Returns whether this entity is currently waiting on given skin to download */ +static CC_INLINE cc_bool IsWaitingForSkinToDownload(struct Entity* e, cc_string* skin) { + cc_string eSkin; + if (e->SkinFetchState != SKIN_FETCH_WAITINGFOR) return false; + + eSkin = String_FromRawArray(e->SkinRaw); + return String_Equals(skin, &eSkin); +} + +/* Transfers skin downloading responsibility to another entity */ +static void TransferSkinDownload(struct Entity* e, struct Entity* src) { + e->SkinFetchState = SKIN_FETCH_DOWNLOADING; + e->_skinReqID = src->_skinReqID; +} + +/* Either transfers skin download or cancels it altogether */ +static void DerefDownloadingSkin(struct Entity* src) { + struct Entity* e; + cc_string skin = String_FromRawArray(src->SkinRaw); + int i; + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + e = Entities.List[i]; + + if (!IsWaitingForSkinToDownload(e, &skin)) continue; + Platform_Log1("Transferring skin download: %s", &skin); + TransferSkinDownload(e, src); + return; + } + + Platform_Log1("Cancelling skin download: %s", &skin); + Http_TryCancel(src->_skinReqID); +} + /* Returns true if no other entities are sharing this skin texture */ static cc_bool CanDeleteTexture(struct Entity* except) { int i; @@ -413,9 +459,10 @@ static cc_bool CanDeleteTexture(struct Entity* except) { CC_NOINLINE static void DeleteSkin(struct Entity* e) { if (CanDeleteTexture(e)) Gfx_DeleteTexture(&e->TextureId); + if (e->SkinFetchState == SKIN_FETCH_DOWNLOADING) DerefDownloadingSkin(e); Entity_ResetSkin(e); - e->SkinFetchState = 0; + e->SkinFetchState = SKIN_FETCH_UNCHECKED; } void Entity_SetSkin(struct Entity* e, const cc_string* skin) { @@ -424,9 +471,11 @@ void Entity_SetSkin(struct Entity* e, const cc_string* skin) { if (Utils_IsUrlPrefix(skin)) { tmp = *skin; + e->NonHumanSkin = true; } else { String_InitArray(tmp, tmpBuffer); String_AppendColorless(&tmp, skin); + e->NonHumanSkin = false; } String_CopyToRawArray(e->SkinRaw, &tmp); } diff --git a/src/Entity.h b/src/Entity.h index 69988c798..3c719475d 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -85,10 +85,14 @@ struct EntityVTABLE { cc_bool (*ShouldRenderName)(struct Entity* e); }; -/* Skin is still being downloaded asynchronously */ -#define SKIN_FETCH_DOWNLOADING 1 -/* Skin was downloaded or copied from another entity with the same skin. */ -#define SKIN_FETCH_COMPLETED 2 +/* Entity's skin has not been checked yet */ +#define SKIN_FETCH_UNCHECKED 0 +/* Waiting for another entity with the same skin to finish downloading it */ +#define SKIN_FETCH_WAITINGFOR 1 +/* Entity's skin is currently being downloaded asynchronously */ +#define SKIN_FETCH_DOWNLOADING 2 +/* Entity's skin has been downloaded or copied from another entity with the same skin. */ +#define SKIN_FETCH_COMPLETED 3 /* true to restrict model scale (needed for local player, giant model collisions are too costly) */ #define ENTITY_FLAG_MODEL_RESTRICTED_SCALE 0x01 @@ -107,6 +111,7 @@ struct Entity { const struct EntityVTABLE* VTABLE; Vec3 Position; /* NOTE: Do NOT change order of yaw/pitch, this will break models in plugins */ + /* When adding a new field to structs that plugins can access, add them to the end to avoid breaking compatibility. */ float Pitch, Yaw, RotX, RotY, RotZ; Vec3 Velocity; @@ -121,7 +126,8 @@ struct Entity { cc_uint8 SkinType; cc_uint8 SkinFetchState; cc_bool NoShade, OnGround; - GfxResourceID TextureId, MobTextureId; + GfxResourceID TextureId; + cc_bool NonHumanSkin; /* Whether custom skin is also used on non humanoid models */ float uScale, vScale; struct AnimatedComp Anim; @@ -133,6 +139,8 @@ struct Entity { /* Current state is linearly interpolated between prev and next */ struct EntityLocation prev, next; GfxResourceID ModelVB; + + float PushStrength; }; typedef cc_bool (*Entity_TouchesCondition)(BlockID block); diff --git a/src/EntityComponents.c b/src/EntityComponents.c index 034f6344e..12e7b309c 100644 --- a/src/EntityComponents.c +++ b/src/EntityComponents.c @@ -1047,7 +1047,7 @@ void PhysicsComp_DoEntityPush(struct Entity* entity) { if (dist < 0.002f || dist > 1.0f) continue; /* TODO: range needs to be lower? */ Vec3_Normalise(&dir); - pushStrength = (1 - dist) / 32.0f; /* TODO: should be 24/25 */ + pushStrength = (other->PushStrength - dist) / 32.0f; /* TODO: should be 24/25 */ /* entity.Velocity -= dir * pushStrength */ Vec3_Mul1By(&dir, pushStrength); Vec3_SubBy(&entity->Velocity, &dir); diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index d88564504..7476c8071 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -704,6 +704,7 @@ static CC_NOINLINE void BuildMapSides(void) { struct VertexTextured* data; if (!World.Loaded) return; + if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return; block = Env.SidesBlock; if (Blocks.Draw[block] == DRAW_GAS) return; @@ -756,6 +757,7 @@ static CC_NOINLINE void BuildMapEdges(void) { struct VertexTextured* data; if (!World.Loaded) return; + if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return; block = Env.EdgeBlock; if (Blocks.Draw[block] == DRAW_GAS) return; diff --git a/src/ExtMath.c b/src/ExtMath.c index 5c31554d6..c032f283a 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -98,7 +98,7 @@ float sqrtf(float x) { } #elif defined __GNUC__ || defined NXDK /* Defined in .h using builtins */ -#elif defined __TINYC__ +#elif defined __TINYC__ || defined CC_BUILD_ATARIOS || defined CC_BUILD_AMIGA /* Older versions of TinyC don't support fabsf or sqrtf */ /* Those can be used though if compiling with newer TinyC */ /* versions for a very small performance improvement */ diff --git a/src/Game.c b/src/Game.c index 4439fc26b..b51f4b613 100644 --- a/src/Game.c +++ b/src/Game.c @@ -840,7 +840,7 @@ void Game_RenderFrame(void) { if (Game_ScreenshotRequested) Game_TakeScreenshot(); Gfx_EndFrame(); - if (gfx_minFrameMs) LimitFPS(); + if (gfx_minFrameMs != 0.0f) LimitFPS(); } void Game_Free(void) { diff --git a/src/Graphics.h b/src/Graphics.h index 509dc421b..81b763f26 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -103,6 +103,8 @@ CC_VAR extern struct _GfxData { #define GFX_LIMIT_MAX_VERTEX_SIZE 0x04 /* Whether the graphics backend is minimal (no fog, clouds, sky) */ #define GFX_LIMIT_MINIMAL 0x08 +/* Whether the graphics backend shouldn't have horizon/border drawn */ +#define GFX_LIMIT_WORLD_ONLY 0x10 extern const cc_string Gfx_LowPerfMessage; diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 02a21331c..a8d5fc9bf 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -25,6 +25,8 @@ #include "../misc/opengl/GL1Funcs.h" #if defined CC_BUILD_SYMBIAN #include "../misc/opengl/GL2Funcs.h" + +static cc_bool mbx; #endif #if CC_BUILD_MAXSTACK <= (64 * 1024) @@ -84,7 +86,9 @@ void Gfx_Create(void) { #ifdef CC_BUILD_GL11_FALLBACK GLContext_GetAll(coreFuncs, Array_Elems(coreFuncs)); #endif +#ifndef CC_BUILD_GLES customMipmapsLevels = true; +#endif Gfx.BackendType = CC_GFX_BACKEND_GL1; GL_InitCommon(); @@ -203,27 +207,27 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { #define IB_PTR NULL static void GL_SetupVbColoured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, VB_PTR + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, VB_PTR + 12); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + 12)); } static void GL_SetupVbTextured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 16)); } static void GL_SetupVbColoured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, VB_PTR + offset + 12); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + offset + 12)); } static void GL_SetupVbTextured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 16)); } void Gfx_SetVertexFormat(VertexFormat fmt) { @@ -263,9 +267,9 @@ void Gfx_DrawVb_IndexedTris(int verticesCount) { void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 16)); _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); } @@ -335,6 +339,21 @@ static void SetAlphaTest(cc_bool enabled) { void Gfx_DepthOnlyRendering(cc_bool depthOnly) { cc_bool enabled = !depthOnly; +#ifdef CC_BUILD_SYMBIAN + if (mbx) { + /* On PowerVR MBX cards, glColorMask appears to be unimplemented in hardware */ + /* and thus any usage of it significantly hurts performance. */ + /* So instead, draw with blending of 'new_RGB = current_RGB' - that way */ + /* depth buffer is updated while the colour buffer remain unchanged. */ + if (depthOnly) { + _glBlendFunc(GL_ZERO, GL_ONE); + Gfx_SetAlphaBlending(true); + } else { + _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + return; + } +#endif SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); @@ -422,6 +441,18 @@ cc_bool Gfx_WarnIfNecessary(void) { Gfx.Limitations |= GFX_LIMIT_VERTEX_ONLY_FOG; return true; } +#if defined CC_BUILD_SYMBIAN + if (String_ContainsConst(&renderer, "SGX")) { + } else if (String_ContainsConst(&renderer, "MBX")) { + Gfx.Limitations |= GFX_LIMIT_MINIMAL; + mbx = true; + } else if (!String_ContainsConst(&renderer, "HW")) { + Chat_AddRaw("&cSoftware rendering is being used, performance will greatly suffer."); + + Gfx.Limitations |= GFX_LIMIT_MINIMAL; + return true; + } +#endif return false; } @@ -554,7 +585,7 @@ static void APIENTRY gl10_colorPointer(GLint size, GLenum type, GLsizei stride, static void APIENTRY gl10_texCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { } static void APIENTRY gl10_vertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { - gl10_vb = cur_vb->data + offset; + gl10_vb = cur_vb->data + (cc_uintptr)offset; } diff --git a/src/Graphics_GL11.c b/src/Graphics_GL11.c index 60a75cc58..5c84fe433 100644 --- a/src/Graphics_GL11.c +++ b/src/Graphics_GL11.c @@ -30,6 +30,17 @@ typedef void (*GL_SetupVBRangeFunc)(int startVertex); static GL_SetupVBFunc gfx_setupVBFunc; static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; +static void CheckSupport(void) { + static const cc_string bgraExt = String_FromConst("GL_EXT_bgra"); + cc_string extensions = String_FromReadonly((const char*)_glGetString(GL_EXTENSIONS)); + const GLubyte* ver = _glGetString(GL_VERSION); + + /* Version string is always: x.y. (and whatever afterwards) */ + int major = ver[0] - '0', minor = ver[2] - '0'; + /* Some old IRIX cards don't support BGRA */ + convert_rgba = major == 1 && minor <= 1 && !String_CaselessContains(&extensions, &bgraExt); +} + void Gfx_Create(void) { GLContext_Create(); GL_InitCommon(); @@ -37,6 +48,7 @@ void Gfx_Create(void) { MakeIndices(gl_indices, GFX_MAX_INDICES, NULL); Gfx_RestoreState(); GLContext_SetVSync(gfx_vsync); + CheckSupport(); } diff --git a/src/Graphics_SoftFP.c b/src/Graphics_SoftFP.c new file mode 100644 index 000000000..0ba5e8f74 --- /dev/null +++ b/src/Graphics_SoftFP.c @@ -0,0 +1,1474 @@ +#include "Core.h" +#if CC_GFX_BACKEND == CC_GFX_BACKEND_SOFTFP +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" +#include +#include + + +// 16.16 fixed point +#define FP_SHIFT 16 +#define FP_ONE (1 << FP_SHIFT) +#define FP_HALF (FP_ONE >> 1) +#define FP_MASK ((1 << FP_SHIFT) - 1) + +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +#define FloatToFixed(x) ((int)((x) * FP_ONE)) +#define FixedToFloat(x) ((float)(x) / FP_ONE) +#define FixedToInt(x) ((x) >> FP_SHIFT) +#define IntToFixed(x) ((x) << FP_SHIFT) + +#define FixedMul(a, b) (((int64_t)(a) * (b)) >> FP_SHIFT) + +#define FixedDiv(a, b) (((int64_t)(a) << FP_SHIFT) / (b)) + +static int FixedReciprocal(int x) { + if (x == 0) return 0; + int64_t res = ((int64_t)FP_ONE << FP_SHIFT) / (int64_t)x; // (1<<32)/x -> fixed reciprocal + if (res > INT_MAX) return INT_MAX; + if (res < INT_MIN) return INT_MIN; + return (int)res; +} + +static cc_bool faceCulling; +static int fb_width, fb_height; +static struct Bitmap fb_bmp; +static int vp_hwidth_fp, vp_hheight_fp; +static int fb_maxX, fb_maxY; + +static BitmapCol* colorBuffer; +static BitmapCol clearColor; +static cc_bool colWrite = true; +static int cb_stride; + +static int* depthBuffer; +static cc_bool depthTest = true; +static cc_bool depthWrite = true; +static int db_stride; + +static void* gfx_vertices; +static GfxResourceID white_square; + +typedef struct FixedMatrix { + int m[4][4]; +} FixedMatrix; + +typedef struct VertexFixed { + int x, y, z, w; + int u, v; + PackedCol c; +} VertexFixed; + +static int tex_offseting; +static int texOffsetX_fp, texOffsetY_fp; // Fixed point texture offsets +static FixedMatrix _view_fp, _proj_fp, _mvp_fp; + +static void Gfx_RestoreState(void) { + InitDefaultResources(); + + struct Bitmap bmp; + BitmapCol pixels[1] = { BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 1, 1, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +static void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + Gfx.MaxTexWidth = 4096; + Gfx.MaxTexHeight = 4096; + Gfx.Created = true; + Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; + Gfx.Limitations = GFX_LIMIT_MINIMAL; + + Gfx_RestoreState(); +} + +static void DestroyBuffers(void) { + Window_FreeFramebuffer(&fb_bmp); + Mem_Free(depthBuffer); + depthBuffer = NULL; +} + +void Gfx_Free(void) { + Gfx_FreeState(); + DestroyBuffers(); +} + +typedef struct CCTexture { + int width, height; + BitmapCol pixels[]; +} CCTexture; + +static CCTexture* curTexture; +static BitmapCol* curTexPixels; +static int curTexWidth, curTexHeight; +static int texWidthMask, texHeightMask; +static int texSinglePixel; + +void Gfx_BindTexture(GfxResourceID texId) { + if (!texId) texId = white_square; + CCTexture* tex = texId; + + curTexture = tex; + curTexPixels = tex->pixels; + curTexWidth = tex->width; + curTexHeight = tex->height; + + texWidthMask = (1 << Math_ilog2(tex->width)) - 1; + texHeightMask = (1 << Math_ilog2(tex->height)) - 1; + + texSinglePixel = curTexWidth == 1; +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { + GfxResourceID data = *texId; + if (data) Mem_Free(data); + *texId = NULL; +} + +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)Mem_Alloc(2 + bmp->width * bmp->height, 4, "Texture"); + + tex->width = bmp->width; + tex->height = bmp->height; + + CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, + bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, + bmp->width, bmp->height); + return tex; +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)texId; + BitmapCol* dst = (tex->pixels + x) + y * tex->width; + + CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, + part->scan0, rowWidth * BITMAPCOLOR_SIZE, + part->width, part->height); +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + faceCulling = enabled; +} + +static void SetAlphaTest(cc_bool enabled) { +} + +static void SetAlphaBlend(cc_bool enabled) { +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +static void ClearColorBuffer(void) { + int i, x, y, size = fb_width * fb_height; + + if (cb_stride == fb_width) { + Mem_Set(colorBuffer, clearColor, sizeof(BitmapCol) * size); + } else { + for (y = 0; y < fb_height; y++) { + i = y * cb_stride; + for (x = 0; x < fb_width; x++) { + colorBuffer[i + x] = clearColor; + } + } + } +} + +static void ClearDepthBuffer(void) { + int i, size = fb_width * fb_height; + int maxDepth = 0x7FFFFFFF; // max depth + for (i = 0; i < size; i++) depthBuffer[i] = maxDepth; +} + +void Gfx_ClearBuffers(GfxBuffers buffers) { + if (buffers & GFX_BUFFER_COLOR) ClearColorBuffer(); + if (buffers & GFX_BUFFER_DEPTH) ClearDepthBuffer(); +} + +void Gfx_ClearColor(PackedCol color) { + int R = PackedCol_R(color); + int G = PackedCol_G(color); + int B = PackedCol_B(color); + int A = PackedCol_A(color); + + clearColor = BitmapCol_Make(R, G, B, A); +} + +void Gfx_SetDepthTest(cc_bool enabled) { + depthTest = enabled; +} + +void Gfx_SetDepthWrite(cc_bool enabled) { + depthWrite = enabled; +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + colWrite = !depthOnly; +} + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +// Preprocess vertex buffers into fixed point values +struct FPVertexColoured { + int x, y, z; + BitmapCol c; +}; + +struct FPVertexTextured { + int x, y, z; + BitmapCol c; + int u, v; +}; + +static VertexFormat buf_fmt; +static int buf_count; + +static void PreprocessTexturedVertices(void) { + struct FPVertexTextured* dst = gfx_vertices; + struct VertexTextured* src = gfx_vertices; + + for (int i = 0; i < buf_count; i++, src++, dst++) + { + dst->x = FloatToFixed(src->x); + dst->y = FloatToFixed(src->y); + dst->z = FloatToFixed(src->z); + dst->u = FloatToFixed(src->U); + dst->v = FloatToFixed(src->V); + dst->c = src->Col; + } +} + +static void PreprocessColouredVertices(void) { + struct FPVertexColoured* dst = gfx_vertices; + struct VertexColoured* src = gfx_vertices; + + for (int i = 0; i < buf_count; i++, src++, dst++) + { + dst->x = FloatToFixed(src->x); + dst->y = FloatToFixed(src->y); + dst->z = FloatToFixed(src->z); + dst->c = src->Col; + } +} + +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + buf_fmt = fmt; + buf_count = count; + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; + + if (buf_fmt == VERTEX_FORMAT_TEXTURED) { + PreprocessTexturedVertices(); + } else { + PreprocessColouredVertices(); + } +} + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return Gfx_LockVb(vb, fmt, count); +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { Gfx_UnlockVb(vb); } + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ + +static void MatrixToFixed(FixedMatrix* dst, const struct Matrix* src) { + dst->m[0][0] = FloatToFixed(src->row1.x); dst->m[0][1] = FloatToFixed(src->row1.y); + dst->m[0][2] = FloatToFixed(src->row1.z); dst->m[0][3] = FloatToFixed(src->row1.w); + + dst->m[1][0] = FloatToFixed(src->row2.x); dst->m[1][1] = FloatToFixed(src->row2.y); + dst->m[1][2] = FloatToFixed(src->row2.z); dst->m[1][3] = FloatToFixed(src->row2.w); + + dst->m[2][0] = FloatToFixed(src->row3.x); dst->m[2][1] = FloatToFixed(src->row3.y); + dst->m[2][2] = FloatToFixed(src->row3.z); dst->m[2][3] = FloatToFixed(src->row3.w); + + dst->m[3][0] = FloatToFixed(src->row4.x); dst->m[3][1] = FloatToFixed(src->row4.y); + dst->m[3][2] = FloatToFixed(src->row4.z); dst->m[3][3] = FloatToFixed(src->row4.w); +} + +static void MatrixMulFixed(FixedMatrix* dst, const FixedMatrix* a, const FixedMatrix* b) { + int i, j, k; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + int64_t sum = 0; + for (k = 0; k < 4; k++) { + sum += (int64_t)a->m[i][k] * b->m[k][j]; + } + dst->m[i][j] = (int)(sum >> FP_SHIFT); + } + } +} + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) { + MatrixToFixed(&_view_fp, matrix); + } + if (type == MATRIX_PROJ) { + MatrixToFixed(&_proj_fp, matrix); + } + + MatrixMulFixed(&_mvp_fp, &_view_fp, &_proj_fp); +} + +void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { + MatrixToFixed(&_view_fp, view); + MatrixToFixed(&_proj_fp, proj); + + MatrixMulFixed(&_mvp_fp, &_view_fp, &_proj_fp); + + Matrix_Mul(mvp, view, proj); +} + +void Gfx_EnableTextureOffset(float x, float y) { + tex_offseting = true; + texOffsetX_fp = FloatToFixed(x); + texOffsetY_fp = FloatToFixed(y); +} + +void Gfx_DisableTextureOffset(void) { + tex_offseting = false; +} + +static CC_NOINLINE void ShiftTextureCoords(int count) { + for (int i = 0; i < count; i++) + { + struct FPVertexTextured* v = (struct FPVertexTextured*)gfx_vertices + i; + v->u += texOffsetX_fp; // TODO avoid overflow + v->v += texOffsetY_fp; + } +} + +static CC_NOINLINE void UnshiftTextureCoords(int count) { + for (int i = 0; i < count; i++) + { + struct FPVertexTextured* v = (struct FPVertexTextured*)gfx_vertices + i; + v->u -= texOffsetX_fp; // TODO avoid overflow + v->v -= texOffsetY_fp; + } +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } + +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.1f; + + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ + +enum { PLANE_LEFT=0, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + +static int PlaneDistFixed(const VertexFixed* v, int plane) { + int64_t result; + switch (plane) { + case PLANE_LEFT: + result = (int64_t)v->x + v->w; + break; + case PLANE_RIGHT: + result = (int64_t)v->w - v->x; + break; + case PLANE_BOTTOM: + result = (int64_t)v->y + v->w; + break; + case PLANE_TOP: + result = (int64_t)v->w - v->y; + break; + case PLANE_NEAR: + result = v->z; + break; + case PLANE_FAR: + result = (int64_t)v->w - (v->z >> 2); //hacked + break; + default: + return 0; + } + + // Clamp to valid range + if (result > INT_MAX) return INT_MAX; + if (result < INT_MIN) return INT_MIN; + return (int)result; +} + +static void LerpClipFixed(VertexFixed* out, const VertexFixed* a, const VertexFixed* b, int t) { + if (t < 0) t = 0; + if (t > FP_ONE) t = FP_ONE; + + int invt = FP_ONE - t; + + int64_t x_interp = ((int64_t)invt * a->x + (int64_t)t * b->x) >> FP_SHIFT; + int64_t y_interp = ((int64_t)invt * a->y + (int64_t)t * b->y) >> FP_SHIFT; + int64_t z_interp = ((int64_t)invt * a->z + (int64_t)t * b->z) >> FP_SHIFT; + int64_t w_interp = ((int64_t)invt * a->w + (int64_t)t * b->w) >> FP_SHIFT; + int64_t u_interp = ((int64_t)invt * a->u + (int64_t)t * b->u) >> FP_SHIFT; + int64_t v_interp = ((int64_t)invt * a->v + (int64_t)t * b->v) >> FP_SHIFT; + + // Clamp results + out->x = (x_interp > INT_MAX) ? INT_MAX : (x_interp < INT_MIN) ? INT_MIN : (int)x_interp; + out->y = (y_interp > INT_MAX) ? INT_MAX : (y_interp < INT_MIN) ? INT_MIN : (int)y_interp; + out->z = (z_interp > INT_MAX) ? INT_MAX : (z_interp < INT_MIN) ? INT_MIN : (int)z_interp; + out->w = (w_interp > INT_MAX) ? INT_MAX : (w_interp < INT_MIN) ? INT_MIN : (int)w_interp; + out->u = (u_interp > INT_MAX) ? INT_MAX : (u_interp < INT_MIN) ? INT_MIN : (int)u_interp; + out->v = (v_interp > INT_MAX) ? INT_MAX : (v_interp < INT_MIN) ? INT_MIN : (int)v_interp; + + out->c = (t < FP_HALF) ? a->c : b->c; +} + +static int SafeFixedDiv(int numerator, int denominator) { + if (denominator == 0) return FP_HALF; + if (ABS(denominator) < 16) return FP_HALF; // Avoid extreme divisions + + int64_t result = ((int64_t)numerator << FP_SHIFT) / denominator; + + if (result > FP_ONE) return FP_ONE; + if (result < 0) return 0; + return (int)result; +} + +static int ClipPolygonPlaneFixed(const VertexFixed* in, int inCount, VertexFixed* out, int plane) { + if (inCount == 0) return 0; + if (inCount > 15) inCount = 15; // Safety limit + + int outCount = 0; + + for (int i = 0; i < inCount; i++) { + const VertexFixed* cur = &in[i]; + const VertexFixed* next = &in[(i + 1) % inCount]; + + int dCur = PlaneDistFixed(cur, plane); + int dNext = PlaneDistFixed(next, plane); + cc_bool curIn = dCur >= 0; + cc_bool nextIn = dNext >= 0; + + if (curIn && nextIn) { + // Both inside + out[outCount++] = *next; + } else if (curIn && !nextIn) { + // Exiting + int denom = dCur - dNext; + int t = SafeFixedDiv(dCur, denom); + + VertexFixed intersection; + LerpClipFixed(&intersection, cur, next, t); + out[outCount++] = intersection; + } else if (!curIn && nextIn) { + // Entering + int denom = dCur - dNext; + int t = SafeFixedDiv(dCur, denom); + + VertexFixed intersection; + LerpClipFixed(&intersection, cur, next, t); + out[outCount++] = intersection; + out[outCount++] = *next; + } + // Both outside + + if (outCount >= 15) break; // Safety limit + } + + return outCount; +} + +static int ClipTriangleToFrustumFixed(const VertexFixed tri[3], VertexFixed* outPoly) { + VertexFixed buf1[16], buf2[16]; + VertexFixed* src = buf1; + VertexFixed* dst = buf2; + + src[0] = tri[0]; + src[1] = tri[1]; + src[2] = tri[2]; + int count = 3; + + for (int i = 0; i < 3; i++) { + if (src[i].w == 0) { + return 0; + } + } + + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + + for (int p = 0; p < 6; p++) { + int newCount = ClipPolygonPlaneFixed(src, count, dst, planes[p]); + + if (newCount == 0) { + return 0; + } + + // Swap buffers + VertexFixed* tmp = src; + src = dst; + dst = tmp; + count = newCount; + + if (count > 15) count = 15; // Safety limit + } + + for (int i = 0; i < count; i++) { + outPoly[i] = src[i]; + } + + return count; +} + +static void TransformVertex2D(int index, VertexFixed* vertex) { + struct FPVertexColoured* v_col; + struct FPVertexTextured* v_tex; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + v_col = (struct FPVertexColoured*)gfx_vertices + index; + vertex->x = v_col->x; + vertex->y = v_col->y; + vertex->u = 0; + vertex->v = 0; + vertex->c = v_col->c; + } else { + v_tex = (struct FPVertexTextured*)gfx_vertices + index; + vertex->x = v_tex->x; + vertex->y = v_tex->y; + vertex->u = v_tex->u; + vertex->v = v_tex->v; + vertex->c = v_tex->c; + } +} + +static int TransformVertex3D(int index, VertexFixed* vertex) { + int pos_x, pos_y, pos_z; + struct FPVertexColoured* v_col; + struct FPVertexTextured* v_tex; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + v_col = (struct FPVertexColoured*)gfx_vertices + index; + vertex->x = v_col->x; + vertex->y = v_col->y; + vertex->z = v_col->z; + vertex->u = 0; + vertex->v = 0; + vertex->c = v_col->c; + } else { + v_tex = (struct FPVertexTextured*)gfx_vertices + index; + vertex->x = v_tex->x; + vertex->y = v_tex->y; + vertex->z = v_tex->z; + vertex->u = v_tex->u; + vertex->v = v_tex->v; + vertex->c = v_tex->c; + } + + pos_x = vertex->x; + pos_y = vertex->y; + pos_z = vertex->z; + + if (ABS(pos_x) > (1 << 28) || ABS(pos_y) > (1 << 28) || ABS(pos_z) > (1 << 28)) { + return 0; + } + + int64_t x_temp = (int64_t)pos_x * _mvp_fp.m[0][0] + (int64_t)pos_y * _mvp_fp.m[1][0] + + (int64_t)pos_z * _mvp_fp.m[2][0] + ((int64_t)_mvp_fp.m[3][0] << FP_SHIFT); + int64_t y_temp = (int64_t)pos_x * _mvp_fp.m[0][1] + (int64_t)pos_y * _mvp_fp.m[1][1] + + (int64_t)pos_z * _mvp_fp.m[2][1] + ((int64_t)_mvp_fp.m[3][1] << FP_SHIFT); + int64_t z_temp = (int64_t)pos_x * _mvp_fp.m[0][2] + (int64_t)pos_y * _mvp_fp.m[1][2] + + (int64_t)pos_z * _mvp_fp.m[2][2] + ((int64_t)_mvp_fp.m[3][2] << FP_SHIFT); + int64_t w_temp = (int64_t)pos_x * _mvp_fp.m[0][3] + (int64_t)pos_y * _mvp_fp.m[1][3] + + (int64_t)pos_z * _mvp_fp.m[2][3] + ((int64_t)_mvp_fp.m[3][3] << FP_SHIFT); + + x_temp >>= FP_SHIFT; + y_temp >>= FP_SHIFT; + z_temp >>= FP_SHIFT; + w_temp >>= FP_SHIFT; + + vertex->x = (x_temp > INT_MAX) ? INT_MAX : (x_temp < INT_MIN) ? INT_MIN : (int)x_temp; + vertex->y = (y_temp > INT_MAX) ? INT_MAX : (y_temp < INT_MIN) ? INT_MIN : (int)y_temp; + vertex->z = (z_temp > INT_MAX) ? INT_MAX : (z_temp < INT_MIN) ? INT_MIN : (int)z_temp; + vertex->w = (w_temp > INT_MAX) ? INT_MAX : (w_temp < INT_MIN) ? INT_MIN : (int)w_temp; + + return 1; +} + +static cc_bool ViewportVertex3D(VertexFixed* vertex) { + if (vertex->w == 0) return false; + if (ABS(vertex->w) < 64) return false; // Too small w + + int invW = FixedReciprocal(vertex->w); + + if (ABS(invW) > (FP_ONE << 10)) return false; // 1024x magnification limit + + int64_t x_ndc = ((int64_t)vertex->x * invW) >> FP_SHIFT; + int64_t y_ndc = ((int64_t)vertex->y * invW) >> FP_SHIFT; + int64_t z_ndc = ((int64_t)vertex->z * invW) >> FP_SHIFT; + + int64_t screen_x = vp_hwidth_fp + ((x_ndc * vp_hwidth_fp) >> FP_SHIFT); + int64_t screen_y = vp_hheight_fp - ((y_ndc * vp_hheight_fp) >> FP_SHIFT); + + // Clamp + if (screen_x < -(fb_width << FP_SHIFT) || screen_x > (fb_width << (FP_SHIFT + 1))) return false; + if (screen_y < -(fb_height << FP_SHIFT) || screen_y > (fb_height << (FP_SHIFT + 1))) return false; + + vertex->x = (int)screen_x; + vertex->y = (int)screen_y; + vertex->z = (z_ndc > INT_MAX) ? INT_MAX : (z_ndc < INT_MIN) ? INT_MIN : (int)z_ndc; + vertex->w = invW; + + vertex->u = FixedMul(vertex->u, invW); + vertex->v = FixedMul(vertex->v, invW); + + return true; +} + +static void DrawSprite2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + PackedCol vColor = V0->c; + int minX = FixedToInt(V0->x); + int minY = FixedToInt(V0->y); + int maxX = FixedToInt(V1->x); + int maxY = FixedToInt(V2->y); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + int begTX = FixedMul(V0->u, IntToFixed(curTexWidth)) >> FP_SHIFT; + int begTY = FixedMul(V0->v, IntToFixed(curTexHeight)) >> FP_SHIFT; + int delTX = (FixedMul(V1->u, IntToFixed(curTexWidth)) >> FP_SHIFT) - begTX; + int delTY = (FixedMul(V2->v, IntToFixed(curTexHeight)) >> FP_SHIFT) - begTY; + + int width = maxX - minX, height = maxY - minY; + + int fast = delTX == width && delTY == height && + (begTX + delTX < curTexWidth) && + (begTY + delTY < curTexHeight); + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int x, y; + for (y = minY; y <= maxY; y++) + { + int texY = fast ? (begTY + (y - minY)) : (((begTY + delTY * (y - minY) / height)) & texHeightMask); + for (x = minX; x <= maxX; x++) + { + int texX = fast ? (begTX + (x - minX)) : (((begTX + delTX * (x - minX) / width)) & texWidthMask); + int texIndex = texY * curTexWidth + texX; + + BitmapCol color = curTexPixels[texIndex]; + int R, G, B, A; + + A = BitmapCol_A(color); + if (gfx_alphaBlend && A == 0) continue; + int cb_index = y * cb_stride + x; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = BitmapCol_R(color); + G = BitmapCol_G(color); + B = BitmapCol_B(color); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + color = BitmapCol_Make(R, G, B, 0xFF); + } + + if (vColor != PACKEDCOL_WHITE) { + int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(color); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(vColor), g2 = BitmapCol_G(color); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(vColor), b2 = BitmapCol_B(color); + B = ( b1 * b2 ) >> 8; + + color = BitmapCol_Make(R, G, B, 0xFF); + } + + colorBuffer[cb_index] = color; + } + } +} + +#define edgeFunctionFixed(ax,ay, bx,by, cx,cy) \ + (FixedMul((bx) - (ax), (cy) - (ay)) - FixedMul((by) - (ay), (cx) - (ax))) + + +#define MultiplyColors(vColor, tColor) \ + a1 = PackedCol_A(vColor); \ + a2 = BitmapCol_A(tColor); \ + A = ( a1 * a2 ) >> 8; \ +\ + r1 = PackedCol_R(vColor); \ + r2 = BitmapCol_R(tColor); \ + R = ( r1 * r2 ) >> 8; \ +\ + g1 = PackedCol_G(vColor); \ + g2 = BitmapCol_G(tColor); \ + G = ( g1 * g2 ) >> 8; \ +\ + b1 = PackedCol_B(vColor); \ + b2 = BitmapCol_B(tColor); \ + B = ( b1 * b2 ) >> 8; \ + +/* +static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int area = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, x2_fp, y2_fp); + if (area == 0) return; + + int factor = FixedReciprocal(area); + + int w0 = V0->w, w1 = V1->w, w2 = V2->w; + if (w0 <= 0 && w1 <= 0 && w2 <= 0) return; + + int z0 = V0->z, z1 = V1->z, z2 = V2->z; + PackedCol color = V0->c; + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp, y1_fp, x2_fp, y2_fp, minX_fp, minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp, y2_fp, x0_fp, y0_fp, minX_fp, minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, minX_fp, minY_fp); + + + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; + + if (!texturing) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else if (texSinglePixel) { + int rawY0 = FixedDiv(v0, w0); + int rawY1 = FixedDiv(v1, w1); + int rawY = min(rawY0, rawY1); + int texY = (FixedToInt(rawY) + 1) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + texturing = false; + } + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + int ic0 = FixedMul(bc0, factor); + int ic1 = FixedMul(bc1, factor); + int ic2 = FixedMul(bc2, factor); + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + int db_index = y * db_stride + x; + + int w_interp = FixedMul(ic0, w0) + FixedMul(ic1, w1) + FixedMul(ic2, w2); + if (w_interp == 0) continue; + int w = FixedReciprocal(w_interp); + int z_interp = FixedMul(ic0, z0) + FixedMul(ic1, z1) + FixedMul(ic2, z2); + int z = FixedMul(z_interp, w); + + if (depthTest && (z < 0 || z > depthBuffer[db_index])) continue; + if (!colWrite) { + if (depthWrite) depthBuffer[db_index] = z; + continue; + } + + if (texturing) { + int u_interp = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int v_interp = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int u = FixedMul(u_interp, w); + int v = FixedMul(v_interp, w); + + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + + int texIndex = texY * curTexWidth + texX; + BitmapCol tColor = curTexPixels[texIndex]; + + MultiplyColors(color, tColor); + } + + if (gfx_alphaTest && A < 0x80) continue; + if (depthWrite) depthBuffer[db_index] = z; + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); + continue; + } + + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + int finR = (R * A + dstR * (255 - A)) >> 8; + int finG = (G * A + dstG * (255 - A)) >> 8; + int finB = (B * A + dstB * (255 - A)) >> 8; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } +} +*/ + +static inline void MultiplyColorsInline(PackedCol vColor, BitmapCol tColor, + int *outR, int *outG, int *outB, int *outA) { + int a1 = PackedCol_A(vColor); + int r1 = PackedCol_R(vColor); + int g1 = PackedCol_G(vColor); + int b1 = PackedCol_B(vColor); + + int a2 = BitmapCol_A(tColor); + int r2 = BitmapCol_R(tColor); + int g2 = BitmapCol_G(tColor); + int b2 = BitmapCol_B(tColor); + + *outA = (a1 * a2) >> 8; + *outR = (r1 * r2) >> 8; + *outG = (g1 * g2) >> 8; + *outB = (b1 * b2) >> 8; +} + +static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int area = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, x2_fp, y2_fp); + if (area == 0) return; + + int factor = FixedReciprocal(area); + + int w0 = V0->w, w1 = V1->w, w2 = V2->w; + if (w0 <= 0 && w1 <= 0 && w2 <= 0) return; + + int z0 = V0->z, z1 = V1->z, z2 = V2->z; + PackedCol color = V0->c; + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp, y1_fp, x2_fp, y2_fp, minX_fp, minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp, y2_fp, x0_fp, y0_fp, minX_fp, minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, minX_fp, minY_fp); + + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; + + if (!texturing) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else if (texSinglePixel) { + int rawY0 = FixedDiv(v0, w0); + int rawY1 = FixedDiv(v1, w1); + int rawY = min(rawY0, rawY1); + int texY = (FixedToInt(rawY) + 1) & texHeightMask; + MultiplyColorsInline(color, curTexPixels[texY * curTexWidth], &R, &G, &B, &A); + texturing = false; + } else { + a1 = PackedCol_A(color); + r1 = PackedCol_R(color); + g1 = PackedCol_G(color); + b1 = PackedCol_B(color); + } + + int step_ic0_per_x = FixedMul(dx12, factor); // bc0 += dx12 per x -> ic0 += step_ic0_per_x + int step_ic1_per_x = FixedMul(dx20, factor); // bc1 += dx20 + int step_ic2_per_x = FixedMul(dx01, factor); // bc2 += dx01 + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int ic0 = FixedMul(bc0_start, factor); + int ic1 = FixedMul(bc1_start, factor); + int ic2 = FixedMul(bc2_start, factor); + + int w_interp = FixedMul(ic0, w0) + FixedMul(ic1, w1) + FixedMul(ic2, w2); + int step_w = FixedMul(step_ic0_per_x, w0) + FixedMul(step_ic1_per_x, w1) + FixedMul(step_ic2_per_x, w2); + + int z_interp = FixedMul(ic0, z0) + FixedMul(ic1, z1) + FixedMul(ic2, z2); + int step_z = FixedMul(step_ic0_per_x, z0) + FixedMul(step_ic1_per_x, z1) + FixedMul(step_ic2_per_x, z2); + + int u_interp = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int step_u = FixedMul(step_ic0_per_x, u0) + FixedMul(step_ic1_per_x, u1) + FixedMul(step_ic2_per_x, u2); + + int v_interp = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int step_v = FixedMul(step_ic0_per_x, v0) + FixedMul(step_ic1_per_x, v1) + FixedMul(step_ic2_per_x, v2); + + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + if (ic0 < 0 || ic1 < 0 || ic2 < 0) { + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int db_index = y * db_stride + x; + + if (w_interp == 0) { + // update and skip + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int w = FixedReciprocal(w_interp); + int z = FixedMul(z_interp, w); + + if (depthTest && (z < 0 || z > depthBuffer[db_index])) { + // update and continue + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + if (!colWrite) { + if (depthWrite) depthBuffer[db_index] = z; + // update and continue + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int Rloc = R, Gloc = G, Bloc = B, Aloc = A; // local copy (non-texturing path keeps them) + + if (texturing) { + int u = FixedMul(u_interp, w); + int v = FixedMul(v_interp, w); + + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + + int texIndex = texY * curTexWidth + texX; + BitmapCol tColor = curTexPixels[texIndex]; + + int ta = BitmapCol_A(tColor); + int tr = BitmapCol_R(tColor); + int tg = BitmapCol_G(tColor); + int tb = BitmapCol_B(tColor); + + Aloc = (a1 * ta) >> 8; + Rloc = (r1 * tr) >> 8; + Gloc = (g1 * tg) >> 8; + Bloc = (b1 * tb) >> 8; + } + + if (gfx_alphaTest && Aloc < 0x80) { + // update and continue + if (depthWrite) ; // nothing + } else { + if (depthWrite) depthBuffer[db_index] = z; + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = BitmapCol_Make(Rloc, Gloc, Bloc, 0xFF); + } else { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + int finR = (Rloc * Aloc + dstR * (255 - Aloc)) >> 8; + int finG = (Gloc * Aloc + dstG * (255 - Aloc)) >> 8; + int finB = (Bloc * Aloc + dstB * (255 - Aloc)) >> 8; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } + + // update ic and interpolants + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + } // x + } // y +} + + +static void DrawTriangle2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + PackedCol color = V0->c; + + int area = edgeFunctionFixed(x0_fp,y0_fp, x1_fp,y1_fp, x2_fp,y2_fp); + if (area == 0) return; + int factor = FixedReciprocal(area); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp,y1_fp, x2_fp,y2_fp, minX_fp,minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp,y2_fp, x0_fp,y0_fp, minX_fp,minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp,y0_fp, x1_fp,y1_fp, minX_fp,minY_fp); + + int x, y; + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + int ic0 = FixedMul(bc0, factor); + int ic1 = FixedMul(bc1, factor); + int ic2 = FixedMul(bc2, factor); + + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + int cb_index = y * cb_stride + x; + + int R, G, B, A; + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + int u = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int v = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + int texIndex = texY * curTexWidth + texX; + + BitmapCol tColor = curTexPixels[texIndex]; + int a1 = PackedCol_A(color), a2 = BitmapCol_A(tColor); + A = ( a1 * a2 ) >> 8; + int r1 = PackedCol_R(color), r2 = BitmapCol_R(tColor); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(color), g2 = BitmapCol_G(tColor); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(color), b2 = BitmapCol_B(tColor); + B = ( b1 * b2 ) >> 8; + } else { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } + + if (gfx_alphaTest && A < 0x80) continue; + if (gfx_alphaBlend && A == 0) continue; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + } + + colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); + } + } +} + +static void ProcessClippedTriangleAndDraw(const VertexFixed* inVerts, int polyCount) { + if (polyCount < 3) return; + + for (int i = 1; i + 1 < polyCount; i++) { + VertexFixed A = inVerts[0]; + VertexFixed B = inVerts[i]; + VertexFixed C = inVerts[i + 1]; + + if (faceCulling) { + if (A.w > 0 && B.w > 0 && C.w > 0) { + int invA = FixedReciprocal(A.w); + int invB = FixedReciprocal(B.w); + int invC = FixedReciprocal(C.w); + + int ax = FixedMul(A.x, invA); + int ay = FixedMul(A.y, invA); + int bx = FixedMul(B.x, invB); + int by = FixedMul(B.y, invB); + int cx = FixedMul(C.x, invC); + int cy = FixedMul(C.y, invC); + + int area_ndc = edgeFunctionFixed(ax, ay, bx, by, cx, cy); + if (area_ndc < 0) continue; /* 裏向き → スキップ */ + } + } + + if (!ViewportVertex3D(&A) || !ViewportVertex3D(&B) || !ViewportVertex3D(&C)) { + continue; + } + + int minX = FixedToInt(min(A.x, min(B.x, C.x))); + int minY = FixedToInt(min(A.y, min(B.y, C.y))); + int maxX = FixedToInt(max(A.x, max(B.x, C.x))); + int maxY = FixedToInt(max(A.y, max(B.y, C.y))); + + if (maxX < 0 || minX > fb_maxX || maxY < 0 || minY > fb_maxY) { + continue; + } + + // too small + int area = edgeFunctionFixed(A.x, A.y, B.x, B.y, C.x, C.y); + if (ABS(area) <= FP_ONE) continue; + + DrawTriangle3D(&A, &B, &C); + } +} + +static cc_bool TriangleFullyInsideFrustum(const VertexFixed tri[3]) { + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + for (int p = 0; p < 6; p++) { + for (int i = 0; i < 3; i++) { + if (PlaneDistFixed(&tri[i], planes[p]) < 0) return false; + } + } + return true; +} + +static int ClipQuadToFrustumFixed(const VertexFixed quad[4], VertexFixed* outPoly) { + VertexFixed buf1[16], buf2[16]; + VertexFixed* src = buf1; + VertexFixed* dst = buf2; + + for (int i = 0; i < 4; i++) src[i] = quad[i]; + int count = 4; + + // check w zero + for (int i = 0; i < 4; i++) if (src[i].w == 0) return 0; + + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + + for (int p = 0; p < 6; p++) { + int newCount = ClipPolygonPlaneFixed(src, count, dst, planes[p]); + if (newCount == 0) return 0; + // swap + VertexFixed* tmp = src; src = dst; dst = tmp; + count = newCount; + if (count > 15) count = 15; + } + + for (int i = 0; i < count; i++) outPoly[i] = src[i]; + return count; +} +static cc_bool QuadFullyInsideFrustum(const VertexFixed quad[4]) { + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + for (int p = 0; p < 6; p++) { + for (int i = 0; i < 4; i++) { + if (PlaneDistFixed(&quad[i], planes[p]) < 0) return false; + } + } + return true; +} + +static void DrawClippedFixed(int mask, VertexFixed* v0, VertexFixed* v1, VertexFixed* v2, VertexFixed* v3) { + VertexFixed quad[4] = { *v0, *v1, *v2, *v3 }; + VertexFixed outPoly[16]; + int polyCount; + + if (QuadFullyInsideFrustum(quad)) { + ProcessClippedTriangleAndDraw(quad, 4); + return; + } + + polyCount = ClipQuadToFrustumFixed(quad, outPoly); + if (polyCount > 0) { + ProcessClippedTriangleAndDraw(outPoly, polyCount); + } +} + + +#define V0_VIS (1 << 0) +#define V1_VIS (1 << 1) +#define V2_VIS (1 << 2) +#define V3_VIS (1 << 3) +static void ClipLineFixed(const VertexFixed* v1, const VertexFixed* v2, VertexFixed* out, int d1, int d2) { + int denom = d1 - d2; + int t = denom == 0 ? FP_HALF : FixedDiv(d1, denom); + int invt = FP_ONE - t; + + out->x = FixedMul(invt, v1->x) + FixedMul(t, v2->x); + out->y = FixedMul(invt, v1->y) + FixedMul(t, v2->y); + out->z = FixedMul(invt, v1->z) + FixedMul(t, v2->z); + out->w = FixedMul(invt, v1->w) + FixedMul(t, v2->w); + out->u = FixedMul(invt, v1->u) + FixedMul(t, v2->u); + out->v = FixedMul(invt, v1->v) + FixedMul(t, v2->v); + out->c = v1->c; //TODO: 色補完する? + /* + // Color linear interpolation + int aA = PackedCol_A(a->c), aR = PackedCol_R(a->c), aG = PackedCol_G(a->c), aB = PackedCol_B(a->c); + int bA = PackedCol_A(b->c), bR = PackedCol_R(b->c), bG = PackedCol_G(b->c), bB = PackedCol_B(b->c); + + int Acol = ((int64_t)invt * aA + (int64_t)t * bA) >> FP_SHIFT; + int Rcol = ((int64_t)invt * aR + (int64_t)t * bR) >> FP_SHIFT; + int Gcol = ((int64_t)invt * aG + (int64_t)t * bG) >> FP_SHIFT; + int Bcol = ((int64_t)invt * aB + (int64_t)t * bB) >> FP_SHIFT; + + out->c = PACKEDCOL(Rcol, Gcol, Bcol, Acol); + */ +} + +void DrawQuadsFixed(int startVertex, int verticesCount, DrawHints hints) { + VertexFixed vertices[4]; + int i, j = startVertex; + + if (gfx_rendering2D && (hints & (DRAW_HINT_SPRITE|DRAW_HINT_RECT))) { + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + DrawSprite2D(&vertices[0], &vertices[1], &vertices[2]); + } + } else if (gfx_rendering2D) { + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + TransformVertex2D(j + 3, &vertices[3]); + DrawTriangle2D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); + } + } else { + if (tex_offseting) ShiftTextureCoords(verticesCount); + + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex3D(j + 0, &vertices[0]); + TransformVertex3D(j + 1, &vertices[1]); + TransformVertex3D(j + 2, &vertices[2]); + TransformVertex3D(j + 3, &vertices[3]); + + DrawClippedFixed(0x0F, &vertices[0], &vertices[1], &vertices[2], &vertices[3]); + } + + if (tex_offseting) UnshiftTextureCoords(verticesCount); + } +} +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { } /* TODO */ + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { + DrawQuadsFixed(startVertex, verticesCount, hints); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + DrawQuadsFixed(0, verticesCount, DRAW_HINT_NONE); +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawQuadsFixed(startVertex, verticesCount, DRAW_HINT_NONE); +} + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +static BitmapCol* CB_GetRow(struct Bitmap* bmp, int y, void* ctx) { + return colorBuffer + cb_stride * y; +} + +cc_result Gfx_TakeScreenshot(struct Stream* output) { + struct Bitmap bmp; + Bitmap_Init(bmp, fb_width, fb_height, NULL); + return Png_Encode(&bmp, output, CB_GetRow, false, NULL); +} + +cc_bool Gfx_WarnIfNecessary(void) { return false; } +cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } + +void Gfx_BeginFrame(void) { } + +void Gfx_EndFrame(void) { + Rect2D r = { 0, 0, fb_width, fb_height }; + Window_DrawFramebuffer(r, &fb_bmp); +} + +void Gfx_SetVSync(cc_bool vsync) { + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + if (depthBuffer) DestroyBuffers(); + + fb_width = Game.Width; + fb_height = Game.Height; + + Window_AllocFramebuffer(&fb_bmp, Game.Width, Game.Height); + colorBuffer = fb_bmp.scan0; + cb_stride = fb_bmp.width; + + depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); + db_stride = fb_width; + + Gfx_SetViewport(0, 0, Game.Width, Game.Height); + Gfx_SetScissor (0, 0, Game.Width, Game.Height); +} + +void Gfx_SetViewport(int x, int y, int w, int h) { + vp_hwidth_fp = FloatToFixed(w / 2.0f); + vp_hheight_fp = FloatToFixed(h / 2.0f); +} + +void Gfx_SetScissor (int x, int y, int w, int h) { + fb_maxX = x + w - 1; + fb_maxY = y + h - 1; +} + +void Gfx_GetApiInfo(cc_string* info) { + int pointerSize = sizeof(void*) * 8; + String_Format1(info, "-- Using software fixed-point (%i bit) --\n", &pointerSize); + PrintMaxTextureInfo(info); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index 54c3cc413..ad32d9596 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -23,7 +23,7 @@ static int db_stride; static void* gfx_vertices; static GfxResourceID white_square; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -33,20 +33,14 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } void Gfx_Create(void) { -#if defined CC_BUILD_32X || defined CC_BUILD_GBA - Gfx.MaxTexWidth = 16; - Gfx.MaxTexHeight = 16; -#else Gfx.MaxTexWidth = 4096; Gfx.MaxTexHeight = 4096; -#endif - Gfx.Created = true; Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; Gfx.Limitations = GFX_LIMIT_MINIMAL; @@ -166,10 +160,8 @@ static void ClearColorBuffer(void) { } static void ClearDepthBuffer(void) { -#ifndef SOFTGPU_DISABLE_ZBUFFER int i, size = fb_width * fb_height; for (i = 0; i < size; i++) depthBuffer[i] = 100000000.0f; -#endif } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -664,15 +656,11 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { float w = 1 / (ic0 * w0 + ic1 * w1 + ic2 * w2); float z = (ic0 * z0 + ic1 * z1 + ic2 * z2) * w; -#ifndef SOFTGPU_DISABLE_ZBUFFER if (depthTest && (z < 0 || z > depthBuffer[db_index])) continue; if (!colWrite) { if (depthWrite) depthBuffer[db_index] = z; continue; } -#else - if (!colWrite) continue; -#endif if (texturing) { float u = (ic0 * u0 + ic1 * u1 + ic2 * u2) * w; @@ -687,9 +675,7 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { } if (gfx_alphaTest && A < 0x80) continue; -#ifndef SOFTGPU_DISABLE_ZBUFFER if (depthWrite) depthBuffer[db_index] = z; -#endif int cb_index = y * cb_stride + x; if (!gfx_alphaBlend) { @@ -1084,10 +1070,8 @@ void Gfx_OnWindowResize(void) { colorBuffer = fb_bmp.scan0; cb_stride = fb_bmp.width; -#ifndef SOFTGPU_DISABLE_ZBUFFER depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); db_stride = fb_width; -#endif Gfx_SetViewport(0, 0, Game.Width, Game.Height); Gfx_SetScissor (0, 0, Game.Width, Game.Height); diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c new file mode 100644 index 000000000..2ceba1d57 --- /dev/null +++ b/src/Graphics_SoftMin.c @@ -0,0 +1,974 @@ +#include "Core.h" +#if CC_GFX_BACKEND == CC_GFX_BACKEND_SOFTMIN +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" + +static cc_bool faceCulling; +static int fb_width, fb_height; +static struct Bitmap fb_bmp; +static float vp_hwidth, vp_hheight; +static int fb_maxX, fb_maxY; + +static BitmapCol* colorBuffer; +static BitmapCol clearColor; +static cc_bool colWrite = true; +static int cb_stride; + +static void* gfx_vertices; +static GfxResourceID white_square; + +static void Gfx_RestoreState(void) { + InitDefaultResources(); + + // 1x1 dummy white texture + struct Bitmap bmp; + BitmapCol pixels[1] = { BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 1, 1, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +static void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + Gfx.MaxTexWidth = 256; + Gfx.MaxTexHeight = 256; + Gfx.Created = true; + Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; + Gfx.Limitations = GFX_LIMIT_MINIMAL | GFX_LIMIT_WORLD_ONLY; + + Gfx_RestoreState(); +} + +void Gfx_Free(void) { + Gfx_FreeState(); + Window_FreeFramebuffer(&fb_bmp); +} + + +typedef struct CCTexture { + int width, height; + BitmapCol pixels[]; +} CCTexture; + +static CCTexture* curTexture; +static BitmapCol* curTexPixels; +static int curTexWidth, curTexHeight; +static int texWidthMask, texHeightMask; + +void Gfx_BindTexture(GfxResourceID texId) { + if (!texId) texId = white_square; + CCTexture* tex = texId; + + curTexture = tex; + curTexPixels = tex->pixels; + curTexWidth = tex->width; + curTexHeight = tex->height; + + texWidthMask = (1 << Math_ilog2(tex->width)) - 1; + texHeightMask = (1 << Math_ilog2(tex->height)) - 1; +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { + GfxResourceID data = *texId; + if (data) Mem_Free(data); + *texId = NULL; +} + +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)Mem_Alloc(2 + bmp->width * bmp->height, 4, "Texture"); + + tex->width = bmp->width; + tex->height = bmp->height; + + CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, + bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, + bmp->width, bmp->height); + return tex; +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)texId; + BitmapCol* dst = (tex->pixels + x) + y * tex->width; + + CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, + part->scan0, rowWidth * BITMAPCOLOR_SIZE, + part->width, part->height); +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + faceCulling = enabled; +} + +static void SetAlphaTest(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaTest */ +} + +static void SetAlphaBlend(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaBlending */ +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +static void ClearColorBuffer(void) { + int i, x, y, size = fb_width * fb_height; + + if (cb_stride == fb_width) { + for (i = 0; i < size; i++) colorBuffer[i] = clearColor; + } else { + /* Slower partial buffer clear */ + for (y = 0; y < fb_height; y++) { + i = y * cb_stride; + for (x = 0; x < fb_width; x++) { + colorBuffer[i + x] = clearColor; + } + } + } +} + +void Gfx_ClearBuffers(GfxBuffers buffers) { + if (buffers & GFX_BUFFER_COLOR) ClearColorBuffer(); +} + +void Gfx_ClearColor(PackedCol color) { + int R = PackedCol_R(color); + int G = PackedCol_G(color); + int B = PackedCol_B(color); + int A = PackedCol_A(color); + + clearColor = BitmapCol_Make(R, G, B, A); +} + +void Gfx_SetDepthTest(cc_bool enabled) { +} + +void Gfx_SetDepthWrite(cc_bool enabled) { +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + colWrite = !depthOnly; +} + + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; +} + + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +static float texOffsetX, texOffsetY; +static struct Matrix _view, _proj, _mvp; + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) _view = *matrix; + if (type == MATRIX_PROJ) _proj = *matrix; + + Matrix_Mul(&_mvp, &_view, &_proj); +} + +void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { + _view = *view; + _proj = *proj; + + Matrix_Mul(mvp, view, proj); + _mvp = *mvp; +} + +void Gfx_EnableTextureOffset(float x, float y) { + texOffsetX = x; + texOffsetY = y; +} + +void Gfx_DisableTextureOffset(void) { + texOffsetX = 0; + texOffsetY = 0; +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ + /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.1f; + + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ +typedef struct Vector3 { float x, y, z; } Vector3; +typedef struct Vector2 { float x, y; } Vector2; +typedef struct Vertex_ { + float x, y, z, w; + float u, v; + PackedCol c; +} Vertex; + +static void TransformVertex2D(int index, Vertex* vertex) { + // TODO: avoid the multiply, just add down in DrawTriangles + char* ptr = (char*)gfx_vertices + index * gfx_stride; + Vector3* pos = (Vector3*)ptr; + vertex->x = pos->x; + vertex->y = pos->y; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v = (struct VertexColoured*)ptr; + vertex->u = 0.0f; + vertex->v = 0.0f; + vertex->c = v->Col; + } else { + struct VertexTextured* v = (struct VertexTextured*)ptr; + vertex->u = v->U; + vertex->v = v->V; + vertex->c = v->Col; + } +} + +static int TransformVertex3D(int index, Vertex* vertex) { + // TODO: avoid the multiply, just add down in DrawTriangles + char* ptr = (char*)gfx_vertices + index * gfx_stride; + Vector3* pos = (Vector3*)ptr; + + vertex->x = pos->x * _mvp.row1.x + pos->y * _mvp.row2.x + pos->z * _mvp.row3.x + _mvp.row4.x; + vertex->y = pos->x * _mvp.row1.y + pos->y * _mvp.row2.y + pos->z * _mvp.row3.y + _mvp.row4.y; + vertex->z = pos->x * _mvp.row1.z + pos->y * _mvp.row2.z + pos->z * _mvp.row3.z + _mvp.row4.z; + vertex->w = pos->x * _mvp.row1.w + pos->y * _mvp.row2.w + pos->z * _mvp.row3.w + _mvp.row4.w; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v = (struct VertexColoured*)ptr; + vertex->u = 0.0f; + vertex->v = 0.0f; + vertex->c = v->Col; + } else { + struct VertexTextured* v = (struct VertexTextured*)ptr; + vertex->u = (v->U + texOffsetX); + vertex->v = (v->V + texOffsetY); + vertex->c = v->Col; + } + return vertex->z >= 0.0f; +} + +static void ViewportVertex3D(Vertex* vertex) { + float invW = 1.0f / vertex->w; + + vertex->x = vp_hwidth * (1 + vertex->x * invW); + vertex->y = vp_hheight * (1 - vertex->y * invW); + vertex->z = vertex->z * invW; + vertex->w = invW; +} + +static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2) { + PackedCol vColor = V0->c; + int minX = (int)V0->x; + int minY = (int)V0->y; + int maxX = (int)V1->x; + int maxY = (int)V2->y; + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + int begTX = (int)(V0->u * curTexWidth); + int begTY = (int)(V0->v * curTexHeight); + int delTX = (int)(V1->u * curTexWidth) - begTX; + int delTY = (int)(V2->v * curTexHeight) - begTY; + + int width = maxX - minX, height = maxY - minY; + + int fast = delTX == width && delTY == height && + (begTX + delTX < curTexWidth ) && + (begTY + delTY < curTexHeight); + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int x, y; + for (y = minY; y <= maxY; y++) + { + int texY = fast ? (begTY + (y - minY)) : (((begTY + delTY * (y - minY) / height)) & texHeightMask); + for (x = minX; x <= maxX; x++) + { + int texX = fast ? (begTX + (x - minX)) : (((begTX + delTX * (x - minX) / width)) & texWidthMask); + int texIndex = texY * curTexWidth + texX; + + BitmapCol color = curTexPixels[texIndex]; + int R, G, B; + + if ((color & BITMAPCOLOR_A_MASK) == 0) continue; + int cb_index = y * cb_stride + x; + + if (vColor != PACKEDCOL_WHITE) { + int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(color); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(vColor), g2 = BitmapCol_G(color); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(vColor), b2 = BitmapCol_B(color); + B = ( b1 * b2 ) >> 8; + + color = BitmapCol_Make(R, G, B, 0xFF); + } + + colorBuffer[cb_index] = color; + } + } +} + +#define edgeFunction(ax,ay, bx,by, cx,cy) (((bx) - (ax)) * ((cy) - (ay)) - ((by) - (ay)) * ((cx) - (ax))) + +#define MultiplyColors(vColor, tColor) \ + a1 = PackedCol_A(vColor); \ + a2 = BitmapCol_A(tColor); \ + A = ( a1 * a2 ) >> 8; \ +\ + r1 = PackedCol_R(vColor); \ + r2 = BitmapCol_R(tColor); \ + R = ( r1 * r2 ) >> 8; \ +\ + g1 = PackedCol_G(vColor); \ + g2 = BitmapCol_G(tColor); \ + G = ( g1 * g2 ) >> 8; \ +\ + b1 = PackedCol_B(vColor); \ + b2 = BitmapCol_B(tColor); \ + B = ( b1 * b2 ) >> 8; \ + +static void DrawTriangle2D(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + // TODO still too slow, costs 300 ms/frame + float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); + float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); + float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + + PackedCol color = V0->c; + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else { + /* Always use a single pixel */ + float rawY0 = V0->v * curTexHeight; + float rawY1 = V1->v * curTexHeight; + + float rawY = min(rawY0, rawY1); + int texY = (int)(rawY + 0.01f) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + } + + if (A == 0) return; + color = BitmapCol_Make(R, G, B, 0xFF); + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + float bc0 = bc0_start; + float bc1 = bc1_start; + float bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + if (bc0 < 0 || bc1 < 0 || bc2 < 0) continue; + int cb_index = y * cb_stride + x; + + colorBuffer[cb_index] = color; + } + } +} + +static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + int area = edgeFunction(x0,y0, x1,y1, x2,y2); + if (faceCulling) { + // https://gamedev.stackexchange.com/questions/203694/how-to-make-backface-culling-work-correctly-in-both-orthographic-and-perspective + if (area < 0) return; + } + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + int bc0_start = edgeFunction(x1,y1, x2,y2, minX, minY); + int bc1_start = edgeFunction(x2,y2, x0,y0, minX, minY); + int bc2_start = edgeFunction(x0,y0, x1,y1, minX, minY); + + PackedCol color = V0->c; + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else { + /* Always use a single pixel */ + float rawY0 = V0->v * curTexHeight; + float rawY1 = V1->v * curTexHeight; + + float rawY = min(rawY0, rawY1); + int texY = (int)(rawY + 0.01f) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + } + + if (gfx_alphaTest && A == 0) return; + color = BitmapCol_Make(R, G, B, 0xFF); + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + if ((bc0 | bc1 | bc2) < 0) continue; + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = color; + continue; + } + + // Hardcode for alpha of 128 + BitmapCol dst = colorBuffer[cb_index]; + int finR = (R + BitmapCol_R(dst)) >> 1; + int finG = (G + BitmapCol_G(dst)) >> 1; + int finB = (B + BitmapCol_B(dst)) >> 1; + + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } +} + +#define V0_VIS (1 << 0) +#define V1_VIS (1 << 1) +#define V2_VIS (1 << 2) +#define V3_VIS (1 << 3) + +// https://github.com/behindthepixels/EDXRaster/blob/master/EDXRaster/Core/Clipper.h +static void ClipLine(Vertex* v1, Vertex* v2, Vertex* V) { + float t = Math_AbsF(v1->z / (v2->z - v1->z)); + float invt = 1.0f - t; + + V->x = invt * v1->x + t * v2->x; + V->y = invt * v1->y + t * v2->y; + //V->z = invt * v1->z + t * v2->z; + V->z = 0.0f; // clipped against near plane anyways (I.e Z/W = 0 --> Z = 0) + V->w = invt * v1->w + t * v2->w; + + V->u = invt * v1->u + t * v2->u; + V->v = invt * v1->v + t * v2->v; + V->c = v1->c; +} + +// https://casual-effects.com/research/McGuire2011Clipping/clip.glsl +static void DrawClipped(int mask, Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) { + Vertex tmp[2]; + Vertex* a = &tmp[0]; + Vertex* b = &tmp[1]; + + switch (mask) { + case V0_VIS: + { + // v0 + // / | + // / | + // .....A....B... + // / | + // v3--v2---v1 + ClipLine(v3, v0, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v0); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v0, a, b); + } + break; + case V1_VIS: + { + // v1 + // / | + // / | + // ....A.....B... + // / | + // v0--v3---v2 + ClipLine(v0, v1, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v1); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, b, v1); + } break; + case V2_VIS: + { + // v2 + // / | + // / | + // ....A.....B... + // / | + // v1--v0---v3 + ClipLine(v1, v2, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, b, v2); + } break; + case V3_VIS: + { + // v3 + // / | + // / | + // ....A.....B... + // / | + // v2--v1---v0 + ClipLine(v2, v3, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(b, v3, a); + } + break; + case V0_VIS | V1_VIS: + { + // v0-----------v1 + // \ | + // ...B.........A... + // \ | + // v3-----v2 + ClipLine(v1, v2, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, v0, a); + DrawTriangle3D(a, v0, b); + } break; + // case V0_VIS | V2_VIS: degenerate case that should never happen + case V0_VIS | V3_VIS: + { + // v3-----------v0 + // \ | + // ...B.........A... + // \ | + // v2-----v1 + ClipLine(v0, v1, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, v0, b); + DrawTriangle3D(b, v0, v3); + } break; + case V1_VIS | V2_VIS: + { + // v1-----------v2 + // \ | + // ...B.........A... + // \ | + // v0-----v3 + ClipLine(v2, v3, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, b, v2); + DrawTriangle3D(v2, b, a); + } break; + // case V1_VIS | V3_VIS: degenerate case that should never happen + case V2_VIS | V3_VIS: + { + // v2-----------v3 + // \ | + // ...B.........A... + // \ | + // v1-----v0 + ClipLine(v3, v0, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D( b, a, v2); + DrawTriangle3D(v2, a, v3); + } break; + case V0_VIS | V1_VIS | V2_VIS: + { + // --v1-- + // v0-- --v2 + // \ / + // ....B.....A... + // \ / + // v3 + // v1,v2,v0 v2,v0,A v0,A,B + ClipLine(v2, v3, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, v0, v2); + DrawTriangle3D(v2, v0, a); + DrawTriangle3D(v0, b, a); + } break; + case V0_VIS | V1_VIS | V3_VIS: + { + // --v0-- + // v3-- --v1 + // \ / + // ....B.....A... + // \ / + // v2 + // v0,v1,v3 v1,v3,A v3,A,B + ClipLine(v1, v2, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v0, v3, v1); + DrawTriangle3D(v1, v3, a); + DrawTriangle3D(v3, b, a); + } break; + case V0_VIS | V2_VIS | V3_VIS: + { + // --v3-- + // v2-- --v0 + // \ / + // ....B.....A... + // \ / + // v1 + // v3,v0,v2 v0,v2,A v2,A,B + ClipLine(v0, v1, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v3, v2, v0); + DrawTriangle3D(v0, v2, a); + DrawTriangle3D(v2, b, a); + } break; + case V1_VIS | V2_VIS | V3_VIS: + { + // --v2-- + // v1-- --v3 + // \ / + // ....B.....A... + // \ / + // v0 + // v2,v3,v1 v3,v1,A v1,A,B + ClipLine(v3, v0, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v2, v1, v3); + DrawTriangle3D(v3, v1, a); + DrawTriangle3D(v1, b, a); + } break; + } +} + +void DrawQuads(int startVertex, int verticesCount, DrawHints hints) { + Vertex vertices[4]; + int i, j = startVertex; + + if (gfx_rendering2D && (hints & (DRAW_HINT_SPRITE|DRAW_HINT_RECT))) { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + + DrawSprite2D(&vertices[0], &vertices[1], &vertices[2]); + } + } else if (gfx_rendering2D) { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + TransformVertex2D(j + 3, &vertices[3]); + + DrawTriangle2D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); + } + } else if (colWrite) { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + int clip = TransformVertex3D(j + 0, &vertices[0]) << 0 + | TransformVertex3D(j + 1, &vertices[1]) << 1 + | TransformVertex3D(j + 2, &vertices[2]) << 2 + | TransformVertex3D(j + 3, &vertices[3]) << 3; + + if (clip == 0) { + // Quad entirely clipped + } else if (clip == 0x0F) { + // Quad entirely visible + ViewportVertex3D(&vertices[0]); + ViewportVertex3D(&vertices[1]); + ViewportVertex3D(&vertices[2]); + ViewportVertex3D(&vertices[3]); + + DrawTriangle3D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle3D(&vertices[2], &vertices[0], &vertices[3]); + } else { + // Quad partially visible + DrawClipped(clip, &vertices[0], &vertices[1], &vertices[2], &vertices[3]); + } + } + } +} + +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { } /* TODO */ + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { + DrawQuads(startVertex, verticesCount, hints); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + DrawQuads(0, verticesCount, DRAW_HINT_NONE); +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawQuads(startVertex, verticesCount, DRAW_HINT_NONE); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +static BitmapCol* CB_GetRow(struct Bitmap* bmp, int y, void* ctx) { + return colorBuffer + cb_stride * y; +} + +cc_result Gfx_TakeScreenshot(struct Stream* output) { + struct Bitmap bmp; + Bitmap_Init(bmp, fb_width, fb_height, NULL); + return Png_Encode(&bmp, output, CB_GetRow, false, NULL); +} + +cc_bool Gfx_WarnIfNecessary(void) { return false; } +cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } + +void Gfx_BeginFrame(void) { } + +void Gfx_EndFrame(void) { + Rect2D r = { 0, 0, fb_width, fb_height }; + Window_DrawFramebuffer(r, &fb_bmp); +} + +void Gfx_SetVSync(cc_bool vsync) { + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + // TODO ?????? + //Window_FreeFramebuffer(&fb_bmp); + + fb_width = Game.Width; + fb_height = Game.Height; + + Window_AllocFramebuffer(&fb_bmp, Game.Width, Game.Height); + colorBuffer = fb_bmp.scan0; + cb_stride = fb_bmp.width; + + Gfx_SetViewport(0, 0, Game.Width, Game.Height); + Gfx_SetScissor (0, 0, Game.Width, Game.Height); +} + +void Gfx_SetViewport(int x, int y, int w, int h) { + vp_hwidth = w / 2.0f; + vp_hheight = h / 2.0f; +} + +void Gfx_SetScissor (int x, int y, int w, int h) { + /* TODO minX/Y */ + fb_maxX = x + w - 1; + fb_maxY = y + h - 1; +} + +void Gfx_GetApiInfo(cc_string* info) { + String_AppendConst(info, "-- Using software --\n"); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif diff --git a/src/HeldBlockRenderer.c b/src/HeldBlockRenderer.c index 4b5dcdf70..2f433340c 100644 --- a/src/HeldBlockRenderer.c +++ b/src/HeldBlockRenderer.c @@ -88,7 +88,7 @@ static void ResetHeldState(void) { held_entity.SkinType = p->SkinType; held_entity.TextureId = p->TextureId; - held_entity.MobTextureId = p->MobTextureId; + held_entity.NonHumanSkin = p->NonHumanSkin; held_entity.uScale = p->uScale; held_entity.vScale = p->vScale; } diff --git a/src/Http_Worker.c b/src/Http_Worker.c index c3f6ec549..9f843cdaa 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -1,131 +1,55 @@ #include "Core.h" -#ifndef CC_BUILD_WEB + +#if defined CC_BUILD_WEB +/* Implemented in web http backend without C worker thread(s) */ +#elif !defined CC_BUILD_NETWORKING +#include "Http.h" +#include "Game.h" + +void HttpRequest_Free(struct HttpRequest* request) { } + +cc_bool Http_GetResult(int reqID, struct HttpRequest* item) { + return false; +} + +cc_bool Http_GetCurrent(int* reqID, int* progress) { + return false; +} + +int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) { + return -1; +} +int Http_AsyncGetData(const cc_string* url, cc_uint8 flags) { + return -1; +} +int Http_AsyncGetHeaders(const cc_string* url, cc_uint8 flags) { + return -1; +} +int Http_AsyncPostData(const cc_string* url, cc_uint8 flags, const void* data, cc_uint32 size, struct StringsBuffer* cookies) { + return -1; +} +int Http_AsyncGetDataEx(const cc_string* url, cc_uint8 flags, const cc_string* lastModified, const cc_string* etag, struct StringsBuffer* cookies) { + return -1; +} + +int Http_CheckProgress(int reqID) { return -1; } + +void Http_LogError(const char* action, const struct HttpRequest* item) { } + +void Http_TryCancel(int reqID) { } + +void Http_UrlEncodeUtf8(cc_string* dst, const cc_string* src) { } + +void Http_ClearPending(void) { } + +static void Http_NullInit(void) { } + +struct IGameComponent Http_Component = { + Http_NullInit +}; +#else #include "_HttpBase.h" -/* Ensures data buffer has enough space left to append amount bytes */ -static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) { - cc_uint32 newSize = req->size + amount; - cc_uint8* ptr; - if (newSize <= req->_capacity) return true; - - if (!req->_capacity) { - /* Allocate initial storage */ - req->_capacity = req->contentLength ? req->contentLength : 1; - req->_capacity = max(req->_capacity, newSize); - - ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1); - } else { - /* Reallocate if capacity reached */ - req->_capacity = newSize; - ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1); - } - - if (!ptr) return false; - req->data = ptr; - return true; -} - -/* Increases size and updates current progress */ -static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) { - req->size += read; - if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength); -} - - -/*########################################################################################################################* -*---------------------------------------------------Common backend code---------------------------------------------------* -*#########################################################################################################################*/ -static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) { - cc_string name, data; - int dataEnd; - String_UNSAFE_Separate(value, '=', &name, &data); - /* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */ - /* However only the __cfduid=xyz part of the cookie should be stored */ - dataEnd = String_IndexOf(&data, ';'); - if (dataEnd >= 0) data.length = dataEnd; - - EntryList_Set(req->cookies, &name, &data, '='); -} - -static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) { - int contentLen = 0; - Convert_ParseInt(value, &contentLen); - - if (contentLen <= 0) return; - req->contentLength = contentLen; -} - -/* Parses a HTTP header */ -static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { - static const cc_string httpVersion = String_FromConst("HTTP"); - cc_string name, value, parts[3]; - int numParts; - - /* HTTP[version] [status code] [status reason] */ - if (String_CaselessStarts(line, &httpVersion)) { - numParts = String_UNSAFE_Split(line, ' ', parts, 3); - if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode); - } - /* For all other headers: name: value */ - if (!String_UNSAFE_Separate(line, ':', &name, &value)) return; - - if (String_CaselessEqualsConst(&name, "ETag")) { - String_CopyToRawArray(req->etag, &value); - } else if (String_CaselessEqualsConst(&name, "Content-Length")) { - Http_ParseContentLength(req, &value); - } else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) { - /* dropbox stopped returning Content-Length header since switching to chunked transfer */ - /* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */ - Http_ParseContentLength(req, &value); - } else if (String_CaselessEqualsConst(&name, "Last-Modified")) { - String_CopyToRawArray(req->lastModified, &value); - } else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) { - Http_ParseCookie(req, &value); - } -} - -/* Adds a http header to the request headers. */ -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value); - -/* Adds all the appropriate headers for a request. */ -static void Http_SetRequestHeaders(struct HttpRequest* req) { - static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded"); - cc_string str, cookies; char cookiesBuffer[1024]; - int i; - - if (req->lastModified[0]) { - str = String_FromRawArray(req->lastModified); - Http_AddHeader(req, "If-Modified-Since", &str); - } - if (req->etag[0]) { - str = String_FromRawArray(req->etag); - Http_AddHeader(req, "If-None-Match", &str); - } - - if (req->data) Http_AddHeader(req, "Content-Type", &contentType); - if (!req->cookies || !req->cookies->count) return; - - String_InitArray(cookies, cookiesBuffer); - for (i = 0; i < req->cookies->count; i++) { - if (i) String_AppendConst(&cookies, "; "); - str = StringsBuffer_UNSAFE_Get(req->cookies, i); - String_AppendString(&cookies, &str); - } - Http_AddHeader(req, "Cookie", &cookies); -} - -/* TODO: Rewrite to use a local variable instead */ -static cc_string* Http_GetUserAgent_UNSAFE(void) { - static char userAgentBuffer[STRING_SIZE]; - static cc_string userAgent; - - String_InitArray(userAgent, userAgentBuffer); - String_AppendConst(&userAgent, GAME_APP_NAME); - String_AppendConst(&userAgent, Platform_AppNameSuffix); - return &userAgent; -} - - #if CC_NET_BACKEND == CC_NET_BACKEND_BUILTIN #include "Errors.h" #include "PackedCol.h" @@ -737,146 +661,6 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) { static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { return SSLBackend_DescribeError(res, dst); } -#elif defined CC_BUILD_ANDROID -/*########################################################################################################################* -*-----------------------------------------------------Android backend-----------------------------------------------------* -*#########################################################################################################################*/ -struct HttpRequest* java_req; -static jmethodID JAVA_httpInit, JAVA_httpSetHeader, JAVA_httpPerform, JAVA_httpSetData; -static jmethodID JAVA_httpDescribeError; - -static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { - char buffer[NATIVE_STR_LEN]; - cc_string err; - JNIEnv* env; - jvalue args[1]; - jobject obj; - - JavaGetCurrentEnv(env); - args[0].i = res; - obj = JavaSCall_Obj(env, JAVA_httpDescribeError, args); - if (!obj) return false; - - err = JavaGetString(env, obj, buffer); - String_AppendString(dst, &err); - (*env)->DeleteLocalRef(env, obj); - return true; -} - -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) { - JNIEnv* env; - jvalue args[2]; - - JavaGetCurrentEnv(env); - args[0].l = JavaMakeConst(env, key); - args[1].l = JavaMakeString(env, value); - - JavaSCall_Void(env, JAVA_httpSetHeader, args); - (*env)->DeleteLocalRef(env, args[0].l); - (*env)->DeleteLocalRef(env, args[1].l); -} - -/* Processes a HTTP header downloaded from the server */ -static void JNICALL java_HttpParseHeader(JNIEnv* env, jobject o, jstring header) { - char buffer[NATIVE_STR_LEN]; - cc_string line = JavaGetString(env, header, buffer); - Http_ParseHeader(java_req, &line); -} - -/* Processes a chunk of data downloaded from the web server */ -static void JNICALL java_HttpAppendData(JNIEnv* env, jobject o, jbyteArray arr, jint len) { - struct HttpRequest* req = java_req; - int ok = Http_BufferExpand(req, len); - if (!ok) Process_Abort("Out of memory for HTTP request"); - - (*env)->GetByteArrayRegion(env, arr, 0, len, (jbyte*)(&req->data[req->size])); - Http_BufferExpanded(req, len); -} - -static const JNINativeMethod methods[] = { - { "httpParseHeader", "(Ljava/lang/String;)V", java_HttpParseHeader }, - { "httpAppendData", "([BI)V", java_HttpAppendData } -}; -static void CacheMethodRefs(JNIEnv* env) { - JAVA_httpInit = JavaGetSMethod(env, "httpInit", "(Ljava/lang/String;Ljava/lang/String;)I"); - JAVA_httpSetHeader = JavaGetSMethod(env, "httpSetHeader", "(Ljava/lang/String;Ljava/lang/String;)V"); - JAVA_httpPerform = JavaGetSMethod(env, "httpPerform", "()I"); - JAVA_httpSetData = JavaGetSMethod(env, "httpSetData", "([B)I"); - - JAVA_httpDescribeError = JavaGetSMethod(env, "httpDescribeError", "(I)Ljava/lang/String;"); -} - -static void HttpBackend_Init(void) { - JNIEnv* env; - JavaGetCurrentEnv(env); - JavaRegisterNatives(env, methods); - CacheMethodRefs(env); -} - -static cc_result Http_InitReq(JNIEnv* env, struct HttpRequest* req, cc_string* url) { - static const char* verbs[3] = { "GET", "HEAD", "POST" }; - jvalue args[2]; - jint res; - - args[0].l = JavaMakeString(env, url); - args[1].l = JavaMakeConst(env, verbs[req->requestType]); - - res = JavaSCall_Int(env, JAVA_httpInit, args); - (*env)->DeleteLocalRef(env, args[0].l); - (*env)->DeleteLocalRef(env, args[1].l); - return res; -} - -static cc_result Http_SetData(JNIEnv* env, struct HttpRequest* req) { - jvalue args[1]; - jint res; - - args[0].l = JavaMakeBytes(env, req->data, req->size); - res = JavaSCall_Int(env, JAVA_httpSetData, args); - (*env)->DeleteLocalRef(env, args[0].l); - return res; -} - -static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) { - JNIEnv* env; - jint res; - - JavaGetCurrentEnv(env); - if ((res = Http_InitReq(env, req, url))) return res; - java_req = req; - - Http_SetRequestHeaders(req); - Http_AddHeader(req, "User-Agent", Http_GetUserAgent_UNSAFE()); - - if (req->data) { - if ((res = Http_SetData(env, req))) return res; - HttpRequest_Free(req); - } - - req->_capacity = 0; - req->progress = HTTP_PROGRESS_FETCHING_DATA; - res = JavaSCall_Int(env, JAVA_httpPerform, NULL); - req->progress = 100; - return res; -} -#elif !defined CC_BUILD_NETWORKING -/*########################################################################################################################* -*------------------------------------------------------Null backend-------------------------------------------------------* -*#########################################################################################################################*/ -#include "Errors.h" - -static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { - return false; -} - -static void HttpBackend_Init(void) { } - -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) { } - -static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) { - req->progress = 100; - return ERR_NOT_SUPPORTED; -} #endif diff --git a/src/Input.c b/src/Input.c index 6c9da0736..7f9e16a1b 100644 --- a/src/Input.c +++ b/src/Input.c @@ -327,7 +327,7 @@ struct InputDevice TouchDevice = { struct Pointer Pointers[INPUT_MAX_POINTERS]; struct _PointerHooks PointerHooks; -void Pointer_SetPressed(int idx, cc_bool pressed) { +static void Pointer_SetPressed(int idx, cc_bool pressed) { if (pressed) { if (PointerHooks.DownHook && PointerHooks.DownHook(idx)) return; diff --git a/src/LScreens.c b/src/LScreens.c index d3dd37041..2862c2996 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -1084,9 +1084,9 @@ static void CheckResourcesScreen_Activated(struct LScreen* s_) { } static void CheckResourcesScreen_ResetArea(struct Context2D* ctx, int x, int y, int width, int height) { - int R = BitmapCol_R(Launcher_Theme.BackgroundColor) * 0.78f; /* 153 -> 120 */ - int G = BitmapCol_G(Launcher_Theme.BackgroundColor) * 0.70f; /* 127 -> 89 */ - int B = BitmapCol_B(Launcher_Theme.BackgroundColor) * 0.88f; /* 172 -> 151 */ + float R = BitmapCol_R(Launcher_Theme.BackgroundColor) * 0.78f; /* 153 -> 120 */ + float G = BitmapCol_G(Launcher_Theme.BackgroundColor) * 0.70f; /* 127 -> 89 */ + float B = BitmapCol_B(Launcher_Theme.BackgroundColor) * 0.88f; /* 172 -> 151 */ Gradient_Noise(ctx, BitmapColor_RGB(R, G, B), 4, x, y, width, height); } diff --git a/src/LWeb.c b/src/LWeb.c index e5d600a3f..4101bf4f6 100644 --- a/src/LWeb.c +++ b/src/LWeb.c @@ -99,8 +99,7 @@ static void Json_ConsumeString(struct JsonContext* ctx, cc_string* str) { codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3]; /* don't want control characters in names/software */ - /* TODO: Convert to CP437.. */ - if (codepoint >= 32) String_Append(str, codepoint); + if (codepoint >= 32) String_Append(str, Convert_CodepointToCP437(codepoint)); JsonContext_Consume(ctx, 4); } diff --git a/src/Logger.c b/src/Logger.c index c1ffd251a..b614179b5 100644 --- a/src/Logger.c +++ b/src/Logger.c @@ -280,6 +280,12 @@ static void DumpFrame(cc_string* trace, void* addr) { cc_uintptr addr_ = (cc_uintptr)addr; String_Format1(trace, "%x", &addr_); } +#elif defined CC_BUILD_HPUX +/* HP-UX doesn't expose a nice interface for dladdr */ +static void DumpFrame(cc_string* trace, void* addr) { + cc_uintptr addr_ = (cc_uintptr)addr; + String_Format1(trace, "%x", &addr_); +} #elif defined CC_BUILD_POSIX && !defined CC_BUILD_OS2 /* need to define __USE_GNU for dladdr */ #ifndef __USE_GNU @@ -455,6 +461,11 @@ void Logger_Backtrace(cc_string* trace, void* ctx) { String_AppendConst(trace, "-- backtrace unimplemented --"); /* There is no dladdr on Symbian */ } +#elif defined CC_BUILD_HPUX +/* HP-UX doesn't have unwind support */ +void Logger_Backtrace(cc_string* trace, void* ctx) { + String_AppendConst(trace, "-- backtrace unimplemented --"); +} #elif defined CC_BUILD_POSIX /* musl etc - rely on unwind from GCC instead */ #define CC_BACKTRACE_UNWIND diff --git a/src/Menus.c b/src/Menus.c index b867470d0..6f6b1f728 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -196,6 +196,11 @@ static int Menu_PadAxis(void* screen, struct PadAxisUpdate* upd) { } } +static void AddPrimaryButton(void* screen, struct ButtonWidget* btn, Widget_LeftClick click) { + int width = Game_ClassicMode ? 400 : (Window_Main.Width < 300 ? 200 : 400); + ButtonWidget_Add(screen, btn, width, click); +} + /*########################################################################################################################* *------------------------------------------------------Menu utilities-----------------------------------------------------* @@ -508,7 +513,7 @@ static void PauseScreenBase_ContextRecreated(struct PauseScreen* s, struct FontD static void PauseScreenBase_AddWidgets(struct PauseScreen* s, int width) { TextWidget_Add(s, &s->title); Menu_AddButtons(s, s->btns, width, s->descs, s->descsCount); - ButtonWidget_Add(s, &s->back, 400, PauseScreenBase_Game); + AddPrimaryButton(s, &s->back, PauseScreenBase_Game); } @@ -741,7 +746,7 @@ static void OptionsGroupScreen_Init(void* screen) { Menu_AddButtons(s, s->btns, 300, optsGroup_btns, 8); TextWidget_Add(s, &s->desc); - ButtonWidget_Add(s, &s->done, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->done, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1016,7 +1021,7 @@ static void EditHotkeyScreen_Init(void* screen) { } else { text = String_Empty; } TextInputWidget_Add(s, &s->input, 500, &text, &desc); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchHotkeys); + AddPrimaryButton(s, &s->cancel, Menu_SwitchHotkeys); s->input.onscreenPlaceholder = "Hotkey text"; s->maxVertices = Screen_CalcDefaultMaxVertices(s); @@ -1227,7 +1232,7 @@ static void GenLevelScreen_Init(void* screen) { TextWidget_Add(s, &s->title); ButtonWidget_Add(s, &s->flatgrass, 200, GenLevelScreen_Flatgrass); ButtonWidget_Add(s, &s->vanilla, 200, GenLevelScreen_Notchy); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1307,7 +1312,7 @@ static void ClassicGenScreen_Init(void* screen) { ButtonWidget_Add(s, &s->btns[0], 400, ClassicGenScreen_Small); ButtonWidget_Add(s, &s->btns[1], 400, ClassicGenScreen_Medium); ButtonWidget_Add(s, &s->btns[2], 400, ClassicGenScreen_Huge); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1544,7 +1549,7 @@ static void SaveLevelScreen_Init(void* screen) { ButtonWidget_Add(s, &s->save, 400, SaveLevelScreen_Save); ButtonWidget_Add(s, &s->file, 400, SaveLevelScreen_File); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); TextInputWidget_Add(s, &s->input, 400, &World.Name, &desc); Menu_SelectWidget((struct Screen*)s, 3); /* s->input */ @@ -1927,7 +1932,7 @@ static void BindsSourceScreen_Init(void* screen) { ButtonWidget_Add(s, &s->btns[0], 300, BindsSourceScreen_ModeNormal); ButtonWidget_Add(s, &s->btns[1], 300, BindsSourceScreen_ModeGamepad); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -2108,7 +2113,7 @@ static void KeyBindsScreen_Init(void* screen) { TextWidget_Add(s, &s->title); TextWidget_Add(s, &s->msg); - ButtonWidget_Add(s, &s->back, 400, Gui.ClassicMenu ? Menu_SwitchClassicOptions : Menu_SwitchOptions); + AddPrimaryButton(s, &s->back, Gui.ClassicMenu ? Menu_SwitchClassicOptions : Menu_SwitchOptions); if (s->leftPage || s->rightPage) { ButtonWidget_Add(s, &s->left, 40, s->leftPage); diff --git a/src/Model.c b/src/Model.c index 908b1d446..33d480380 100644 --- a/src/Model.c +++ b/src/Model.c @@ -114,12 +114,12 @@ void Model_Render(struct Model* model, struct Entity* e) { } void Model_SetupState(struct Model* model, struct Entity* e) { - PackedCol col; + PackedCol color; float yawDelta; model->index = 0; - col = e->VTABLE->GetCol(e); - Models.Cols[0] = col; + color = e->VTABLE->GetCol(e); + Models.Cols[0] = color; /* If a model forgets to call Model_ApplyTexture but still tries to draw, */ /* then it is not using the model API properly. */ @@ -129,11 +129,13 @@ void Model_SetupState(struct Model* model, struct Entity* e) { Models.vScale = 100.0f; if (!e->NoShade) { - Models.Cols[1] = PackedCol_Scale(col, PACKEDCOL_SHADE_YMIN); - Models.Cols[2] = PackedCol_Scale(col, PACKEDCOL_SHADE_Z); - Models.Cols[4] = PackedCol_Scale(col, PACKEDCOL_SHADE_X); + Models.Cols[1] = PackedCol_Scale(color, PACKEDCOL_SHADE_YMIN); + Models.Cols[2] = PackedCol_Scale(color, PACKEDCOL_SHADE_Z); + Models.Cols[4] = PackedCol_Scale(color, PACKEDCOL_SHADE_X); } else { - Models.Cols[1] = col; Models.Cols[2] = col; Models.Cols[4] = col; + Models.Cols[1] = color; + Models.Cols[2] = color; + Models.Cols[4] = color; } Models.Cols[3] = Models.Cols[2]; @@ -151,7 +153,7 @@ void Model_ApplyTexture(struct Entity* e) { GfxResourceID tex; cc_bool _64x64; - tex = model->usesHumanSkin ? e->TextureId : e->MobTextureId; + tex = (model->usesHumanSkin || e->NonHumanSkin) ? e->TextureId : 0; if (tex) { Models.skinType = e->SkinType; } else { @@ -212,14 +214,17 @@ void Model_DrawPart(struct ModelPart* part) { struct ModelVertex v; int i, count = part->count; + float uScale = Models.uScale; + float vScale = Models.vScale; - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) + { v = *src; dst->x = v.x; dst->y = v.y; dst->z = v.z; dst->Col = Models.Cols[i >> 2]; - dst->U = (v.u & UV_POS_MASK) * Models.uScale - (v.u >> UV_MAX_SHIFT) * 0.01f * Models.uScale; - dst->V = (v.v & UV_POS_MASK) * Models.vScale - (v.v >> UV_MAX_SHIFT) * 0.01f * Models.vScale; + dst->U = (v.u & UV_POS_MASK) * uScale - (v.u >> UV_MAX_SHIFT) * 0.01f * uScale; + dst->V = (v.v & UV_POS_MASK) * vScale - (v.v >> UV_MAX_SHIFT) * 0.01f * vScale; src++; dst++; } model->index += count; @@ -1446,7 +1451,7 @@ static void ChickenModel_MakeParts(void) { } static void ChickenModel_Draw(struct Entity* e) { - PackedCol col = Models.Cols[0]; + PackedCol color = Models.Cols[0]; int i; Model_ApplyTexture(e); Model_LockVB(e, CHICKEN_MAX_VERTICES); @@ -1461,7 +1466,7 @@ static void ChickenModel_Draw(struct Entity* e) { for (i = 0; i < FACE_COUNT; i++) { - Models.Cols[i] = PackedCol_Scale(col, 0.7f); + Models.Cols[i] = PackedCol_Scale(color, 0.7f); } Model_DrawRotate(e->Anim.LeftLegX, 0, 0, &chicken_leftLeg, false); @@ -2088,13 +2093,13 @@ static TextureLoc BlockModel_GetTex(Face face) { static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { struct VertexTextured* ptr, v; - PackedCol col; int tmp; + PackedCol color; int tmp; float xz1, xz2; TextureLoc loc = BlockModel_GetTex(FACE_ZMAX); TextureRec rec = Atlas1D_TexRec(loc, 1, &tmp); - col = Models.Cols[0]; - Block_Tint(col, bModel_block); + color = Models.Cols[0]; + Block_Tint(color, bModel_block); xz1 = 0.0f; xz2 = 0.0f; if (firstPart) { /* Need to break into two quads for when drawing a sprite model in hand. */ @@ -2106,7 +2111,7 @@ static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { } ptr = bModel_vertices; - v.Col = col; + v.Col = color; v.x = xz1; v.y = 0.0f; v.z = xz1; v.U = rec.u2; v.V = rec.v2; *ptr++ = v; v.y = 1.0f; v.V = rec.v1; *ptr++ = v; @@ -2118,13 +2123,13 @@ static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { static void BlockModel_SpriteXQuad(cc_bool firstPart, cc_bool mirror) { struct VertexTextured* ptr, v; - PackedCol col; int tmp; + PackedCol color; int tmp; float x1, x2, z1, z2; TextureLoc loc = BlockModel_GetTex(FACE_XMAX); TextureRec rec = Atlas1D_TexRec(loc, 1, &tmp); - col = Models.Cols[0]; - Block_Tint(col, bModel_block); + color = Models.Cols[0]; + Block_Tint(color, bModel_block); x1 = 0.0f; x2 = 0.0f; z1 = 0.0f; z2 = 0.0f; if (firstPart) { @@ -2136,7 +2141,7 @@ static void BlockModel_SpriteXQuad(cc_bool firstPart, cc_bool mirror) { } ptr = bModel_vertices; - v.Col = col; + v.Col = color; v.x = x1; v.y = 0.0f; v.z = z1; v.U = rec.u2; v.V = rec.v2; *ptr++ = v; v.y = 1.0f; v.V = rec.v1; *ptr++ = v; diff --git a/src/PackedCol.h b/src/PackedCol.h index 7d8eb2da8..0646e3916 100644 --- a/src/PackedCol.h +++ b/src/PackedCol.h @@ -8,7 +8,7 @@ CC_BEGIN_HEADER */ typedef cc_uint32 PackedCol; -#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST +#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST || defined CC_BUILD_XBOX360 #define PACKEDCOL_B_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 #define PACKEDCOL_R_SHIFT 16 diff --git a/src/Platform.h b/src/Platform.h index 6074e6421..da435ad89 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -8,7 +8,7 @@ Abstracts platform specific memory management, I/O, etc Copyright 2014-2025 ClassiCube | Licensed under BSD-3 */ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX #define _NL "\r\n" #define NATIVE_STR_LEN 300 #else @@ -20,7 +20,7 @@ Copyright 2014-2025 ClassiCube | Licensed under BSD-3 extern const char* Platform_AppNameSuffix; void* TempMem_Alloc(int size); -#if defined CC_BUILD_WIN +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE typedef struct cc_winstring_ { cc_unichar uni[NATIVE_STR_LEN]; /* String represented using UTF16 format */ char ansi[NATIVE_STR_LEN]; /* String lossily represented using ANSI format */ @@ -30,7 +30,7 @@ typedef struct cc_winstring_ { void Platform_EncodeString(cc_winstring* dst, const cc_string* src); #endif -#ifdef CC_BUILD_WIN +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE typedef cc_winstring cc_filepath; #else typedef struct cc_filepath_ { char buffer[NATIVE_STR_LEN]; } cc_filepath; @@ -245,7 +245,7 @@ int Stopwatch_ElapsedMS(cc_uint64 beg, cc_uint64 end); /*########################################################################################################################* *---------------------------------------------------------File I/O--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX typedef void* cc_file; #else typedef int cc_file; @@ -346,7 +346,7 @@ void Platform_LoadSysFonts(void); /*########################################################################################################################* *----------------------------------------------------------Sockets--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX typedef cc_uintptr cc_socket; #else typedef int cc_socket; diff --git a/src/Platform_MacClassic.c b/src/Platform_MacClassic.c index 8c1b2f3c7..03187ae90 100644 --- a/src/Platform_MacClassic.c +++ b/src/Platform_MacClassic.c @@ -1,5 +1,9 @@ #include "Core.h" #if defined CC_BUILD_MACCLASSIC +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "_PlatformBase.h" #include "Stream.h" @@ -362,91 +366,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Delay(delay, &final); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; - // TODO -} - -void Thread_Detach(void* handle) { - // TODO -} - -void Thread_Join(void* handle) { - // TODO -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { - // TODO -} - -void Mutex_Lock(void* handle) { - // TODO -} - -void Mutex_Unlock(void* handle) { - // TODO -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { - // TODO -} - -void Waitable_Signal(void* handle) { - // TODO -} - -void Waitable_Wait(void* handle) { - // TODO -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { - // TODO -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { - -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* @@ -491,49 +410,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dylib"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/Platform_N64.c b/src/Platform_N64.c index 6a676d79c..8457b2b3e 100644 --- a/src/Platform_N64.c +++ b/src/Platform_N64.c @@ -1,5 +1,9 @@ #include "Core.h" #if defined CC_BUILD_N64 +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #define CC_XTEA_ENCRYPTION #include "_PlatformBase.h" @@ -101,6 +105,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, &path_); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1 ? errno : 0; } @@ -197,79 +203,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { wait_ms(milliseconds); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { } - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* @@ -324,6 +257,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -334,4 +269,8 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} #endif diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 1f5c0dfa9..b07d14b8e 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -800,9 +800,16 @@ cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { if (*s == -1) return errno; if (nonblocking) { +#ifdef CC_BUILD_HPUX + int flags = fcntl(*s, F_GETFL, 0); + if (flags == -1) return errno; + int err = fcntl(*s, F_SETFL, flags | O_NONBLOCK); + if (err == -1) return errno; +#else int blocking_raw = -1; /* non-blocking mode */ int err = ioctl(*s, FIONBIO, &blocking_raw); if (err == -1) return errno; +#endif } return 0; } diff --git a/src/Platform_Symbian.cpp b/src/Platform_Symbian.cpp index b43805e10..0648022fb 100644 --- a/src/Platform_Symbian.cpp +++ b/src/Platform_Symbian.cpp @@ -51,7 +51,7 @@ const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; const cc_result ReturnCode_SocketDropped = EPIPE; #define SUPPORTS_GETADDRINFO 1 -const char* Platform_AppNameSuffix = ""; +const char* Platform_AppNameSuffix = " Symbian"; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; cc_bool Platform_ReadonlyFilesystem; diff --git a/src/Platform_WinCE.c b/src/Platform_WinCE.c new file mode 100644 index 000000000..93c290e6b --- /dev/null +++ b/src/Platform_WinCE.c @@ -0,0 +1,781 @@ +#include "Core.h" +#if defined CC_BUILD_WINCE + +#include "_PlatformBase.h" +#include "Stream.h" +#include "SystemFonts.h" +#include "Funcs.h" +#include "Utils.h" +#include "Errors.h" + +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#ifndef UNICODE +#define UNICODE +#define _UNICODE +#endif +#include +#include +#include +#include +#include + +static HANDLE heap; +const cc_result ReturnCode_FileShareViolation = ERROR_SHARING_VIOLATION; +const cc_result ReturnCode_FileNotFound = ERROR_FILE_NOT_FOUND; +const cc_result ReturnCode_DirectoryExists = ERROR_ALREADY_EXISTS; +const cc_result ReturnCode_SocketInProgess = WSAEINPROGRESS; +const cc_result ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK; +const cc_result ReturnCode_SocketDropped = WSAECONNRESET; + +const char* Platform_AppNameSuffix = " CE"; +cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; + +// Current directory management for Windows CE +static WCHAR current_directory[MAX_PATH] = L"\\"; +static cc_string Platform_NextArg(STRING_REF cc_string* args); + +static CRITICAL_SECTION dir_lock; +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "main_impl.h" + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { + cc_result res; + SetupProgram(0, NULL); + + do { + res = RunProgram(0, NULL); + } while (Platform_IsSingleProcess() && Window_Main.Exists); + + Window_Free(); + ExitProcess(res); + return res; +} + +/*########################################################################################################################* +*---------------------------------------------------------Memory----------------------------------------------------------* +*#########################################################################################################################*/ + + +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + +void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapAlloc(heap, 0, size) : NULL; +} + +void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapAlloc(heap, HEAP_ZERO_MEMORY, size) : NULL; +} + +void* Mem_TryRealloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapReAlloc(heap, 0, mem, size) : NULL; +} + +void Mem_Free(void* mem) { + if (mem) HeapFree(heap, 0, mem); +} + +/*########################################################################################################################* +*------------------------------------------------------Logging/Time-------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_Log(const char* msg, int len) { + WCHAR wbuf[2048]; + int wlen = MultiByteToWideChar(CP_UTF8, 0, msg, len, wbuf, 2047); + if (wlen > 0) { + wbuf[wlen] = 0; + OutputDebugStringW(wbuf); + OutputDebugStringW(L"\n"); + } +} + +#define FILETIME_EPOCH 50491123200ULL +#define FileTime_TotalSecs(time) ((time / 10000000) + FILETIME_EPOCH) + +TimeMS DateTime_CurrentUTC(void) { + SYSTEMTIME st; + FILETIME ft; + cc_uint64 raw; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + raw = ft.dwLowDateTime | ((cc_uint64)ft.dwHighDateTime << 32); + return FileTime_TotalSecs(raw); +} + +void DateTime_CurrentLocal(struct cc_datetime* t) { + SYSTEMTIME localTime; + GetLocalTime(&localTime); + + t->year = localTime.wYear; + t->month = localTime.wMonth; + t->day = localTime.wDay; + t->hour = localTime.wHour; + t->minute = localTime.wMinute; + t->second = localTime.wSecond; +} + +cc_uint64 Stopwatch_Measure(void) { + return GetTickCount(); +} + +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + return (end - beg) * 1000; // GetTickCount returns milliseconds +} + +/*########################################################################################################################* +*-------------------------------------------------------Crash handling----------------------------------------------------* +*#########################################################################################################################*/ +void CrashHandler_Install(void) { + // SetUnhandledExceptionFilter not available on Windows CE +} + +void Process_Abort2(cc_result result, const char* raw_msg) { + WCHAR wbuf[512]; + WCHAR fbuf[512]; + int wlen = MultiByteToWideChar(CP_UTF8, 0, raw_msg, -1, wbuf, 511); + if (wlen > 0) { + swprintf(fbuf, L"Error %s: 0x%04x", result, wbuf); + MessageBoxW(NULL, fbuf, L"Error", MB_OK | MB_ICONERROR); + } + ExitProcess(result); +} + +/*########################################################################################################################* +*-----------------------------------------------Current Directory Management---------------------------------------------* +*#########################################################################################################################*/ + +static void NormalizePath(WCHAR* path) { + WCHAR* src = path; + WCHAR* dst = path; + WCHAR* component_start; + + while (*src) { + if (*src == L'/' || *src == L'\\') { + *dst++ = L'\\'; + src++; + while (*src == L'/' || *src == L'\\') src++; + continue; + } + + component_start = dst; + while (*src && *src != L'/' && *src != L'\\') { + *dst++ = *src++; + } + + if (dst - component_start == 1 && component_start[0] == L'.') { + dst = component_start; + if (dst > path && dst[-1] == L'\\') dst--; + } else if (dst - component_start == 2 && component_start[0] == L'.' && component_start[1] == L'.') { + dst = component_start; + if (dst > path && dst[-1] == L'\\') dst--; + while (dst > path && dst[-1] != L'\\') dst--; + if (dst > path) dst--; + } + } + + if (dst == path) { + *dst++ = L'\\'; + } + *dst = L'\0'; +} + +static void SetCurrentDirectoryImpl(const WCHAR* path) { + EnterCriticalSection(&dir_lock); + + if (path[0] == L'\\') { + wcscpy(current_directory, path); + } else { + wcscat(current_directory, L"\\"); + wcscat(current_directory, path); + } + + NormalizePath(current_directory); + LeaveCriticalSection(&dir_lock); +} + +static void GetCurrentDirectoryImpl(WCHAR* buffer, DWORD size) { + EnterCriticalSection(&dir_lock); + wcsncpy(buffer, current_directory, size - 1); + buffer[size - 1] = L'\0'; + LeaveCriticalSection(&dir_lock); +} + +static void MakeAbsolutePath(const WCHAR* relative_path, WCHAR* absolute_path, DWORD size) { + if (relative_path[0] == L'\\') { + wcsncpy(absolute_path, relative_path, size - 1); + } else { + GetCurrentDirectoryImpl(absolute_path, size); + if (wcslen(absolute_path) + wcslen(relative_path) + 2 < size) { + wcscat(absolute_path, L"\\"); + wcscat(absolute_path, relative_path); + } + } + absolute_path[size - 1] = L'\0'; + NormalizePath(absolute_path); +} +/*########################################################################################################################* +*-----------------------------------------------------Directory/File------------------------------------------------------* +*#########################################################################################################################*/ +void Directory_GetCachePath(cc_string* path) { + String_AppendConst(path, "\\cache"); +} + +void Platform_EncodePath(cc_filepath* dst, const cc_string* src) { + Platform_EncodeString(dst, src); +} + +cc_result Directory_Create(const cc_filepath* path) { + WCHAR fullPath[MAX_PATH]; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + return CreateDirectoryW(fullPath, NULL) ? 0 : GetLastError(); +} + +int File_Exists(const cc_filepath* path) { + WCHAR fullPath[MAX_PATH]; + DWORD attribs; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + + attribs = GetFileAttributesW(fullPath); + return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY); +} + +static cc_result Directory_EnumCore(const cc_string* dirPath, const cc_string* file, DWORD attribs, + void* obj, Directory_EnumCallback callback) { + cc_string path; char pathBuffer[MAX_PATH + 10]; + int is_dir; + + if (file->length == 1 && file->buffer[0] == '.') return 0; + if (file->length == 2 && file->buffer[0] == '.' && file->buffer[1] == '.') return 0; + + String_InitArray(path, pathBuffer); + String_Format2(&path, "%s/%s", dirPath, file); + + is_dir = attribs & FILE_ATTRIBUTE_DIRECTORY; + callback(&path, obj, is_dir); + return 0; +} + +cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { + cc_string path; char pathBuffer[MAX_PATH + 10]; + WIN32_FIND_DATAW eW; + cc_filepath str; + HANDLE find; + cc_result res; + int i; + + String_InitArray(path, pathBuffer); + String_Format1(&path, "%s\\*", dirPath); + Platform_EncodePath(&str, &path); + + find = FindFirstFileW(str.uni, &eW); + if (find == INVALID_HANDLE_VALUE) return GetLastError(); + + do { + path.length = 0; + for (i = 0; i < MAX_PATH && eW.cFileName[i]; i++) { + // Convert wide char to UTF-8 + char utf8[4]; + int len = WideCharToMultiByte(CP_UTF8, 0, &eW.cFileName[i], 1, utf8, 4, NULL, NULL); + for (int j = 0; j < len; j++) { + String_Append(&path, utf8[j]); + } + } + if ((res = Directory_EnumCore(dirPath, &path, eW.dwFileAttributes, obj, callback))) return res; + } while (FindNextFileW(find, &eW)); + + res = GetLastError(); + FindClose(find); + return res == ERROR_NO_MORE_FILES ? 0 : res; +} + +static cc_result DoFile(cc_file* file, const cc_filepath* path, DWORD access, DWORD createMode) { + WCHAR fullPath[MAX_PATH]; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + *file = CreateFileW(fullPath, access, FILE_SHARE_READ, NULL, createMode, 0, NULL); + return *file != INVALID_HANDLE_VALUE ? 0 : GetLastError(); +} + +cc_result File_Open(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_READ, OPEN_EXISTING); +} + +cc_result File_Create(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_WRITE | GENERIC_READ, CREATE_ALWAYS); +} + +cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS); +} + +cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { + BOOL success = ReadFile(file, data, count, (DWORD*)bytesRead, NULL); + return success ? 0 : GetLastError(); +} + +cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) { + BOOL success = WriteFile(file, data, count, (DWORD*)bytesWrote, NULL); + return success ? 0 : GetLastError(); +} + +cc_result File_Close(cc_file file) { + return CloseHandle(file) ? 0 : GetLastError(); +} + +cc_result File_Seek(cc_file file, int offset, int seekType) { + static cc_uint8 modes[] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; + DWORD pos = SetFilePointer(file, offset, NULL, modes[seekType]); + return pos != INVALID_SET_FILE_POINTER ? 0 : GetLastError(); +} + +cc_result File_Position(cc_file file, cc_uint32* pos) { + *pos = SetFilePointer(file, 0, NULL, FILE_CURRENT); + return *pos != INVALID_SET_FILE_POINTER ? 0 : GetLastError(); +} + +cc_result File_Length(cc_file file, cc_uint32* len) { + *len = GetFileSize(file, NULL); + return *len != INVALID_FILE_SIZE ? 0 : GetLastError(); +} + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +void Thread_Sleep(cc_uint32 milliseconds) { + Sleep(milliseconds); +} + +static DWORD WINAPI ExecThread(void* param) { + Thread_StartFunc func = (Thread_StartFunc)param; + func(); + return 0; +} + +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + DWORD threadID; + HANDLE thread = CreateThread(NULL, stackSize, ExecThread, (void*)func, 0, &threadID); + if (!thread) Process_Abort2(GetLastError(), "Creating thread"); + *handle = thread; +} + +void Thread_Detach(void* handle) { + if (!CloseHandle((HANDLE)handle)) { + Process_Abort2(GetLastError(), "Freeing thread handle"); + } +} + +void Thread_Join(void* handle) { + WaitForSingleObject((HANDLE)handle, INFINITE); + Thread_Detach(handle); +} + +void* Mutex_Create(const char* name) { + CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex"); + InitializeCriticalSection(ptr); + return ptr; +} + +void Mutex_Free(void* handle) { + DeleteCriticalSection((CRITICAL_SECTION*)handle); + Mem_Free(handle); +} + +void Mutex_Lock(void* handle) { + EnterCriticalSection((CRITICAL_SECTION*)handle); +} + +void Mutex_Unlock(void* handle) { + LeaveCriticalSection((CRITICAL_SECTION*)handle); +} + +void* Waitable_Create(const char* name) { + void* handle = CreateEventW(NULL, false, false, NULL); + if (!handle) { + Process_Abort2(GetLastError(), "Creating waitable"); + } + return handle; +} + +void Waitable_Free(void* handle) { + if (!CloseHandle((HANDLE)handle)) { + Process_Abort2(GetLastError(), "Freeing waitable"); + } +} + +void Waitable_Signal(void* handle) { + SetEvent((HANDLE)handle); +} + +void Waitable_Wait(void* handle) { + WaitForSingleObject((HANDLE)handle, INFINITE); +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { + WaitForSingleObject((HANDLE)handle, milliseconds); +} + +/*########################################################################################################################* +*--------------------------------------------------------Font/Text--------------------------------------------------------* +*#########################################################################################################################*/ +static void FontDirCallback(const cc_string* path, void* obj, int isDirectory) { + if (isDirectory) { + Directory_Enum(path, NULL, FontDirCallback); + } else { + SysFonts_Register(path, NULL); + } +} + +void Platform_LoadSysFonts(void) { + cc_string fontDir = String_FromConst("\\Windows\\Fonts"); + Directory_Enum(&fontDir, NULL, FontDirCallback); +} + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +static char sockaddr_size_check[sizeof(SOCKADDR_STORAGE) < CC_SOCKETADDR_MAXSIZE ? 1 : -1]; + +static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst->data; + cc_uint32 ip_addr; + if (!ParseIPv4Address(ip, &ip_addr)) return false; + + addr4->sin_addr.S_un.S_addr = ip_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + + dst->size = sizeof(*addr4); + return true; +} + +static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) { + return false; +} + +static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { + struct hostent* res = gethostbyname(host); + SOCKADDR_IN* addr4; + char* src_addr; + int i; + + if (!res) { + cc_result wsa_res = WSAGetLastError(); + if (wsa_res == WSAHOST_NOT_FOUND) return SOCK_ERR_UNKNOWN_HOST; + return ERR_INVALID_ARGUMENT; + } + + if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT; + if (!res->h_addr_list) return ERR_INVALID_ARGUMENT; + + for (i = 0; i < SOCKET_MAX_ADDRS; i++) { + src_addr = res->h_addr_list[i]; + if (!src_addr) break; + addrs[i].size = sizeof(SOCKADDR_IN); + + addr4 = (SOCKADDR_IN*)addrs[i].data; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + addr4->sin_addr = *(IN_ADDR*)src_addr; + } + + *numValidAddrs = i; + return i == 0 ? ERR_INVALID_ARGUMENT : 0; +} +cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + SOCKADDR* raw_addr = (SOCKADDR*)addr->data; + *s = socket(raw_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); + if (*s == INVALID_SOCKET) return WSAGetLastError(); + + if (nonblocking) { + u_long blockingMode = 1; + ioctlsocket(*s, FIONBIO, &blockingMode); + } + return 0; +} + +cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { + SOCKADDR* raw_addr = (SOCKADDR*)addr->data; + int res = connect(s, raw_addr, addr->size); + return res == SOCKET_ERROR ? WSAGetLastError() : 0; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + int recvCount = recv(s, (char*)data, count, 0); + if (recvCount != SOCKET_ERROR) { *modified = recvCount; return 0; } + *modified = 0; return WSAGetLastError(); +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + int sentCount = send(s, (const char*)data, count, 0); + if (sentCount != SOCKET_ERROR) { *modified = sentCount; return 0; } + *modified = 0; return WSAGetLastError(); +} + +void Socket_Close(cc_socket s) { + shutdown(s, SD_BOTH); + closesocket(s); +} + +static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { + fd_set set; + struct timeval time = { 0 }; + int selectCount; + + FD_ZERO(&set); + FD_SET(s, &set); + + if (mode == SOCKET_POLL_READ) { + selectCount = select(0, &set, NULL, NULL, &time); + } else { + selectCount = select(0, NULL, &set, NULL, &time); + } + + if (selectCount == SOCKET_ERROR) { *success = false; return WSAGetLastError(); } + *success = FD_ISSET(s, &set) != 0; return 0; +} + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return Socket_Poll(s, SOCKET_POLL_READ, readable); +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + int resultSize = sizeof(cc_result); + cc_result res = Socket_Poll(s, SOCKET_POLL_WRITE, writable); + if (res || *writable) return res; + + getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&res, &resultSize); + return res; +} + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Process_OpenSupported = false; + +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return SetGameArgs(args, numArgs); +} + +void Process_Exit(cc_result code) { + ExitProcess(code); +} + +cc_result Process_StartOpen(const cc_string* args) { + return ERR_NOT_SUPPORTED; +} + +/*########################################################################################################################* +*--------------------------------------------------------Updater----------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Updater_Supported = false; +const struct UpdaterInfo Updater_Info = { "&eUpdate not supported on Windows CE", 0 }; + +cc_bool Updater_Clean(void) { return true; } +cc_result Updater_Start(const char** action) { return ERR_NOT_SUPPORTED; } +cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } +cc_result Updater_MarkExecutable(void) { return 0; } +cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-------------------------------------------------------Dynamic lib-------------------------------------------------------* +*#########################################################################################################################*/ +const cc_string DynamicLib_Ext = String_FromConst(".dll"); +static cc_result dynamicErr; + +void* DynamicLib_Load2(const cc_string* path) { + cc_filepath str; + void* lib; + + Platform_EncodePath(&str, path); + lib = LoadLibraryW(str.uni); + if (!lib) dynamicErr = GetLastError(); + return lib; +} + +void* DynamicLib_Get2(void* lib, const char* name) { + WCHAR wname[256]; + MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, 256); + + void* addr = GetProcAddressW((HMODULE)lib, wname); + if (!addr) dynamicErr = GetLastError(); + return addr; +} + +cc_bool DynamicLib_DescribeError(cc_string* dst) { + cc_result res = dynamicErr; + dynamicErr = 0; + Platform_DescribeError(res, dst); + String_Format1(dst, " (error %e)", &res); + return true; +} + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_EncodeString(cc_winstring* dst, const cc_string* src) { + int i; + + MultiByteToWideChar(CP_UTF8, 0, src->buffer, src->length, dst->uni, NATIVE_STR_LEN - 1); + dst->uni[src->length] = 0; + + WideCharToMultiByte(CP_ACP, 0, dst->uni, -1, dst->ansi, NATIVE_STR_LEN - 1, NULL, NULL); +} + +void Platform_Init(void) { + WSADATA wsaData; + cc_result res; + + heap = GetProcessHeap(); + + res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (res) Logger_SysWarn(res, "starting WSA"); +} + +void Platform_Free(void) { + WSACleanup(); +} + +cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { + WCHAR chars[NATIVE_STR_LEN]; + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + + res = FormatMessageW(flags, NULL, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + chars, NATIVE_STR_LEN, NULL); + if (!res) return false; + + String_AppendUtf16(dst, chars, res * 2); + return true; +} + +/*########################################################################################################################* +*-------------------------------------------------------Encryption--------------------------------------------------------* +*#########################################################################################################################*/ +static const cc_uint8 xor_key[] = { 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x9A }; + +cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { + const cc_uint8* bytes = (const cc_uint8*)data; + int i; + + for (i = 0; i < len; i++) { + String_Append(dst, bytes[i] ^ xor_key[i % 8]); + } + return 0; +} + +cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { + const cc_uint8* bytes = (const cc_uint8*)data; + int i; + + for (i = 0; i < len; i++) { + String_Append(dst, bytes[i] ^ xor_key[i % 8]); + } + return 0; +} + +cc_result Platform_GetEntropy(void* data, int len) { + // Simple random generator + static cc_uint32 seed = 1; + cc_uint8* bytes = (cc_uint8*)data; + int i; + + if (seed == 1) { + seed = GetTickCount(); + } + + for (i = 0; i < len; i++) { + seed = seed * 1103515245 + 12345; + bytes[i] = (cc_uint8)(seed >> 8); + } + return 0; +} + +/*########################################################################################################################* +*-----------------------------------------------------Configuration-------------------------------------------------------* +*#########################################################################################################################*/ +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + LPWSTR cmdLine = GetCommandLineW(); + char cmdLineUtf8[1024]; + cc_string cmdArgs; + int i; + + if (gameHasArgs) return GetGameArgs(args); + + WideCharToMultiByte(CP_UTF8, 0, cmdLine, -1, cmdLineUtf8, 1024, NULL, NULL); + cmdArgs = String_FromReadonly(cmdLineUtf8); + + Platform_NextArg(&cmdArgs); + + for (i = 0; i < GAME_MAX_CMDARGS; i++) { + args[i] = Platform_NextArg(&cmdArgs); + if (!args[i].length) break; + } + return i; +} + +static cc_string Platform_NextArg(STRING_REF cc_string* args) { + cc_string arg; + int end; + + // Remove leading spaces + while (args->length && args->buffer[0] == ' ') { + *args = String_UNSAFE_SubstringAt(args, 1); + } + + if (args->length && args->buffer[0] == '"') { + // Quoted argument + *args = String_UNSAFE_SubstringAt(args, 1); + end = String_IndexOf(args, '"'); + } else { + end = String_IndexOf(args, ' '); + } + + if (end == -1) { + arg = *args; + args->length = 0; + } else { + arg = String_UNSAFE_Substring(args, 0, end); + *args = String_UNSAFE_SubstringAt(args, end + 1); + } + return arg; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char** argv) { + WCHAR module_path[MAX_PATH]; + WCHAR* last_slash; + DWORD len; + + len = GetModuleFileNameW(NULL, module_path, MAX_PATH); + if (len == 0) { + SetCurrentDirectoryImpl(L"\\"); + return 0; + } + + last_slash = wcsrchr(module_path, L'\\'); + if (last_slash) { + *last_slash = L'\0'; + SetCurrentDirectoryImpl(module_path); + } else { + SetCurrentDirectoryImpl(L"\\"); + } + + return 0; +} + + +#endif diff --git a/src/Protocol.c b/src/Protocol.c index 51d1b1495..0d1e73810 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -80,7 +80,7 @@ static struct CpeExt bulkBlockUpdate_Ext = { "BulkBlockUpdate", 1 }, textColors_Ext = { "TextColors", 1 }, envMapAspect_Ext = { "EnvMapAspect", 2 }, - entityProperty_Ext = { "EntityProperty", 1 }, + entityProperty_Ext = { "EntityProperty", 2 }, extEntityPos_Ext = { "ExtEntityPositions", 1 }, twoWayPing_Ext = { "TwoWayPing", 1 }, invOrder_Ext = { "InventoryOrder", 1 }, @@ -1428,6 +1428,12 @@ static void CPE_SetEntityProperty(cc_uint8* data) { Entity_UpdateModelBounds(e); return; + case 6: + scale = value / 1000.0f; + if (scale < -1024.0f) scale = -1024.0f; + if (scale > 1024.0f) scale = 1024.0f; + e->PushStrength = scale; + return; default: return; } diff --git a/src/SSL.c b/src/SSL.c index 12bc3222a..fbb40e514 100644 --- a/src/SSL.c +++ b/src/SSL.c @@ -58,10 +58,8 @@ static unsigned x509_maybe_skip_verify(unsigned r) { if (r != BR_ERR_X509_EXPIRED) return r; cc_uint64 cur = DateTime_CurrentUTC(); - uint32_t days = (uint32_t)(cur / 86400) + 366; - - /* Time earlier than August 2024 usually mean an improperly calibrated RTC */ - if (days < 739464) return 0; + /* Time earlier than 19 Sep 2025 usually mean an improperly calibrated RTC */ + if (cur < 63893864669ull) return 0; #endif return r; diff --git a/src/Screens.c b/src/Screens.c index 3bdc48bb2..10dfd844a 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -1955,7 +1955,7 @@ static void LoadingScreen_Render(void* screen, float delta) { if (s->rows) { loc = Block_Tex(BLOCK_DIRT, FACE_YMAX); Atlas1D_Bind(Atlas1D_Index(loc)); - Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, 0); + Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, DRAW_HINT_SPRITE); offset = s->rows * 4; } diff --git a/src/Server.c b/src/Server.c index f6fea3c60..c554b5a41 100644 --- a/src/Server.c +++ b/src/Server.c @@ -132,7 +132,7 @@ static void SPConnection_BeginConnect(void) { Random_SeedFromCurrentTime(&rnd); World_NewMap(); -#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_MACCLASSIC || defined CC_BUILD_32X || defined CC_BUILD_GBA +#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_MACCLASSIC || defined CC_BUILD_TINYMEM horSize = 16; verSize = 16; #elif defined CC_BUILD_LOWMEM @@ -144,7 +144,7 @@ static void SPConnection_BeginConnect(void) { #endif World_SetDimensions(horSize, verSize, horSize); -#if defined CC_BUILD_N64 || defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_32X || defined CC_BUILD_GBA +#if defined CC_BUILD_N64 || defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_TINYMEM Gen_Active = &FlatgrassGen; #else Gen_Active = &NotchyGen; diff --git a/src/Stream.c b/src/Stream.c index b298cb17e..6ce8ef4bf 100644 --- a/src/Stream.c +++ b/src/Stream.c @@ -209,10 +209,13 @@ static cc_result Stream_PortionSkip(struct Stream* s, cc_uint32 count) { } static cc_result Stream_PortionPosition(struct Stream* s, cc_uint32* position) { - *position = s->meta.portion.length - s->meta.portion.left; return 0; + *position = s->meta.portion.length - s->meta.portion.left; + return 0; } + static cc_result Stream_PortionLength(struct Stream* s, cc_uint32* length) { - *length = s->meta.portion.length; return 0; + *length = s->meta.portion.length; + return 0; } void Stream_ReadonlyPortion(struct Stream* s, struct Stream* source, cc_uint32 len) { diff --git a/src/SystemFonts.c b/src/SystemFonts.c index 83eba18d1..10a8303f3 100644 --- a/src/SystemFonts.c +++ b/src/SystemFonts.c @@ -405,7 +405,6 @@ void cc_qsort(void* v, size_t count, size_t size, } - static FT_Library ft_lib; static struct FT_MemoryRec_ ft_mem; static struct StringsBuffer font_list; diff --git a/src/TexturePack.c b/src/TexturePack.c index 4e5c02e72..4b9d0d4f4 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -578,6 +578,7 @@ static cc_result ExtractFrom(struct Stream* stream, const cc_string* path) { } #if defined CC_BUILD_PS1 || defined CC_BUILD_SATURN +/* Load hardcoded texture pack */ #include "../misc/ps1/classicubezip.h" static cc_result ExtractFromFile(const cc_string* path) { @@ -586,6 +587,11 @@ static cc_result ExtractFromFile(const cc_string* path) { return ExtractFrom(&stream, path); } +#elif !defined CC_BUILD_FILESYSTEM +/* E.g. GBA/32X don't support textures at all */ +static cc_result ExtractFromFile(const cc_string* path) { + return ERR_NOT_SUPPORTED; +} #else static cc_result ExtractFromFile(const cc_string* path) { struct Stream stream; diff --git a/misc/UWP/Platform_UWP.cpp b/src/UWP/Platform_UWP.cpp similarity index 87% rename from misc/UWP/Platform_UWP.cpp rename to src/UWP/Platform_UWP.cpp index c42713b99..30760feb3 100644 --- a/misc/UWP/Platform_UWP.cpp +++ b/src/UWP/Platform_UWP.cpp @@ -1,10 +1,9 @@ -#include "../../src/Core.h" -#include "../../src/_PlatformBase.h" -#include "../../src/Stream.h" -#include "../../src/SystemFonts.h" -#include "../../src/Funcs.h" -#include "../../src/Utils.h" -#include "../../src/Errors.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Utils.h" +#include "../Errors.h" #define WIN32_LEAN_AND_MEAN #define NOSERVICE @@ -14,6 +13,7 @@ #define UNICODE #define _UNICODE #endif + #include #include #include @@ -40,6 +40,25 @@ cc_bool Platform_ReadonlyFilesystem; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; #define UWP_STRING(str) ((wchar_t*)(str)->uni) +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +// TODO integrate better with Window_UWP.cpp instead of hardcoding like this... +int main(int argc, char** argv) { + cc_result res; + SetupProgram(argc, argv); + + do { + res = RunProgram(argc, argv); + } while (Window_Main.Exists); + + Window_Free(); + Process_Exit(res); + return res; +} + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ @@ -387,7 +406,37 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { /* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */ static char sockaddr_size_check[sizeof(SOCKADDR_STORAGE) < CC_SOCKETADDR_MAXSIZE ? 1 : -1]; -static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { +static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst->data; + cc_uint32 ip_addr; + if (!ParseIPv4Address(ip, &ip_addr)) return false; + + addr4->sin_addr.S_un.S_addr = ip_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + + dst->size = sizeof(*addr4); + return true; +} + +static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)dst->data; + cc_winstring str; + INT size = sizeof(*addr6); + + cc_string address = String_FromReadonly(ip); + Platform_EncodeString(&str, &address); + + if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET6, NULL, (SOCKADDR*)addr6, &size)) { + addr6->sin6_port = htons(port); + + dst->size = size; + return true; + } + return false; +} + +static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { char portRaw[32]; cc_string portStr; struct addrinfo hints = { 0 }; struct addrinfo* result; @@ -423,36 +472,6 @@ static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* num return i == 0 ? ERR_INVALID_ARGUMENT : 0; } -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - SOCKADDR_IN* addr4 = (SOCKADDR_IN* )addrs[0].data; - SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)addrs[0].data; - cc_winstring str; - INT size; - - *numValidAddrs = 0; - Platform_EncodeString(&str, address); - - size = sizeof(*addr4); - if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET, NULL, (SOCKADDR*)addr4, &size)) { - addr4->sin_port = htons(port); - - addrs[0].size = size; - *numValidAddrs = 1; - return 0; - } - - size = sizeof(*addr6); - if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET6, NULL, (SOCKADDR*)addr6, &size)) { - addr6->sin6_port = htons(port); - - addrs[0].size = size; - *numValidAddrs = 1; - return 0; - } - - return ParseHostNew(str.ansi, port, addrs, numValidAddrs); -} - cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { SOCKADDR* raw_addr = (SOCKADDR*)addr->data; @@ -538,43 +557,7 @@ static cc_result Process_RawGetExePath(cc_winstring* path, int* len) { } cc_result Process_StartGame2(const cc_string* args, int numArgs) { - union STARTUPINFO_union { - STARTUPINFOW wide; - STARTUPINFOA ansi; - } si = { 0 }; // less compiler warnings this way - - cc_winstring path; - cc_string argv; char argvBuffer[NATIVE_STR_LEN]; - PROCESS_INFORMATION pi = { 0 }; - cc_winstring raw; - cc_result res; - int len, i; - - if (Platform_IsSingleProcess()) return SetGameArgs(args, numArgs); - - if ((res = Process_RawGetExePath(&path, &len))) return res; - si.wide.cb = sizeof(STARTUPINFOW); - - String_InitArray(argv, argvBuffer); - /* Game doesn't actually care about argv[0] */ - String_AppendConst(&argv, "cc"); - for (i = 0; i < numArgs; i++) - { - if (String_IndexOf(&args[i], ' ') >= 0) { - String_Format1(&argv, " \"%s\"", &args[i]); - } else { - String_Format1(&argv, " %s", &args[i]); - } - } - Platform_EncodeString(&raw, &argv); - - if (!CreateProcessW(UWP_STRING(&path), UWP_STRING(&raw), NULL, NULL, - false, 0, NULL, NULL, &si.wide, &pi)) return GetLastError(); - - /* Don't leak memory for process return code */ - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return 0; + return SetGameArgs(args, numArgs); } void Process_Exit(cc_result code) { ExitProcess(code); } @@ -599,29 +582,7 @@ cc_result Process_StartOpen(const cc_string* args) { #define UPDATE_SRC TEXT(UPDATE_FILE) cc_bool Updater_Supported = true; -#if defined _M_IX86 -const struct UpdaterInfo Updater_Info = { - "&eDirect3D 9 is recommended", 2, - { - { "Direct3D9", "ClassiCube.exe" }, - { "OpenGL", "ClassiCube.opengl.exe" } - } -}; -#elif defined _M_X64 -const struct UpdaterInfo Updater_Info = { - "&eDirect3D 9 is recommended", 2, - { - { "Direct3D9", "ClassiCube.64.exe" }, - { "OpenGL", "ClassiCube.64-opengl.exe" } - } -}; -#elif defined _M_ARM64 -const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm64-d3d11.exe" } } }; -#elif defined _M_ARM -const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm32-d3d11.exe" } } }; -#else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; -#endif cc_bool Updater_Clean(void) { return DeleteFile(UPDATE_TMP) || GetLastError() == ERROR_FILE_NOT_FOUND; diff --git a/misc/UWP/Window_UWP.cpp b/src/UWP/Window_UWP.cpp similarity index 92% rename from misc/UWP/Window_UWP.cpp rename to src/UWP/Window_UWP.cpp index 6fe90de4f..71d942edb 100644 --- a/misc/UWP/Window_UWP.cpp +++ b/src/UWP/Window_UWP.cpp @@ -1,4 +1,11 @@ -#include "../../src/Core.h" +#include "../_WindowBase.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Options.h" +#include "../Errors.h" +#include "../Graphics.h" +#include "../Game.h" #include #include @@ -23,14 +30,6 @@ using namespace Windows::System; using namespace Windows::UI::Core; using namespace Windows::UI::Input; -#include "../../src/_WindowBase.h" -#include "../../src/String.h" -#include "../../src/Funcs.h" -#include "../../src/Bitmap.h" -#include "../../src/Options.h" -#include "../../src/Errors.h" -#include "../../src/Graphics.h" -#include "../../src/Game.h" #define UWP_STRING(str) ((wchar_t*)(str)->uni) @@ -199,8 +198,11 @@ cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { static GfxResourceID fb_tex, fb_vb; static void AllocateVB(void) { - struct VertexTextured* data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&fb_vb, - VERTEX_FORMAT_TEXTURED, 4); + Gfx_DeleteVb(&fb_vb); + fb_vb = Gfx_CreateVb(VERTEX_FORMAT_TEXTURED, 4); + + struct VertexTextured* data = (struct VertexTextured*)Gfx_LockVb(fb_vb, VERTEX_FORMAT_TEXTURED, 4); + data[0].x = -1.0f; data[0].y = -1.0f; data[0].z = 0.0f; data[0].Col = PACKEDCOL_WHITE; data[0].U = 0.0f; data[0].V = 1.0f; data[1].x = 1.0f; data[1].y = -1.0f; data[1].z = 0.0f; data[1].Col = PACKEDCOL_WHITE; data[1].U = 1.0f; data[1].V = 1.0f; data[2].x = 1.0f; data[2].y = 1.0f; data[2].z = 0.0f; data[2].Col = PACKEDCOL_WHITE; data[2].U = 1.0f; data[2].V = 0.0f; @@ -285,7 +287,6 @@ void Window_DisableRawMouse(void) { struct CCApp : implements { - // IFrameworkViewSource interface IFrameworkView CreateView() { @@ -324,4 +325,4 @@ int __stdcall wWinMain(void*, void*, wchar_t** argv, int argc) { auto app = make(); CoreApplication::Run(app); -} \ No newline at end of file +} diff --git a/src/Vectors.c b/src/Vectors.c index c69baab71..04fdc1ad2 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -14,7 +14,7 @@ void Vec3_Normalise(Vec3* v) { float scale, lenSquared; lenSquared = v->x * v->x + v->y * v->y + v->z * v->z; /* handle zero vector */ - if (!lenSquared) return; + if (lenSquared == 0.0f) return; scale = 1.0f / Math_SqrtF(lenSquared); v->x = v->x * scale; @@ -205,7 +205,7 @@ cc_bool FrustumCulling_SphereInFrustum(float x, float y, float z, float radius) if (d <= -radius) return false; /* Don't test NEAR plane, it's pointless */ -#ifdef CC_BUILD_SATURN +#if defined CC_BUILD_SATURN || defined CC_BUILD_32X /* Workaround a compiler bug causing the below statement to return 0 instead */ __asm__( "!" ); #endif diff --git a/src/Vorbis.c b/src/Vorbis.c index f0fc89263..f82a6af82 100644 --- a/src/Vorbis.c +++ b/src/Vorbis.c @@ -7,6 +7,7 @@ #include "Errors.h" #include "Stream.h" +#if !defined CC_BUILD_ATARIOS && !defined CC_BUILD_AMIGA /*########################################################################################################################* *-------------------------------------------------------Ogg stream--------------------------------------------------------* *#########################################################################################################################*/ @@ -1672,3 +1673,5 @@ int Vorbis_OutputFrame(struct VorbisState* ctx, cc_int16* data) { ctx->prevBlockSize = ctx->curBlockSize; return (prevQrtr + curQrtr) * ctx->channels; } +#endif + diff --git a/src/Widgets.c b/src/Widgets.c index 2580df3a5..2bd1ae496 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -2184,6 +2184,10 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta for (i = 0; i < w->lines; i++) { line = TextGroupWidget_UNSAFE_Get(w, i); + /* TODO properly fix this buffer overflow if multiple lines */ + /* of max chat length are added by a plugin and have URLs */ + line.length = min(line.length, TEXTGROUPWIDGET_LEN); + begs[i] = -1; ends[i] = -1; if (!line.length) continue; diff --git a/src/Window_N64.c b/src/Window_N64.c index f2fd20823..0f0b21e1e 100644 --- a/src/Window_N64.c +++ b/src/Window_N64.c @@ -100,24 +100,24 @@ static void ProcessMouse(joypad_inputs_t* inputs, float delta) { /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ -static const BindMapping default_n64[BIND_COUNT] = { - [BIND_FORWARD] = { CCPAD_CUP, 0 }, - [BIND_BACK] = { CCPAD_CDOWN, 0 }, - [BIND_LEFT] = { CCPAD_CLEFT, 0 }, - [BIND_RIGHT] = { CCPAD_CRIGHT, 0 }, +static const BindMapping defaults_n64[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_CUP }, + [BIND_BACK] = { CCPAD_CDOWN }, + [BIND_LEFT] = { CCPAD_CLEFT }, + [BIND_RIGHT] = { CCPAD_CRIGHT }, - [BIND_FLY_UP] = { CCPAD_UP, 0 }, - [BIND_FLY_DOWN]= { CCPAD_DOWN, 0 }, - [BIND_SPEED] = { CCPAD_LEFT, 0 }, - [BIND_FLY] = { CCPAD_RIGHT, 0 }, + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN]= { CCPAD_DOWN }, + [BIND_SPEED] = { CCPAD_LEFT }, + [BIND_FLY] = { CCPAD_RIGHT }, - [BIND_JUMP] = { CCPAD_1, 0 }, - [BIND_INVENTORY] = { CCPAD_2, 0 }, - [BIND_PLACE_BLOCK] = { CCPAD_5, 0 }, - [BIND_HOTBAR_RIGHT] = { CCPAD_L, 0 }, - [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_INVENTORY] = { CCPAD_2 }, + [BIND_PLACE_BLOCK] = { CCPAD_5 }, + [BIND_HOTBAR_RIGHT] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, - [BIND_SET_SPAWN] = { CCPAD_START, 0 }, + [BIND_SET_SPAWN] = { CCPAD_START }, }; void Gamepads_Init(void) { @@ -169,7 +169,7 @@ void Gamepads_Process(float delta) { ProcessMouse(&inputs, delta); continue; } - int port = Gamepad_Connect(0x64 + i, default_n64); + int port = Gamepad_Connect(0x64 + i, defaults_n64); HandleButtons(port, inputs.btn); ProcessAnalogInput(port, &inputs, delta); } diff --git a/src/Window_SDL2.c b/src/Window_SDL2.c index 9f8d101c9..4c0b5dcbb 100644 --- a/src/Window_SDL2.c +++ b/src/Window_SDL2.c @@ -38,6 +38,8 @@ typedef struct _WINDATA { #endif +static void SetGLAttributes(); + static void RefreshWindowBounds(void) { SDL_GetWindowSize(win_handle, &Window_Main.Width, &Window_Main.Height); } @@ -99,7 +101,10 @@ static void DoCreateWindow(int width, int height, int flags) { void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } #if CC_GFX_BACKEND_IS_GL() -void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +void Window_Create3D(int width, int height) { + SetGLAttributes(); + DoCreateWindow(width, height, SDL_WINDOW_OPENGL); +} #else void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } #endif @@ -537,7 +542,7 @@ void Gamepads_Process(float delta) { #if CC_GFX_BACKEND_IS_GL() static SDL_GLContext win_ctx; -void GLContext_Create(void) { +void SetGLAttributes(void) { struct GraphicsMode mode; InitGraphicsMode(&mode); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode.R); @@ -553,7 +558,9 @@ void GLContext_Create(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif +} +void GLContext_Create(void) { win_ctx = SDL_GL_CreateContext(win_handle); if (!win_ctx) Window_SDLFail("creating OpenGL context"); } diff --git a/src/Window_SDL3.c b/src/Window_SDL3.c index 351c72610..0fd8edce9 100644 --- a/src/Window_SDL3.c +++ b/src/Window_SDL3.c @@ -11,6 +11,8 @@ static SDL_Window* win_handle; static Uint32 dlg_event; +static void SetGLAttributes(); + static void RefreshWindowBounds(void) { SDL_GetWindowSize(win_handle, &Window_Main.Width, &Window_Main.Height); } @@ -84,7 +86,10 @@ static void DoCreateWindow(int width, int height, int flags) { void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } #if CC_GFX_BACKEND_IS_GL() -void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +void Window_Create3D(int width, int height) { + SetGLAttributes(); + DoCreateWindow(width, height, SDL_WINDOW_OPENGL); +} #else void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } #endif @@ -567,7 +572,7 @@ void Gamepads_Process(float delta) { #if CC_GFX_BACKEND_IS_GL() static SDL_GLContext win_ctx; -void GLContext_Create(void) { +void SetGLAttributes(void) { struct GraphicsMode mode; InitGraphicsMode(&mode); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode.R); @@ -583,7 +588,9 @@ void GLContext_Create(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif +} +void GLContext_Create(void) { win_ctx = SDL_GL_CreateContext(win_handle); if (!win_ctx) Window_SDLFail("creating OpenGL context"); } diff --git a/src/Window_Symbian.cpp b/src/Window_Symbian.cpp index f9f7609fc..15d32668c 100644 --- a/src/Window_Symbian.cpp +++ b/src/Window_Symbian.cpp @@ -485,35 +485,41 @@ void CCAppUi::HandleCommandL(TInt aCommand) { // CCContainer implementation TInt CCContainer::LoopCallBack(TAny*) { - if (!WindowInfo.Exists) { - Window_RequestClose(); - container->iAppUi->Exit(); - return EFalse; - } - - // launcher -> game -> launcher -> ... loop - launcher: - if (!gameRunning) { - if (Launcher_Tick()) { - return ETrue; + cc_bool run = false; + for (;;) { + if (!WindowInfo.Exists) { + Window_RequestClose(); + container->iAppUi->Exit(); + return EFalse; } - Launcher_Finish(); - - // run game - gameRunning = true; - Game_Setup(); - container->RestartTimerL(100); + + if (run) { + run = false; + ProcessProgramArgs(0, 0); + Game_Setup(); + gameRunning = true; + container->RestartTimerL(100); + } + + if (!gameRunning) { + if (Launcher_Tick()) break; + Launcher_Finish(); + run = true; + continue; + } + + if (!Game_Running) { + gameRunning = false; + Game_Free(); +// Launcher_Setup(); +// container->RestartTimerL(10000); + WindowInfo.Exists = false; + continue; + } + + Game_RenderFrame(); + break; } - - if (!Game_Running) { - // return to launcher - gameRunning = false; - Game_Free(); - Launcher_Setup(); - container->RestartTimerL(10000); - goto launcher; - } - Game_RenderFrame(); return ETrue; } diff --git a/src/Window_Terminal.c b/src/Window_Terminal.c index af370828e..1ede3c179 100644 --- a/src/Window_Terminal.c +++ b/src/Window_Terminal.c @@ -34,7 +34,7 @@ #define OutputConsole(buf, len) WriteConsoleA(hStdout, buf, len, NULL, NULL) #define BOX_CHAR "\xE2\x96\x84" #else - #define OutputConsole(buf, len) write(STDOUT_FILENO, buf, len) + #define OutputConsole(buf, len) !!write(STDOUT_FILENO, buf, len) #define BOX_CHAR "\xE2\x96\x84" #endif @@ -146,7 +146,7 @@ static void HookTerminal(void) { tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Normal-tracking-mode - OutputConst(DEC_PM_SET("1049")); // Use Normal Screen Buffer and restore cursor as in DECRC, xterm. + OutputConst(DEC_PM_SET("1049")); OutputConst(CSI "0m"); OutputConst(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. OutputConst(DEC_PM_SET("1003")); // Ps = 1 0 0 3 ⇒ Use All Motion Mouse Tracking, xterm. See @@ -161,7 +161,7 @@ static void UnhookTerminal(void) { //ioctl(STDIN_FILENO, KDSKBMODE, orig_KB); tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); - OutputConst(DEC_PM_RESET("1049")); + OutputConst(DEC_PM_RESET("1049")); // Return to Normal Screen Buffer and restore cursor OutputConst(CSI "0m"); OutputConst(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. OutputConst(DEC_PM_SET("25")); diff --git a/src/Window_WinCE.c b/src/Window_WinCE.c new file mode 100644 index 000000000..f853744a2 --- /dev/null +++ b/src/Window_WinCE.c @@ -0,0 +1,696 @@ +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_WIN32CE +/* + The Open Toolkit Library License + + Copyright (c) 2006 - 2009 the Open Toolkit library. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "_WindowBase.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Options.h" +#include "Errors.h" +#include "Gui.h" + +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#ifndef UNICODE +#define UNICODE +#define _UNICODE +#endif + +#include +#include + +/* https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelformat */ +#define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN +#define CC_WIN_CLASSNAME TEXT("ClassiCube_Window") +#define Rect_Width(rect) (rect.right - rect.left) +#define Rect_Height(rect) (rect.bottom - rect.top) + +static HINSTANCE win_instance; +static HDC win_DC; +static cc_bool suppress_resize; +static cc_bool is_ansiWindow, grabCursor; +static int windowX, windowY; + +static const cc_uint8 key_map[] = { +/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 08 */ CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, CCKEY_F5, CCKEY_ENTER, 0, 0, +/* 10 */ 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, +/* 18 */ 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, +/* 20 */ CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, +/* 28 */ CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0, +/* 30 */ '0', '1', '2', '3', '4', '5', '6', '7', +/* 38 */ '8', '9', 0, 0, 0, 0, 0, 0, +/* 40 */ 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', +/* 48 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', +/* 50 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', +/* 58 */ 'X', 'Y', 'Z', CCKEY_LWIN, CCKEY_RWIN, CCKEY_MENU, 0, CCKEY_SLEEP, +/* 60 */ CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, +/* 68 */ CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MULTIPLY, CCKEY_KP_PLUS, 0, CCKEY_KP_MINUS, CCKEY_KP_DECIMAL, CCKEY_KP_DIVIDE, +/* 70 */ CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, +/* 78 */ CCKEY_F9, CCKEY_F10, CCKEY_F11, CCKEY_F12, CCKEY_F13, CCKEY_F14, CCKEY_F15, CCKEY_F16, +/* 80 */ CCKEY_F17, CCKEY_F18, CCKEY_F19, CCKEY_F20, CCKEY_F21, CCKEY_F22, CCKEY_F23, CCKEY_F24, +/* 88 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 90 */ CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, 0, 0, 0, 0, 0, 0, +/* 98 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* A0 */ CCKEY_LSHIFT, CCKEY_RSHIFT, CCKEY_LCTRL, CCKEY_RCTRL, CCKEY_LALT, CCKEY_RALT, CCKEY_BROWSER_PREV, CCKEY_BROWSER_NEXT, +/* A8 */ CCKEY_BROWSER_REFRESH, CCKEY_BROWSER_STOP, CCKEY_BROWSER_SEARCH, CCKEY_BROWSER_FAVORITES, CCKEY_BROWSER_HOME, CCKEY_VOLUME_MUTE, CCKEY_VOLUME_DOWN, CCKEY_VOLUME_UP, +/* B0 */ CCKEY_MEDIA_NEXT, CCKEY_MEDIA_PREV, CCKEY_MEDIA_STOP, CCKEY_MEDIA_PLAY, CCKEY_LAUNCH_MAIL, CCKEY_LAUNCH_MEDIA, CCKEY_LAUNCH_APP1, CCKEY_LAUNCH_CALC, +/* B8 */ 0, 0, CCKEY_SEMICOLON, CCKEY_EQUALS, CCKEY_COMMA, CCKEY_MINUS, CCKEY_PERIOD, CCKEY_SLASH, +/* C0 */ CCKEY_TILDE, 0, 0, 0, 0, 0, 0, 0, +/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D8 */ 0, 0, 0, CCKEY_LBRACKET, CCKEY_BACKSLASH, CCKEY_RBRACKET, CCKEY_QUOTE, 0, +}; + +static int MapNativeKey(WPARAM vk_key, LPARAM meta) { + LPARAM ext = meta & (1UL << 24); + LPARAM scancode = (meta >> 16) & 0xFF; + int key; + if (ext) scancode |= 0xE000; + + switch (vk_key) + { + case VK_CONTROL: + return ext ? CCKEY_RCTRL : CCKEY_LCTRL; + case VK_MENU: + return ext ? CCKEY_RALT : CCKEY_LALT; + case VK_RETURN: + return ext ? CCKEY_KP_ENTER : CCKEY_ENTER; + } + + key = vk_key < Array_Elems(key_map) ? key_map[vk_key] : 0; + if (!key) Platform_Log2("Unknown key: %x, %x", &vk_key, &scancode); + return key; +} + +static cc_bool RefreshWindowDimensions(void) { + HWND hwnd = Window_Main.Handle.ptr; + RECT rect; + int width = Window_Main.Width, height = Window_Main.Height; + + GetClientRect(hwnd, &rect); + Window_Main.Width = Rect_Width(rect); + Window_Main.Height = Rect_Height(rect); + + return width != Window_Main.Width || height != Window_Main.Height; +} + +static void RefreshWindowPosition(void) { + HWND hwnd = Window_Main.Handle.ptr; + POINT topLeft = { 0, 0 }; + /* GetClientRect always returns 0,0 for left,top (see MSDN) */ + ClientToScreen(hwnd, &topLeft); + windowX = topLeft.x; windowY = topLeft.y; +} + +static void GrabCursor(void) { +#ifndef CC_BUILD_TOUCH + HWND hwnd = Window_Main.Handle.ptr; + RECT rect; + if (!grabCursor || !Input.RawMode) return; + + GetWindowRect(hwnd, &rect); + ClipCursor(&rect); +#endif +} + +static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { + float wheelDelta; + cc_bool sized; + HWND hwnd; + + switch (message) { + case WM_ACTIVATE: + Window_Main.Focused = LOWORD(wParam) != 0; + Event_RaiseVoid(&WindowEvents.FocusChanged); + break; + + case WM_ERASEBKGND: + return 1; /* Avoid flickering */ + + case WM_PAINT: + { + hwnd = Window_Main.Handle.ptr; + //ValidateRect(hwnd, NULL); + PAINTSTRUCT ps; + HWND hwnd = Window_Main.Handle.ptr; + HDC hdc = BeginPaint(handle, &ps); + EndPaint(handle, &ps); + Event_RaiseVoid(&WindowEvents.RedrawNeeded); + return 0; + } + + case WM_SIZE: + sized = RefreshWindowDimensions(); + + if (sized && !suppress_resize) Event_RaiseVoid(&WindowEvents.Resized); + Event_RaiseVoid(&WindowEvents.StateChanged); + break; + + case WM_MOVE: + RefreshWindowPosition(); + break; + + case WM_CHAR: + /* TODO: Use WM_UNICHAR instead, as WM_CHAR is just utf16 */ + Event_RaiseInt(&InputEvents.Press, (cc_unichar)wParam); + break; + +#ifndef CC_BUILD_TOUCH + case WM_MOUSEMOVE: + /* Set before position change, in case mouse buttons changed when outside window */ + if (!(wParam & 0x01)) Input_SetReleased(CCMOUSE_L); + //Input_SetNonRepeatable(CCMOUSE_L, wParam & 0x01); + Input_SetNonRepeatable(CCMOUSE_R, wParam & 0x02); + Input_SetNonRepeatable(CCMOUSE_M, wParam & 0x10); + /* TODO: do we need to set XBUTTON1/XBUTTON2 here */ + Pointer_SetPosition(0, LOWORD(lParam), HIWORD(lParam)); + break; +#else + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) + Input_UpdateTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; +#endif + case WM_MOUSEWHEEL: + wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; + Mouse_ScrollVWheel(wheelDelta); + return 0; +#ifndef CC_BUILD_TOUCH + case WM_LBUTTONDOWN: + Input_SetPressed(CCMOUSE_L); break; +#else + case WM_LBUTTONDOWN: + Input_AddTouch(0, (short)LOWORD(lParam), (short)HIWORD(lParam)); + break; +#endif + case WM_MBUTTONDOWN: + Input_SetPressed(CCMOUSE_M); break; + case WM_RBUTTONDOWN: + Input_SetPressed(CCMOUSE_R); break; + +#ifndef CC_BUILD_TOUCH + case WM_LBUTTONUP: + Input_SetReleased(CCMOUSE_L); break; +#else + case WM_LBUTTONUP: + Input_RemoveTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; +#endif + case WM_MBUTTONUP: + Input_SetReleased(CCMOUSE_M); break; + case WM_RBUTTONUP: + Input_SetReleased(CCMOUSE_R); break; + + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { + cc_bool pressed = message == WM_KEYDOWN || message == WM_SYSKEYDOWN; + /* Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed + and released. It looks like neither key is released in this case, or that the wrong key is + released in the case of Control and Alt. + To combat this, we are going to release both keys when either is released. Hacky, but should work. + Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). + In this case, both keys will be reported as pressed. */ + cc_bool lShiftDown, rShiftDown; + int key; + + if (wParam == VK_SHIFT) { + /* The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit + to distinguish between left and right keys. Moreover, pressing both keys and releasing one + may result in both keys being held down (but not always).*/ + lShiftDown = ((USHORT)GetKeyState(VK_LSHIFT)) >> 15; + rShiftDown = ((USHORT)GetKeyState(VK_RSHIFT)) >> 15; + + if (!pressed || lShiftDown != rShiftDown) { + Input_Set(CCKEY_LSHIFT, lShiftDown); + Input_Set(CCKEY_RSHIFT, rShiftDown); + } + } else { + key = MapNativeKey(wParam, lParam); + if (key) Input_Set(key, pressed); + } + return 0; + } break; + + case WM_SYSCHAR: + return 0; + + case WM_KILLFOCUS: + /* TODO: Keep track of keyboard when focus is lost */ +#ifndef CC_BUILD_TOUCH + Input_Clear(); +#else + Input_SetTouchMode(TRUE); +#endif + break; + + case WM_CLOSE: + Window_Main.Exists = false; + Window_RequestClose(); + return 0; + + case WM_DESTROY: + UnregisterClassW(CC_WIN_CLASSNAME, win_instance); + break; + } + return DefWindowProc(handle, message, wParam, lParam); +} + + +/*########################################################################################################################* +*--------------------------------------------------Public implementation--------------------------------------------------* +*#########################################################################################################################*/ +void Window_PreInit(void) { + DisplayInfo.CursorVisible = true; +} + +void Window_Init(void) { + HDC hdc; + Input.Sources = INPUT_SOURCE_NORMAL; + + hdc = GetDC(NULL); + DisplayInfo.Width = GetSystemMetrics(SM_CXSCREEN); + DisplayInfo.Height = GetSystemMetrics(SM_CYSCREEN); + DisplayInfo.Depth = GetDeviceCaps(hdc, BITSPIXEL); + DisplayInfo.ScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + DisplayInfo.ScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; + ReleaseDC(NULL, hdc); + + /* https://docs.microsoft.com/en-us/windows/win32/opengl/reading-color-values-from-the-framebuffer */ + /* https://devblogs.microsoft.com/oldnewthing/20101013-00/?p=12543 */ + /* TODO probably should always multiply? not just for 16 colors */ + if (DisplayInfo.Depth != 1) return; + DisplayInfo.Depth *= GetDeviceCaps(hdc, PLANES); + Input_SetTouchMode(TRUE); + //Gui_SetTouchUI(TRUE); +} + +void Window_Free(void) { } + +static ATOM DoRegisterClass(void) { + ATOM atom; + cc_result res; + WNDCLASSW wc = { 0 }; + wc.style = CS_OWNDC; /* https://stackoverflow.com/questions/48663815/getdc-releasedc-cs-owndc-with-opengl-and-gdi */ + wc.hInstance = win_instance; + wc.lpfnWndProc = Window_Procedure; + wc.lpszClassName = CC_WIN_CLASSNAME; + + wc.hIcon = (HICON)LoadImage(win_instance, MAKEINTRESOURCE(1), IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0); + wc.hCursor = LoadCursorW(NULL, IDC_ARROW); + + if ((atom = RegisterClass(&wc))) return atom; +} + +static HWND CreateWindowHandle(ATOM atom, int width, int height) { + cc_result res; + HWND hwnd; + RECT r; + + /* Calculate final window rectangle after window decorations are added (titlebar, borders etc) */ + r.left = Display_CentreX(width); r.right = r.left + width; + r.top = Display_CentreY(height); r.bottom = r.top + height; + AdjustWindowRectEx(&r, CC_WIN_STYLE, false, 0); + + + if ((hwnd = CreateWindowExW(0, CC_WIN_CLASSNAME, NULL, CC_WIN_STYLE, + r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return hwnd; + res = GetLastError(); + + Process_Abort2(res, "Failed to create window"); + return NULL; +} + +static void DoCreateWindow(int width, int height) { + ATOM atom; + HWND hwnd; + + width = min(width, 240); + height = min(height, 160); + + win_instance = GetModuleHandle(NULL); + /* TODO: UngroupFromTaskbar(); */ + width = Display_ScaleX(width); + height = Display_ScaleY(height); + + atom = DoRegisterClass(); + hwnd = CreateWindowHandle(atom, width, height); + RefreshWindowDimensions(); + RefreshWindowPosition(); + + win_DC = GetDC(hwnd); + if (!win_DC) Process_Abort2(GetLastError(), "Failed to get device context"); + + Window_Main.Exists = true; + Window_Main.Handle.ptr = hwnd; + Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; + Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; + + grabCursor = Options_GetBool(OPT_GRAB_CURSOR, false); +} +void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } +void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } + +void Window_Destroy(void) { + HWND hwnd = Window_Main.Handle.ptr; + if (win_DC) ReleaseDC(hwnd, win_DC); + DestroyWindow(hwnd); +} + +void Window_SetTitle(const cc_string* title) { + HWND hwnd = Window_Main.Handle.ptr; + cc_winstring str; + Platform_EncodeString(&str, title); + SetWindowTextW(hwnd, str.uni); +} + +void Clipboard_GetText(cc_string* value) { + HWND hwnd = Window_Main.Handle.ptr; + cc_bool unicode; + HANDLE hGlobal; + SIZE_T size; + void* src; + int i; + + /* retry up to 50 times */ + for (i = 0; i < 50; i++) { + if (!OpenClipboard(hwnd)) { + Thread_Sleep(10); + continue; + } + + unicode = true; + hGlobal = GetClipboardData(CF_UNICODETEXT); + if (!hGlobal) { + hGlobal = GetClipboardData(CF_TEXT); + unicode = false; + } + + if (!hGlobal) { CloseClipboard(); return; } + src = GlobalLock(hGlobal); + size = GlobalSize(hGlobal); + + /* ignore trailing NULL at end */ + /* TODO: Verify it's always there */ + if (unicode) { + String_AppendUtf16(value, src, size - 2); + } else { + String_AppendCP1252(value, src, size - 1); + } + + GlobalUnlock(hGlobal); + CloseClipboard(); + return; + } +} + +void Clipboard_SetText(const cc_string* value) { + HWND hwnd = Window_Main.Handle.ptr; + cc_unichar* text; + HANDLE hGlobal; + int i; + + /* retry up to 10 times */ + for (i = 0; i < 10; i++) { + if (!OpenClipboard(hwnd)) { + Thread_Sleep(100); + continue; + } + + hGlobal = GlobalAlloc(GMEM_MOVEABLE, (value->length + 1) * 2); + if (!hGlobal) { CloseClipboard(); return; } + + text = (cc_unichar*)GlobalLock(hGlobal); + for (i = 0; i < value->length; i++, text++) { + *text = Convert_CP437ToUnicode(value->buffer[i]); + } + *text = '\0'; + + GlobalUnlock(hGlobal); + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, hGlobal); + CloseClipboard(); + return; + } +} + +int Window_GetWindowState(void) { + HWND hwnd = Window_Main.Handle.ptr; + DWORD s = GetWindowLong(hwnd, GWL_STYLE); + + if ((s & WS_MINIMIZE)) return WINDOW_STATE_MINIMISED; + if ((s & WS_MAXIMIZE) && (s & WS_POPUP)) return WINDOW_STATE_FULLSCREEN; + return WINDOW_STATE_NORMAL; +} + +static void ToggleFullscreen(HWND hwnd, cc_bool fullscreen, UINT finalShow) { + DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + style |= (fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW); + + suppress_resize = true; + { + ShowWindow(hwnd, SW_RESTORE); /* reset maximised state */ + SetWindowLong(hwnd, GWL_STYLE, style); + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + ShowWindow(hwnd, finalShow); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + Window_ProcessEvents(0.0); + } + suppress_resize = false; + + /* call Resized event only once */ + RefreshWindowDimensions(); + Event_RaiseVoid(&WindowEvents.Resized); +} + +static UINT win_show; +cc_result Window_EnterFullscreen(void) { + HWND hwnd = Window_Main.Handle.ptr; + WINDOWPLACEMENT w = { 0 }; + w.length = sizeof(WINDOWPLACEMENT); + + win_show = w.showCmd; + ToggleFullscreen(hwnd, true, SW_MAXIMIZE); + return 0; +} + +cc_result Window_ExitFullscreen(void) { + HWND hwnd = Window_Main.Handle.ptr; + ToggleFullscreen(hwnd, false, win_show); + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { + HWND hwnd = Window_Main.Handle.ptr; + ShowWindow(hwnd, SW_SHOW); + BringWindowToTop(hwnd); + SetForegroundWindow(hwnd); +} + +void Window_SetSize(int width, int height) { + HWND hwnd = Window_Main.Handle.ptr; + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + RECT rect = { 0, 0, width, height }; + AdjustWindowRectEx(&rect, CC_WIN_STYLE, false, 0); + + SetWindowPos(hwnd, NULL, 0, 0, + Rect_Width(rect), Rect_Height(rect), SWP_NOMOVE); +} + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + +void Window_ProcessEvents(float delta) { + HWND foreground; + HWND hwnd; + MSG msg; + + while (PeekMessageW(&msg, NULL, 0, 0, 1)) { + TranslateMessage(&msg); DispatchMessageW(&msg); + } + + foreground = GetForegroundWindow(); + if (foreground) { + hwnd = Window_Main.Handle.ptr; + Window_Main.Focused = foreground == hwnd; + } +} + +void Gamepads_Init(void) { + +} + +void Gamepads_Process(float delta) { } + +static void Cursor_GetRawPos(int* x, int* y) { + POINT point; + GetCursorPos(&point); + *x = point.x; *y = point.y; +} + +void Cursor_SetPosition(int x, int y) { + SetCursorPos(x + windowX, y + windowY); +} +static void Cursor_DoSetVisible(cc_bool visible) { + int i; + /* ShowCursor actually is a counter (returns > 0 if visible, <= 0 if not) */ + /* Try multiple times in case cursor count was changed by something else */ + /* (there's at least system out there that requires 30 times) */ + if (visible) { + for (i = 0; i < 50 && ShowCursor(true) < 0; i++) { } + } else { + for (i = 0; i < 50 && ShowCursor(false) >= 0; i++) {} + } +} + +static void ShowDialogCore(const char* title, const char* msg) { + HWND hwnd = Window_Main.Handle.ptr; + + int tlen = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); + int mlen = MultiByteToWideChar(CP_UTF8, 0, msg, -1, NULL, 0); + + wchar_t* wtitle = (wchar_t*)malloc(tlen * sizeof(wchar_t)); + wchar_t* wmsg = (wchar_t*)malloc(mlen * sizeof(wchar_t)); + + MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, tlen); + MultiByteToWideChar(CP_UTF8, 0, msg, -1, wmsg, mlen); + + MessageBoxW(hwnd, wmsg, wtitle, 0); + + free(wtitle); + free(wmsg); +} + +static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load, + const char* const* fileExts, const cc_string* defaultName) { + // TODO + return 0; +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + const char* const* fileExts = args->filters; + cc_string filters; char buffer[NATIVE_STR_LEN]; + int i; + + /* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */ + String_InitArray(filters, buffer); + String_Format1(&filters, "%c (", args->description); + for (i = 0; fileExts[i]; i++) + { + if (i) String_Append(&filters, ';'); + String_Format1(&filters, "*%c", fileExts[i]); + } + String_Append(&filters, ')'); + String_Append(&filters, '\0'); + + for (i = 0; fileExts[i]; i++) + { + if (i) String_Append(&filters, ';'); + String_Format1(&filters, "*%c", fileExts[i]); + } + String_Append(&filters, '\0'); + + return OpenSaveFileDialog(&filters, args->Callback, true, fileExts, &String_Empty); +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + const char* const* titles = args->titles; + const char* const* fileExts = args->filters; + cc_string filters; char buffer[NATIVE_STR_LEN]; + int i; + + /* Filter tokens are \0 separated - e.g. "Map (*.cw)\0*.cw\0 */ + String_InitArray(filters, buffer); + for (i = 0; fileExts[i]; i++) + { + String_Format2(&filters, "%c (*%c)", titles[i], fileExts[i]); + String_Append(&filters, '\0'); + String_Format1(&filters, "*%c", fileExts[i]); + String_Append(&filters, '\0'); + } + return OpenSaveFileDialog(&filters, args->Callback, false, fileExts, &args->defaultName); +} + +static HDC draw_DC; +static HBITMAP draw_DIB; + +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + BITMAPINFO hdr = { 0 }; + cc_result res; + + bmp->width = width; + bmp->height = height; + if (!draw_DC) draw_DC = CreateCompatibleDC(win_DC); + + /* sizeof(BITMAPINFO) does not work on Windows 9x */ + hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + hdr.bmiHeader.biWidth = width; + hdr.bmiHeader.biHeight = -height; + hdr.bmiHeader.biBitCount = 32; + hdr.bmiHeader.biPlanes = 1; + + draw_DIB = CreateDIBSection(draw_DC, &hdr, DIB_RGB_COLORS, (void**)&bmp->scan0, NULL, 0); + if (draw_DIB) return; +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + HGDIOBJ oldSrc = SelectObject(draw_DC, draw_DIB); + BitBlt(win_DC, r.x, r.y, r.width, r.height, draw_DC, r.x, r.y, SRCCOPY); + SelectObject(draw_DC, oldSrc); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + if (draw_DIB) DeleteObject(draw_DIB); + draw_DIB = NULL; +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Close(void) { } + + +void Window_EnableRawMouse(void) { + Input.RawMode = true; +} + +void Window_UpdateRawMouse(void) { } + +void Window_DisableRawMouse(void) { + Input.RawMode = false; +} + +#endif diff --git a/src/_GLShared.h b/src/_GLShared.h index 40c2afa65..dd497511d 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -70,22 +70,18 @@ static void* FastAllocTempMem(int size) { static cc_bool convert_rgba; static void ConvertRGBA(void* dst, const void* src, int numPixels) { - cc_uint8* d = (cc_uint8*)dst; - cc_uint8* s = (cc_uint8*)src; + cc_uint8* d = (cc_uint8*)dst; + BitmapCol* s = (BitmapCol*)src; int i; - for (i = 0; i < numPixels; i++, d += 4, s += 4) { -#ifdef CC_BUILD_IRIX - d[0] = s[1]; - d[1] = s[2]; - d[2] = s[3]; - d[3] = s[0]; -#else - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = s[3]; -#endif + /* R,G,B,A byte order regardless of system endian */ + for (i = 0; i < numPixels; i++, d += 4, s++) + { + BitmapCol col = *s; + d[0] = BitmapCol_R(col); + d[1] = BitmapCol_G(col); + d[2] = BitmapCol_B(col); + d[3] = BitmapCol_A(col); } } diff --git a/src/_HttpBase.h b/src/_HttpBase.h index 3ac646c98..af32751cf 100644 --- a/src/_HttpBase.h +++ b/src/_HttpBase.h @@ -23,14 +23,11 @@ void HttpRequest_Free(struct HttpRequest* request) { } #define HttpRequest_Copy(dst, src) Mem_Copy(dst, src, sizeof(struct HttpRequest)) + /*########################################################################################################################* *----------------------------------------------------Http requests list---------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_NETWORKING - #define HTTP_DEF_ELEMS 10 -#else - #define HTTP_DEF_ELEMS 1 /* TODO better unused code removal */ -#endif +#define HTTP_DEF_ELEMS 10 struct RequestList { int count, capacity; @@ -111,6 +108,133 @@ static void RequestList_Free(struct RequestList* list) { } +/*########################################################################################################################* +*---------------------------------------------------Common buffer code----------------------------------------------------* +*#########################################################################################################################*/ +/* Ensures data buffer has enough space left to append amount bytes */ +static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) { + cc_uint32 newSize = req->size + amount; + cc_uint8* ptr; + if (newSize <= req->_capacity) return true; + + if (!req->_capacity) { + /* Allocate initial storage */ + req->_capacity = req->contentLength ? req->contentLength : 1; + req->_capacity = max(req->_capacity, newSize); + + ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1); + } else { + /* Reallocate if capacity reached */ + req->_capacity = newSize; + ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1); + } + + if (!ptr) return false; + req->data = ptr; + return true; +} + +/* Increases size and updates current progress */ +static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) { + req->size += read; + if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength); +} + + +/*########################################################################################################################* +*---------------------------------------------------Common header code----------------------------------------------------* +*#########################################################################################################################*/ +static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) { + cc_string name, data; + int dataEnd; + String_UNSAFE_Separate(value, '=', &name, &data); + /* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */ + /* However only the __cfduid=xyz part of the cookie should be stored */ + dataEnd = String_IndexOf(&data, ';'); + if (dataEnd >= 0) data.length = dataEnd; + + EntryList_Set(req->cookies, &name, &data, '='); +} + +static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) { + int contentLen = 0; + Convert_ParseInt(value, &contentLen); + + if (contentLen <= 0) return; + req->contentLength = contentLen; +} + +/* Parses a HTTP header */ +static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { + static const cc_string httpVersion = String_FromConst("HTTP"); + cc_string name, value, parts[3]; + int numParts; + + /* HTTP[version] [status code] [status reason] */ + if (String_CaselessStarts(line, &httpVersion)) { + numParts = String_UNSAFE_Split(line, ' ', parts, 3); + if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode); + } + /* For all other headers: name: value */ + if (!String_UNSAFE_Separate(line, ':', &name, &value)) return; + + if (String_CaselessEqualsConst(&name, "ETag")) { + String_CopyToRawArray(req->etag, &value); + } else if (String_CaselessEqualsConst(&name, "Content-Length")) { + Http_ParseContentLength(req, &value); + } else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) { + /* dropbox stopped returning Content-Length header since switching to chunked transfer */ + /* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */ + Http_ParseContentLength(req, &value); + } else if (String_CaselessEqualsConst(&name, "Last-Modified")) { + String_CopyToRawArray(req->lastModified, &value); + } else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) { + Http_ParseCookie(req, &value); + } +} + +/* Adds a http header to the request headers. */ +static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value); + +/* Adds all the appropriate headers for a request. */ +static void Http_SetRequestHeaders(struct HttpRequest* req) { + static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded"); + cc_string str, cookies; char cookiesBuffer[1024]; + int i; + + if (req->lastModified[0]) { + str = String_FromRawArray(req->lastModified); + Http_AddHeader(req, "If-Modified-Since", &str); + } + if (req->etag[0]) { + str = String_FromRawArray(req->etag); + Http_AddHeader(req, "If-None-Match", &str); + } + + if (req->data) Http_AddHeader(req, "Content-Type", &contentType); + if (!req->cookies || !req->cookies->count) return; + + String_InitArray(cookies, cookiesBuffer); + for (i = 0; i < req->cookies->count; i++) { + if (i) String_AppendConst(&cookies, "; "); + str = StringsBuffer_UNSAFE_Get(req->cookies, i); + String_AppendString(&cookies, &str); + } + Http_AddHeader(req, "Cookie", &cookies); +} + +/* TODO: Rewrite to use a local variable instead */ +static cc_string* Http_GetUserAgent_UNSAFE(void) { + static char userAgentBuffer[STRING_SIZE]; + static cc_string userAgent; + + String_InitArray(userAgent, userAgentBuffer); + String_AppendConst(&userAgent, GAME_APP_NAME); + String_AppendConst(&userAgent, Platform_AppNameSuffix); + return &userAgent; +} + + /*########################################################################################################################* *--------------------------------------------------Common downloader code-------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index 576dfb91a..4a170d28d 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -102,7 +102,7 @@ static char gameArgs[GAME_MAX_CMDARGS][STRING_SIZE]; static int gameNumArgs; static cc_bool gameHasArgs; -static cc_result SetGameArgs(const cc_string* args, int numArgs) { +static CC_INLINE cc_result SetGameArgs(const cc_string* args, int numArgs) { int i; for (i = 0; i < numArgs; i++) { @@ -114,7 +114,7 @@ static cc_result SetGameArgs(const cc_string* args, int numArgs) { return 0; } -static int GetGameArgs(cc_string* args) { +static CC_INLINE int GetGameArgs(cc_string* args) { int i, count = gameNumArgs; for (i = 0; i < count; i++) { @@ -341,3 +341,118 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a } #endif + +/*########################################################################################################################* +*--------------------------------------------------------Updater----------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_UPDATER +cc_bool Updater_Supported = false; +cc_bool Updater_Clean(void) { return true; } + +const struct UpdaterInfo Updater_Info = { "&eRedownload or recompile to update", 0 }; + +cc_result Updater_Start(const char** action) { + *action = "Starting game"; + return ERR_NOT_SUPPORTED; +} + +cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } + +cc_result Updater_MarkExecutable(void) { return ERR_NOT_SUPPORTED; } + +cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } +#endif + + +/*########################################################################################################################* +*-------------------------------------------------------Dynamic lib-------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_DYNLIB +const cc_string DynamicLib_Ext = String_FromConst(".so"); + +void* DynamicLib_Load2(const cc_string* path) { return NULL; } +void* DynamicLib_Get2(void* lib, const char* name) { return NULL; } + +cc_bool DynamicLib_DescribeError(cc_string* dst) { return false; } +#endif + + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_SOCKETS +cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +void Socket_Close(cc_socket s) { } + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + return ERR_NOT_SUPPORTED; +} +#endif + + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_THREADING +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + *handle = NULL; +} + +void Thread_Detach(void* handle) { +} + +void Thread_Join(void* handle) { +} + +void* Mutex_Create(const char* name) { + return NULL; +} + +void Mutex_Free(void* handle) { +} + +void Mutex_Lock(void* handle) { +} + +void Mutex_Unlock(void* handle) { +} + +void* Waitable_Create(const char* name) { + return NULL; +} + +void Waitable_Free(void* handle) { +} + +void Waitable_Signal(void* handle) { +} + +void Waitable_Wait(void* handle) { +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { +} +#endif diff --git a/src/_PlatformConsole.h b/src/_PlatformConsole.h index 7877e42bb..c8930a32e 100644 --- a/src/_PlatformConsole.h +++ b/src/_PlatformConsole.h @@ -8,7 +8,7 @@ cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; int main(int argc, char** argv) { SetupProgram(argc, argv); while (Window_Main.Exists) { - RunProgram(argc, argv); + RunProgram(argc, argv); } Window_Free(); @@ -44,12 +44,6 @@ void Mem_Free(void* mem) { #endif -/*########################################################################################################################* -*-----------------------------------------------------Directory/File------------------------------------------------------* -*#########################################################################################################################*/ -void Directory_GetCachePath(cc_string* path) { } - - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* *#########################################################################################################################*/ @@ -86,50 +80,3 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { return 0; } -void Process_Exit(cc_result code) { exit(code); } - - -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - *action = "Starting game"; - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } - -cc_result Updater_MarkExecutable(void) { return ERR_NOT_SUPPORTED; } - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -// TODO can this actually be supported somehow -const cc_string DynamicLib_Ext = String_FromConst(".so"); - -void* DynamicLib_Load2(const cc_string* path) { return NULL; } -void* DynamicLib_Get2(void* lib, const char* name) { return NULL; } - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - String_AppendConst(dst, "Dynamic linking unsupported"); - return true; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Encryption--------------------------------------------------------* -*#########################################################################################################################*/ -#ifndef CC_BUILD_3DS -cc_result Platform_GetEntropy(void* data, int len) { - return ERR_NOT_SUPPORTED; -} -#endif - diff --git a/src/Platform_Amiga.c b/src/amiga/Platform_Amiga.c similarity index 68% rename from src/Platform_Amiga.c rename to src/amiga/Platform_Amiga.c index f89e51b6c..6df619547 100644 --- a/src/Platform_Amiga.c +++ b/src/amiga/Platform_Amiga.c @@ -1,15 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_AMIGA +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" #include #include @@ -29,7 +31,11 @@ const char* Platform_AppNameSuffix = " Amiga"; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; cc_bool Platform_ReadonlyFilesystem; +#ifdef __GNUC__ static const char __attribute__((used)) min_stack[] = "$STACK:102400"; +#else +size_t __stack = 65536; // vbcc +#endif /*########################################################################################################################* *-----------------------------------------------------Main entrypoint-----------------------------------------------------* @@ -85,9 +91,10 @@ void Platform_Log(const char* msg, int len) { TimeMS DateTime_CurrentUTC(void) { ULONG secs, micro; - CurrentTime(&secs, µ); + //CurrentTime(&secs, µ); // TODO epoch adjustment - return secs; + //return secs; + return 0; } void DateTime_CurrentLocal(struct cc_datetime* t) { @@ -111,9 +118,14 @@ void Process_Abort2(cc_result result, const char* raw_msg) { #define US_PER_SEC 1000000ULL cc_uint64 Stopwatch_Measure(void) { +#ifdef __GNUC__ ULONG secs, micro; CurrentTime(&secs, µ); return secs * US_PER_SEC + micro; +#else + // TODO + return 10; +#endif } cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { @@ -201,91 +213,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Delay(ticks); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; - // TODO -} - -void Thread_Detach(void* handle) { - // TODO -} - -void Thread_Join(void* handle) { - // TODO -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { - // TODO -} - -void Mutex_Lock(void* handle) { - // TODO -} - -void Mutex_Unlock(void* handle) { - // TODO -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { - // TODO -} - -void Waitable_Signal(void* handle) { - // TODO -} - -void Waitable_Wait(void* handle) { - // TODO -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { - // TODO -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { - -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* @@ -330,49 +257,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dylib"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ @@ -399,4 +283,3 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { cc_result Platform_GetEntropy(void* data, int len) { return ERR_NOT_SUPPORTED; } -#endif diff --git a/src/Window_Amiga.c b/src/amiga/Window_Amiga.c similarity index 90% rename from src/Window_Amiga.c rename to src/amiga/Window_Amiga.c index 16553c9fd..38a7806ba 100644 --- a/src/Window_Amiga.c +++ b/src/amiga/Window_Amiga.c @@ -1,12 +1,9 @@ -#include "Core.h" -#if defined CC_BUILD_AMIGA - -#include "_WindowBase.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Options.h" -#include "Errors.h" +#include "../_WindowBase.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Options.h" +#include "../Errors.h" /*########################################################################################################################* @@ -147,4 +144,3 @@ void Window_UpdateRawMouse(void) { void Window_DisableRawMouse(void) { DefaultDisableRawMouse(); } -#endif diff --git a/src/atari_st/Platform_Atari.c b/src/atari_st/Platform_Atari.c new file mode 100644 index 000000000..1ddad6b12 --- /dev/null +++ b/src/atari_st/Platform_Atari.c @@ -0,0 +1,254 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../Options.h" +#include "../Animations.h" + +#include +#include +#include + +#include "../../third_party/tinyalloc/tinyalloc.c" + +typedef volatile uint8_t vu8; +typedef volatile uint16_t vu16; +typedef volatile uint32_t vu32; + +const cc_result ReturnCode_FileShareViolation = 1000000000; // not used +const cc_result ReturnCode_FileNotFound = -1; +const cc_result ReturnCode_DirectoryExists = -1; +const cc_result ReturnCode_SocketInProgess = -1; +const cc_result ReturnCode_SocketWouldBlock = -1; +const cc_result ReturnCode_SocketDropped = -1; + +const char* Platform_AppNameSuffix = " GBA"; +cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; + + +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunGame(); + //RunProgram(argc, argv); + } + + Window_Free(); + return 0; +} + +/*########################################################################################################################* +*---------------------------------------------------------Memory----------------------------------------------------------* +*#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + +void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + void* ptr = size ? ta_alloc(size) : NULL; + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); + return ptr; +} + +void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + void* ptr = size ? ta_alloc(size) : NULL; + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); + + if (ptr) Mem_Set(ptr, 0, size); + return ptr; +} + +void* Mem_TryRealloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize) { + return NULL; // TODO +} + +void Mem_Free(void* mem) { + if (mem) ta_free(mem); +} + + +/*########################################################################################################################* +*------------------------------------------------------Logging/Time-------------------------------------------------------* +*#########################################################################################################################*/ +// Number of ticks 200 HZ system timer +// Must be called when in supervisor mode +static LONG Read_200HZ(void) { return *((LONG*)0x04BA); } + +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + + // 200 ticks a second + // 1,000,000 microseconds a second + // > one tick = 10^6/200 = 5000 microseconds + return (end - beg) * 5000; +} + +cc_uint64 Stopwatch_Measure(void) { + return Supexec(Read_200HZ); +} + +void Platform_Log(const char* msg, int len) { + for (int i = 0; i < len; i++) + { + Bconout(2, msg[i]); + } + Bconout(2, '\r'); + Bconout(2, '\n'); +} + +TimeMS DateTime_CurrentUTC(void) { + return 0; +} + +void DateTime_CurrentLocal(struct cc_datetime* t) { + Mem_Set(t, 0, sizeof(*t)); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Crash handling----------------------------------------------------* +*#########################################################################################################################*/ +void CrashHandler_Install(void) { +} + +void Process_Abort2(cc_result result, const char* raw_msg) { + Platform_LogConst(raw_msg); + exit(0); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Directory/File------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { + char* str = dst->buffer; + String_EncodeUtf8(str, path); +} + +void Directory_GetCachePath(cc_string* path) { } + +cc_result Directory_Create(const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +int File_Exists(const cc_filepath* path) { + return false; +} + +cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Open(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Create(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Close(cc_file file) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Seek(cc_file file, int offset, int seekType) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Position(cc_file file, cc_uint32* pos) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Length(cc_file file, cc_uint32* len) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +// !!! NOTE: PSP uses cooperative multithreading (not preemptive multithreading) !!! +void Thread_Sleep(cc_uint32 milliseconds) { + // TODO probably wrong +} + + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_Init(void) { + LONG size = (LONG)Malloc(-1); + char* ptr = Malloc(size); + + char* heap_beg = ptr; + char* heap_end = ptr + size; + ta_init(heap_beg, heap_end, 256, 16, 4); + + int size_ = (int)(heap_end - heap_beg); +} + +void Platform_Free(void) { } + +cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { + return false; +} + +cc_bool Process_OpenSupported = false; +cc_result Process_StartOpen(const cc_string* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} + +cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { exit(code); } + diff --git a/src/atari_st/Window_Atari.c b/src/atari_st/Window_Atari.c new file mode 100644 index 000000000..1314f558e --- /dev/null +++ b/src/atari_st/Window_Atari.c @@ -0,0 +1,206 @@ +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Camera.h" + +#include +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 + +/*########################################################################################################################* +*------------------------------------------------------General data-------------------------------------------------------* +*#########################################################################################################################*/ +struct _DisplayData DisplayInfo; +struct cc_window WindowInfo; + +// TODO backup palette +void Window_PreInit(void) { + for (int i = 0; i < 16; i++) + { + int R = (i & 0x1) >> 0; + int B = (i & 0x2) >> 1; + int G = (i & 0xC) >> 2; + + R = R ? ((R << 3) | 0x07) : 0; + B = B ? ((B << 3) | 0x07) : 0; + G = G ? ((G << 2) | 0x03) : 0; + + Setcolor(i, (R << 8) | (G << 4) | B); + } +} + +void Window_Init(void) { + DisplayInfo.Width = SCREEN_WIDTH; + DisplayInfo.Height = SCREEN_HEIGHT; + DisplayInfo.ScaleX = 0.5f; + DisplayInfo.ScaleY = 0.5f; + + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; + Window_Main.Focused = true; + + Window_Main.Exists = true; + Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; + Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; +} + +void Window_Free(void) { } + +void Window_Create2D(int width, int height) { +} + +void Window_Create3D(int width, int height) { +} + +void Window_Destroy(void) { } + +void Window_SetTitle(const cc_string* title) { } +void Clipboard_GetText(cc_string* value) { } +void Clipboard_SetText(const cc_string* value) { } + +int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; } +cc_result Window_EnterFullscreen(void) { return 0; } +cc_result Window_ExitFullscreen(void) { return 0; } +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } +void Window_SetSize(int width, int height) { } + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +void Window_ProcessEvents(float delta) { + +} + +void Cursor_SetPosition(int x, int y) { } // Makes no sense for PSP +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } + +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +void Gamepads_Init(void) { } + +void Gamepads_Process(float delta) { } + + +/*########################################################################################################################* +*------------------------------------------------------Framebuffer--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels"); + bmp->width = width; + bmp->height = height; +} + +// Each group of 16 pixels is interleaved across 4 bitplanes +struct GRWORD { UWORD plane1, plane2, plane3, plane4; }; + +// TODO should be done in assembly.. search up 'chunky to planar atari ST' +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO + UWORD* ptr = Physbase(); + Mem_Set(ptr, 0, 32000); + int idx = 0; + struct GRWORD* planes = (struct GRWORD*)ptr; + + for (int y = 0; y < r.height; y++) + { + BitmapCol* row = Bitmap_GetRow(bmp, y); + + for (int x = 0; x < r.width; x++, idx++) + { + // TODO optimise + BitmapCol col = row[x]; + cc_uint8 R = BitmapCol_R(col) >> 7; + cc_uint8 G = BitmapCol_G(col) >> 6; + cc_uint8 B = BitmapCol_B(col) >> 7; + + //int pal = R | (G << 1) | (B << 2); + int g1 = G & 0x01, g2 = (G >> 1); + + int word = idx >> 4, bit = 15 - (idx & 0x0F); + + planes[word].plane1 |= R << bit; + planes[word].plane2 |= B << bit; + planes[word].plane3 |= g1<< bit; + planes[word].plane4 |= g2<< bit; + } + } +} +/* +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO + UWORD* ptr = Physbase(); + + for (int y = 0; y < r.height; ++y) + { + BitmapCol* row = Bitmap_GetRow(bmp, y); + UWORD* src = ptr + 80 * y; + Mem_Set(src, 0, sizeof(UWORD) * 80); + + for (int x = 0; x < r.width; ++x) + { + // TODO optimise + BitmapCol col = row[x]; + cc_uint8 R = BitmapCol_R(col) >> 7; + cc_uint8 G = BitmapCol_G(col) >> 7; + cc_uint8 B = BitmapCol_B(col) >> 6; + + int idx = R | (G << 1) | (B << 2); + src[x] |= idx << ((x & 0x03) * 4); + } + } +} +*/ + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + + +/*########################################################################################################################* +*------------------------------------------------------Soft keyboard------------------------------------------------------* +*#########################################################################################################################*/ +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { +} + +void OnscreenKeyboard_SetText(const cc_string* text) { } + +void OnscreenKeyboard_Close(void) { +} + + +/*########################################################################################################################* +*-------------------------------------------------------Misc/Other--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_ShowDialog(const char* title, const char* msg) { + /* TODO implement */ + Platform_LogConst(title); + Platform_LogConst(msg); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/dreamcast/Audio_Dreamcast.c b/src/dreamcast/Audio_Dreamcast.c index 64250b926..71e5a3774 100644 --- a/src/dreamcast/Audio_Dreamcast.c +++ b/src/dreamcast/Audio_Dreamcast.c @@ -2,7 +2,12 @@ #include "../Audio.h" /* TODO needs way more testing, especially with sounds */ -static cc_bool valid_handles[SND_STREAM_MAX]; +#define HANDLE_STATE_UNUSED 0 +#define HANDLE_STATE_ALLOCATED 1 +#define HANDLE_STATE_PLAYABLE 2 +// Need to manually track playable state, to avoid triggering divide by zero when 0 channels in poll +// https://github.com/KallistiOS/KallistiOS/pull/1099 - but manually check this to support older toolchains +static cc_uint8 valid_handles[SND_STREAM_MAX]; struct AudioBuffer { int available; @@ -28,7 +33,7 @@ void AudioBackend_Tick(void) { // TODO is this really threadsafe with music? should this be done in Audio_Poll instead? for (int i = 0; i < SND_STREAM_MAX; i++) { - if (valid_handles[i]) snd_stream_poll(i); + if (valid_handles[i] == HANDLE_STATE_PLAYABLE) snd_stream_poll(i); } } @@ -70,7 +75,7 @@ cc_result Audio_Init(struct AudioContext* ctx, int buffers) { ctx->count = buffers; ctx->bufHead = 0; - valid_handles[ctx->hnd] = true; + valid_handles[ctx->hnd] = HANDLE_STATE_ALLOCATED; return 0; } @@ -78,7 +83,7 @@ void Audio_Close(struct AudioContext* ctx) { if (ctx->count) { snd_stream_stop(ctx->hnd); snd_stream_destroy(ctx->hnd); - valid_handles[ctx->hnd] = false; + valid_handles[ctx->hnd] = HANDLE_STATE_UNUSED; } ctx->hnd = SND_STREAM_INVALID; @@ -115,6 +120,7 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { cc_result Audio_Play(struct AudioContext* ctx) { snd_stream_start(ctx->hnd, ctx->sampleRate, ctx->channels == 2); + valid_handles[ctx->hnd] = HANDLE_STATE_PLAYABLE; return 0; } diff --git a/src/dreamcast/Graphics_Dreamcast.c b/src/dreamcast/Graphics_Dreamcast.c index 38f3d6ed8..061643559 100644 --- a/src/dreamcast/Graphics_Dreamcast.c +++ b/src/dreamcast/Graphics_Dreamcast.c @@ -718,7 +718,6 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f *-------------------------------------------------------Index buffers-----------------------------------------------------* *#########################################################################################################################*/ static void* gfx_vertices; -static int vb_size; GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { return (void*)1; @@ -743,15 +742,9 @@ void Gfx_DeleteVb(GfxResourceID* vb) { *vb = 0; } -void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; -} +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } -void Gfx_UnlockVb(GfxResourceID vb) { - gfx_vertices = vb; - //sceKernelDcacheWritebackInvalidateRange(vb, vb_size); -} +void Gfx_UnlockVb(GfxResourceID vb) { gfx_vertices = vb; } static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { @@ -760,15 +753,9 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; -} +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; - //dcache_flush_range(vb, vb_size); -} +void Gfx_UnlockDynamicVb(GfxResourceID vb) { gfx_vertices = vb; } void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } @@ -988,8 +975,34 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { /*########################################################################################################################* *-----------------------------------------------------------Misc----------------------------------------------------------* *#########################################################################################################################*/ +static BitmapCol* DC_GetRow(struct Bitmap* bmp, int y, void* ctx) { + BitmapCol* tmp = (BitmapCol*)ctx; + uint16_t* src = vram_s + vid_mode->width * y; + int r, g, b, width = bmp->width; + + for (int x = 0; x < width; x++) + { + int r, g, b; + // RGB565 to RGB888 + r = ((src[x] >> 11) & 0x1F) << 3; + g = ((src[x] >> 6) & 0x3F) << 2; + b = ((src[x] >> 0) & 0x1F) << 3; + + tmp[x] = BitmapColor_RGB(r, g, b); + } + return tmp; +} + cc_result Gfx_TakeScreenshot(struct Stream* output) { - return ERR_NOT_SUPPORTED; + BitmapCol tmp[1024]; + int width = vid_mode->width; + int height = vid_mode->height; + + struct Bitmap bmp; + bmp.width = width; + bmp.height = height; + + return Png_Encode(&bmp, output, DC_GetRow, false, tmp); } void Gfx_GetApiInfo(cc_string* info) { diff --git a/src/dreamcast/Platform_Dreamcast.c b/src/dreamcast/Platform_Dreamcast.c index f0ff07410..fe03ddebe 100644 --- a/src/dreamcast/Platform_Dreamcast.c +++ b/src/dreamcast/Platform_Dreamcast.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -141,6 +144,13 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *-------------------------------------------------------Crash handling----------------------------------------------------* *#########################################################################################################################*/ +static cc_string GetThreadName(void) { + kthread_t* thd = thd_get_current(); + if (!thd) return String_FromReadonly("(unknown)"); + + return String_FromRawArray(thd->label); +} + static void HandleCrash(irq_t evt, irq_context_t* ctx, void* data) { uint32_t code = evt; log_timestamp = false; @@ -149,9 +159,10 @@ static void HandleCrash(irq_t evt, irq_context_t* ctx, void* data) { for (;;) { + cc_string name = GetThreadName(); Platform_LogConst("** CLASSICUBE FATALLY CRASHED **"); - Platform_Log2("PC: %h, error: %h", - &ctx->pc, &code); + Platform_Log3("PC: %h, error: %h, thd: %s", + &ctx->pc, &code, &name); Platform_LogConst(""); static const char* const regNames[] = { @@ -319,6 +330,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int res = fs_mkdir(path->buffer); int err = res == -1 ? errno : 0; @@ -692,7 +705,7 @@ static void InitModem(void) { ppp_init(); Platform_LogConst("Dialling modem.. (can take ~20 seconds)"); - err = ppp_modem_init("111111111111", 0, NULL); + err = ppp_modem_init("111111111111", 1, NULL); if (err) { Platform_Log1("Establishing link failed (%i)", &err); return; } @@ -741,6 +754,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -752,3 +767,6 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/dreamcast/Window_Dreamcast.c b/src/dreamcast/Window_Dreamcast.c index 24f91dcdd..89fdb6554 100644 --- a/src/dreamcast/Window_Dreamcast.c +++ b/src/dreamcast/Window_Dreamcast.c @@ -222,6 +222,28 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_dc[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_SCREENSHOT] = { CCPAD_3 }, +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } @@ -264,7 +286,7 @@ static void HandleController(int port, bool dual_analog, cont_state_t* state, fl // TODO: verify values are right if(dual_analog) { - HandleJoystick(port, PAD_AXIS_LEFT, state->joyx, state->joyy, delta); + HandleJoystick(port, PAD_AXIS_LEFT, state->joyx, state->joyy, delta); HandleJoystick(port, PAD_AXIS_RIGHT, state->joy2x, state->joy2y, delta); } else @@ -287,7 +309,7 @@ void Gamepads_Process(float delta) { int dual_analog = cont_has_capabilities(cont, CONT_CAPABILITIES_DUAL_ANALOG); if(dual_analog == -1) dual_analog = 0; - int port = Gamepad_Connect(0xDC + i, PadBind_Defaults); + int port = Gamepad_Connect(0xDC + i, defaults_dc); HandleButtons(port, state->buttons); HandleController(port, dual_analog, state, delta); } diff --git a/src/gba/Platform_GBA.c b/src/gba/Platform_GBA.c index 8e20f8c22..553c4c1fb 100644 --- a/src/gba/Platform_GBA.c +++ b/src/gba/Platform_GBA.c @@ -1,3 +1,8 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -13,9 +18,6 @@ #include #include "gbadefs.h" -#define OVERRIDE_MEM_FUNCTIONS -#include "../_PlatformConsole.h" - #include "../../third_party/tinyalloc/tinyalloc.c" typedef volatile uint8_t vu8; @@ -31,24 +33,42 @@ const cc_result ReturnCode_SocketDropped = -1; const char* Platform_AppNameSuffix = " GBA"; cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunGame(); + } + + Window_Free(); + return 0; +} + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" MALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("MALLOCED: %x", &ptr); + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); return ptr; } void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" CALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("CALLOCED: %x", &ptr); + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); if (ptr) Mem_Set(ptr, 0, size); return ptr; @@ -70,12 +90,13 @@ static uint32_t GetTimerValues(void) { uint16_t lo = REG_TMR2_DATA; uint16_t hi = REG_TMR3_DATA; - // Did lo timer possibly overflow between reading lo and hi? + // Lo timer can possibly overflow between reading lo and hi uint16_t lo_again = REG_TMR2_DATA; uint16_t hi_again = REG_TMR3_DATA; + // Check if lo timer has overflowed if (lo_again < lo) { - // If so, use known safe timer read values instead + // If so, use known stable timer read values instead lo = lo_again; hi = hi_again; } @@ -180,6 +201,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ERR_NOT_SUPPORTED; } @@ -238,80 +261,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { //swiDelay(8378 * milliseconds); // TODO probably wrong } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* @@ -348,3 +297,21 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { _exit(code); } + diff --git a/src/gba/Window_GBA.c b/src/gba/Window_GBA.c index 4ddc77685..ca7df6f6a 100644 --- a/src/gba/Window_GBA.c +++ b/src/gba/Window_GBA.c @@ -85,12 +85,29 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping pad_defaults[BIND_COUNT] = { + [BIND_LOOK_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_LOOK_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_LOOK_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_LOOK_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_FORWARD] = { CCPAD_UP, 0 }, + [BIND_BACK] = { CCPAD_DOWN, 0 }, + [BIND_LEFT] = { CCPAD_LEFT, 0 }, + [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, + [BIND_JUMP] = { CCPAD_1, 0 }, + [BIND_INVENTORY] = { CCPAD_R, CCPAD_UP }, + [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, + [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_HOTBAR_LEFT] = { CCPAD_L, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_L, CCPAD_RIGHT } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x5BA, PadBind_Defaults); + int port = Gamepad_Connect(0x5BA, pad_defaults); int mods = ~REG_KEYINPUT; Gamepad_SetButton(port, CCPAD_L, mods & KEY_L); @@ -125,7 +142,6 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { } void Window_FreeFramebuffer(struct Bitmap* bmp) { - Mem_Free(bmp->scan0); } diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index 822c035f2..1c889ec19 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -6,6 +6,7 @@ #include #include #include +#include "gx_gpu.h" static void* fifo_buffer; #define FIFO_SIZE (256 * 1024) @@ -60,6 +61,7 @@ void Gfx_Create(void) { Gfx.MaxTexWidth = 1024; Gfx.MaxTexHeight = 1024; Gfx.MaxTexSize = 512 * 512; + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; Gfx.MinTexWidth = 4; Gfx.MinTexHeight = 4; @@ -77,7 +79,7 @@ void Gfx_Free(void) { } cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 4x4 dummy white texture (textures must be at least 1 4x4 tile) @@ -88,7 +90,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } @@ -109,50 +111,74 @@ typedef struct CCTexture_ { // GX RGBA8 textures // - store pixels in 4x4 tiles // - store all of the AR values of the tile's pixels, then store all of the GB values +// +// http://hitmen.c02.at/files/yagcd/yagcd/chap15.html +// section 15.35 TPL (Texture Palette) +// "RGBA8 (4x4 tiles in two cache lines - first is AR and second is GB" +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, + unsigned* maskX, unsigned* maskY) { + *maskX = 0b00011; // 2 linear X bits, 1 bit until next block + *maskY = 0b01100; // 2 linear Y bits, 1 bit until next block + + // Adjust for lower 2 X and 2 Y linear bits + w >>= 3; + h >>= 3; + int shift = 5; + + for (; w > 0; w >>= 1) { + *maskX += 0x01 << shift; + shift += 1; + } + + for (; h > 0; h >>= 1) { + *maskY += 0x01 << shift; + shift += 1; + } +} + static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp, int originX, int originY, int rowWidth) { - int stride = GX_GetTexObjWidth(&tex->obj) * 4; - // TODO not really right - // TODO originX ignored - originX &= ~0x03; - originY &= ~0x03; - - // http://hitmen.c02.at/files/yagcd/yagcd/chap15.html - // section 15.35 TPL (Texture Palette) - // "RGBA8 (4x4 tiles in two cache lines - first is AR and second is GB" - uint8_t *src = (uint8_t*)bmp->scan0; - uint8_t *dst = (uint8_t*)tex->pixels + stride * originY; - int srcWidth = bmp->width, srcHeight = bmp->height; - - for (int tileY = 0; tileY < srcHeight; tileY += 4) - for (int tileX = 0; tileX < srcWidth; tileX += 4) + int src_w = bmp->width, dst_w = GX_GetTexObjWidth(&tex->obj); + int src_h = bmp->height, dst_h = GX_GetTexObjHeight(&tex->obj); + + cc_uint16* dst_AR = (cc_uint16*)tex->pixels; + cc_uint16* dst_GB = (cc_uint16*)tex->pixels + 16; // offset by a 4x4 block + cc_uint32* src = bmp->scan0; + + unsigned maskX, maskY; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + unsigned begX = 0, begY = 0; + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { begX = (begX - maskX) & maskX; } + for (int y = 0; y < originY; y++) { begY = (begY - maskY) & maskY; } + + unsigned Y = begY; + for (int y = 0; y < src_h; y++) { - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - uint32_t idx = (((tileY + y) * rowWidth) + tileX + x) << 2; - - *dst++ = src[idx + 0]; // A - *dst++ = src[idx + 1]; // R - } - } - - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - uint32_t idx = (((tileY + y) * rowWidth) + tileX + x) << 2; - - *dst++ = src[idx + 2]; // G - *dst++ = src[idx + 3]; // B - } + unsigned X = begX; + for (int x = 0; x < src_w; x++) + { + BitmapCol c = src[x]; + dst_AR[X | Y] = (BitmapCol_A(c) << 8) | BitmapCol_R(c); + dst_GB[X | Y] = (BitmapCol_G(c) << 8) | BitmapCol_B(c); + + X = (X - maskX) & maskX; } + Y = (Y - maskY) & maskY; + src += rowWidth; } } GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + int size = dst_w * dst_h * 4; CCTexture* tex = (CCTexture*)memalign(32, 32 + size); if (!tex) return NULL; - GX_InitTexObj(&tex->obj, tex->pixels, bmp->width, bmp->height, + GX_InitTexObj(&tex->obj, tex->pixels, dst_w, dst_h, GX_TF_RGBA8, GX_REPEAT, GX_REPEAT, GX_FALSE); GX_InitTexObjFilterMode(&tex->obj, GX_NEAR, GX_NEAR); @@ -163,7 +189,6 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { CCTexture* tex = (CCTexture*)texId; - // TODO: wrong behaviour if x/y/part isn't multiple of 4 pixels ReorderPixels(tex, part, x, y, rowWidth); GX_InvalidateTexAll(); } @@ -245,7 +270,8 @@ static BitmapCol* GCWii_GetRow(struct Bitmap* bmp, int y, void* ctx) { int blockXStride = (4 * 4) * 4; // 16 pixels per tile // Do the inverse of converting from 4x4 tiled to linear - for (u32 x = 0; x < bmp->width; x++) + int width = bmp->width; + for (u32 x = 0; x < width; x++) { int tileY = y >> 2, tileX = x >> 2; int locY = y & 0x3, locX = x & 0x3; @@ -527,7 +553,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { GX_LoadProjectionMtx(dst, tmp[3*4+3] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC); } else { - GX_LoadPosMtxImm(dst, GX_PNMTX0); + XF_SetMatrix_3x4((GX_matrix_3x4*)&dst, XF_POS_MATRIX0); } } @@ -540,12 +566,12 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma static float texOffsetX, texOffsetY; static void UpdateTexCoordGen(void) { if (texOffsetX || texOffsetY) { - Mtx mat = { 0 }; + GX_matrix_2x4 mat = { 0 }; // https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml - mat[0][0] = 1; mat[0][3] = texOffsetX; - mat[1][1] = 1; mat[1][3] = texOffsetY; + mat.m[0][0] = 1; mat.m[0][3] = texOffsetX; + mat.m[1][1] = 1; mat.m[1][3] = texOffsetY; - GX_LoadTexMtxImm(mat, GX_TEXMTX0, GX_MTX2x4); + XF_SetMatrix_2x4(&mat, XF_TEX_MATRIX0); GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0); } else { GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); @@ -611,8 +637,8 @@ static void Draw_ColouredTriangles(int verticesCount, int startVertex) { { struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; - GX_Position3f32(v->x, v->y, v->z); - GX_Color1u32(v->Col); + FIFO_PUSH_F32x3(v->x, v->y, v->z); + FIFO_PUSH_U32(v->Col); } } @@ -622,9 +648,9 @@ static void Draw_TexturedTriangles(int verticesCount, int startVertex) { { struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; - GX_Position3f32(v->x, v->y, v->z); - GX_Color1u32(v->Col); - GX_TexCoord2f32(v->U, v->V); + FIFO_PUSH_F32x3(v->x, v->y, v->z); + FIFO_PUSH_U32(v->Col); + FIFO_PUSH_F32x2(v->U, v->V); } } diff --git a/src/gcwii/Platform_GCWii.c b/src/gcwii/Platform_GCWii.c index 11d73737e..291aab862 100644 --- a/src/gcwii/Platform_GCWii.c +++ b/src/gcwii/Platform_GCWii.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -45,10 +48,6 @@ cc_bool Platform_ReadonlyFilesystem; /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ -// To see these log messages: -// 1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu -// 2) Make sure "OSReport EXI (OSREPORT)" log type is enabled -// 3) In the UI, make sure 'Show log' checkbox is checked in View menu static void LogOverEXI(char* msg, int len) { u32 cmd = 0x80000000 | (0x800400 << 6); // write flag, UART base address @@ -139,6 +138,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return ENOSYS; @@ -629,6 +630,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -644,3 +647,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/gcwii/Window_GCWii.c b/src/gcwii/Window_GCWii.c index 2fe333169..87556db8a 100644 --- a/src/gcwii/Window_GCWii.c +++ b/src/gcwii/Window_GCWii.c @@ -111,6 +111,23 @@ void Window_RequestClose(void) { *#########################################################################################################################*/ static PADStatus gc_pads[PAD_CHANMAX]; +static const BindMapping defaults_gc[BIND_COUNT] = { + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, +}; + #define PAD_AXIS_SCALE 8.0f static void ProcessPAD_Joystick(int port, int axis, int x, int y, float delta) { // May not be exactly 0 on actual hardware @@ -149,7 +166,7 @@ static void ProcessPADInput(PADStatus* pad, int i, float delta) { return; // not connected, still busy, etc } - int port = Gamepad_Connect(0x5C + i, PadBind_Defaults); + int port = Gamepad_Connect(0x5C + i, defaults_gc); ProcessPAD_Buttons(port, gc_pads[i].button); ProcessPAD_Joystick(port, PAD_AXIS_LEFT, gc_pads[i].stickX, gc_pads[i].stickY, delta); ProcessPAD_Joystick(port, PAD_AXIS_RIGHT, gc_pads[i].substickX, gc_pads[i].substickY, delta); diff --git a/src/gcwii/gx_gpu.h b/src/gcwii/gx_gpu.h new file mode 100644 index 000000000..47cfb2641 --- /dev/null +++ b/src/gcwii/gx_gpu.h @@ -0,0 +1,132 @@ +// https://patents.google.com/patent/US6618048 +// https://patents.google.com/patent/US6639595B1 - general +// https://patents.google.com/patent/US6700586 - Transform Functions (XF) unit mostly +// https://patents.google.com/patent/US7002591 - general +// https://patents.google.com/patent/US6697074 - Command Processor (CP) unit + opcodes +// https://patents.google.com/patent/US7995069B2 - Blitter Processor (BP) unit +// https://patents.google.com/patent/US20070165043A1 - FIFO unit +// https://patents.google.com/patent/US7034828B1 - some texture functions +// https://patents.google.com/patent/US6664962B1 - some texture functions +// yet another gamecube documentation +// dolphin headers + +typedef struct { float m[4][4]; } GX_matrix_4x4; +typedef struct { float m[3][4]; } GX_matrix_3x4; +typedef struct { float m[2][4]; } GX_matrix_2x4; + +#define ENTRIES_2x4 8 +#define ENTRIES_3x4 12 +#define ENTRIES_4x4 16 + + +/*########################################################################################################################* +*----------------------------------------------------FIFO functionality---------------------------------------------------* +*#########################################################################################################################*/ +#define FIFO_PUSH_I32(value) wgPipe->I32 = value; +#define FIFO_PUSH_F32(value) wgPipe->F32 = value; +#define FIFO_PUSH_U32(value) wgPipe->U32 = value; + +#define FIFO_PUSH_U8(value) wgPipe->U8 = value; + +#define FIFO_PUSH_F32x2(x, y) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); +#define FIFO_PUSH_F32x3(x, y, z) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); FIFO_PUSH_F32(z); +#define FIFO_PUSH_F32x4(x, y, z, w) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); FIFO_PUSH_F32(z); FIFO_PUSH_F32(w); + +#define FIFO_PUSH_MTX_2x4(mtx) \ + FIFO_PUSH_F32x4(mtx->m[0][0], mtx->m[0][1], mtx->m[0][2], mtx->m[0][3]); \ + FIFO_PUSH_F32x4(mtx->m[1][0], mtx->m[1][1], mtx->m[1][2], mtx->m[1][3]); \ + +#define FIFO_PUSH_MTX_3x4(mtx) \ + FIFO_PUSH_F32x4(mtx->m[0][0], mtx->m[0][1], mtx->m[0][2], mtx->m[0][3]); \ + FIFO_PUSH_F32x4(mtx->m[1][0], mtx->m[1][1], mtx->m[1][2], mtx->m[1][3]); \ + FIFO_PUSH_F32x4(mtx->m[2][0], mtx->m[2][1], mtx->m[2][2], mtx->m[2][3]); \ + + +/*########################################################################################################################* +*------------------------------------------------Command processor commands-----------------------------------------------* +*#########################################################################################################################*/ +enum { + // No operation + CP_CMD_NOP = 0x00, + // Loads Command Processor register + CP_CMD_LOAD_CP_REG = 0x08, + // Loads Transform Unit register(s) + CP_CMD_LOAD_XF_REGS = 0x10, + // Runs all commands in a display list + CP_CMD_CALL_DISPLIST = 0x40, + // Loads Blitting Processor register + CP_CMD_LOAD_BP_REG = 0x61, + // Primitive command types + CP_CMD_PRIM_BASE = 0x80, + // TODO missing indexed + stat commands +}; + +#define GX_NOP() \ + FIFO_PUSH_U8(CP_CMD_NOP); + +#define GX_LOAD_XF_REGISTERS(start_reg, num_regs) \ + FIFO_PUSH_U8(CP_CMD_LOAD_XF_REGS); \ + FIFO_PUSH_U32( ((((num_regs) - 1) & 0xFFFF) << 16) | (start_reg) ); \ + + +/*########################################################################################################################* +*-----------------------------------------------Transform Function registers----------------------------------------------* +*#########################################################################################################################*/ +enum { + // https://www.gc-forever.com/yagcd/chap5.html#sec5.11.3 + // 256 floats -> 64 rows of 4xFloats -> ~21 entries of 3x4Matrices + XF_REG_BASE_MATRICES_BEG = 0x0000, + XF_REG_BASE_MATRICES_END = 0x0100, + #define XF_REG_BASE_MATRIX(idx) XF_REG_BASE_MATRICES_BEG + ((idx) * ENTRIES_3x4) +}; + +/*########################################################################################################################* +*-----------------------------------------------Transform Function commands-----------------------------------------------* +*#########################################################################################################################*/ +typedef enum { + XF_BASE_MATRIX00, XF_BASE_MATRIX01, XF_BASE_MATRIX02, + XF_BASE_MATRIX03, XF_BASE_MATRIX04, XF_BASE_MATRIX05, + XF_BASE_MATRIX06, XF_BASE_MATRIX07, XF_BASE_MATRIX08, + XF_BASE_MATRIX09, XF_BASE_MATRIX10, XF_BASE_MATRIX11, + XF_BASE_MATRIX12, XF_BASE_MATRIX13, XF_BASE_MATRIX14, + XF_BASE_MATRIX15, XF_BASE_MATRIX16, XF_BASE_MATRIX17, + XF_BASE_MATRIX18, XF_BASE_MATRIX19, XF_BASE_MATRIX20, + + // Default mapping, allocate first 10 matrices for positions + // (that way can use the same index as a corresponding normal matrix) + XF_POS_MATRIX0 = XF_BASE_MATRIX00, + XF_POS_MATRIX1 = XF_BASE_MATRIX01, + XF_POS_MATRIX2 = XF_BASE_MATRIX02, + XF_POS_MATRIX3 = XF_BASE_MATRIX03, + XF_POS_MATRIX4 = XF_BASE_MATRIX04, + XF_POS_MATRIX5 = XF_BASE_MATRIX05, + XF_POS_MATRIX6 = XF_BASE_MATRIX06, + XF_POS_MATRIX7 = XF_BASE_MATRIX07, + XF_POS_MATRIX8 = XF_BASE_MATRIX08, + XF_POS_MATRIX9 = XF_BASE_MATRIX09, + + // Default mapping, allocate rest of matrices for textures + // (avoids overlapping with position matrices) + XF_TEX_MATRIX0 = XF_BASE_MATRIX10, + XF_TEX_MATRIX1 = XF_BASE_MATRIX11, + XF_TEX_MATRIX2 = XF_BASE_MATRIX12, + XF_TEX_MATRIX3 = XF_BASE_MATRIX13, + XF_TEX_MATRIX4 = XF_BASE_MATRIX14, + XF_TEX_MATRIX5 = XF_BASE_MATRIX15, + XF_TEX_MATRIX6 = XF_BASE_MATRIX16, + XF_TEX_MATRIX7 = XF_BASE_MATRIX17, + XF_TEX_MATRIX8 = XF_BASE_MATRIX18, + XF_TEX_MATRIX9 = XF_BASE_MATRIX19, +} XF_BASE_MATRIX_INDEX; + +static CC_INLINE void XF_SetMatrix_3x4(const GX_matrix_3x4* matrix, XF_BASE_MATRIX_INDEX index) +{ + GX_LOAD_XF_REGISTERS(XF_REG_BASE_MATRIX(index), ENTRIES_3x4); + FIFO_PUSH_MTX_3x4(matrix); +} + +static CC_INLINE void XF_SetMatrix_2x4(const GX_matrix_2x4* matrix, XF_BASE_MATRIX_INDEX index) +{ + GX_LOAD_XF_REGISTERS(XF_REG_BASE_MATRIX(index), ENTRIES_2x4); + FIFO_PUSH_MTX_2x4(matrix); +} diff --git a/src/msdos/Platform_MSDOS.c b/src/msdos/Platform_MSDOS.c index 56fc5ba13..60b3c1d22 100644 --- a/src/msdos/Platform_MSDOS.c +++ b/src/msdos/Platform_MSDOS.c @@ -1,3 +1,8 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -126,9 +131,9 @@ void Process_Abort2(cc_result result, const char* raw_msg) { #define US_PER_SEC 1000000ULL cc_uint64 Stopwatch_Measure(void) { - struct timeval cur; - gettimeofday(&cur, NULL); - return (cc_uint64)cur.tv_sec * US_PER_SEC + cur.tv_usec; + struct timeval cur; + gettimeofday(&cur, NULL); + return (cc_uint64)cur.tv_sec * US_PER_SEC + cur.tv_usec; } cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { @@ -259,73 +264,6 @@ cc_result File_Length(cc_file file, cc_uint32* len) { *#########################################################################################################################*/ void Thread_Sleep(cc_uint32 milliseconds) { usleep(milliseconds * 1000); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { } - -void Thread_Join(void* handle) { } - -void* Mutex_Create(const char* name) { return NULL; } - -void Mutex_Free(void* handle) { } - -void Mutex_Lock(void* handle) { } - -void Mutex_Unlock(void* handle) { } - -void* Waitable_Create(const char* name) { return NULL; } - -void Waitable_Free(void* handle) { } - -void Waitable_Signal(void* handle) { } - -void Waitable_Wait(void* handle) { } - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { } - - -/*########################################################################################################################* -*--------------------------------------------------------Font/Text--------------------------------------------------------* -*#########################################################################################################################*/ -void Platform_LoadSysFonts(void) { } - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* @@ -343,50 +281,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; - -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dll"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/Graphics_NDS.c b/src/nds/Graphics_NDS.c similarity index 95% rename from src/Graphics_NDS.c rename to src/nds/Graphics_NDS.c index 285cccba2..414a7afd3 100644 --- a/src/Graphics_NDS.c +++ b/src/nds/Graphics_NDS.c @@ -1,11 +1,9 @@ -#include "Core.h" -#ifdef CC_BUILD_NDS -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Logger.h" -#include "Window.h" +#include "../_GraphicsBase.h" +#include "../Errors.h" +#include "../Logger.h" +#include "../Window.h" #include -#include "_BlockAlloc.h" +#include "../_BlockAlloc.h" #define DS_MAT_PROJECTION 0 #define DS_MAT_POSITION 1 @@ -833,5 +831,4 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { if (skipRendering) return; Draw_TexturedTriangles(verticesCount, startVertex); } -#endif diff --git a/src/Platform_NDS.c b/src/nds/Platform_NDS.c similarity index 90% rename from src/Platform_NDS.c rename to src/nds/Platform_NDS.c index a9a10dffd..49e9ad220 100644 --- a/src/Platform_NDS.c +++ b/src/nds/Platform_NDS.c @@ -1,16 +1,16 @@ -#include "Core.h" -#if defined CC_BUILD_NDS +#define CC_NO_UPDATER +#define CC_NO_DYNLIB #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "Options.h" -#include "Animations.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../Options.h" +#include "../Animations.h" #include #include @@ -31,7 +31,7 @@ #include #include #ifdef BUILD_DSI -#include "../third_party/dsiwifi/include/dsiwifi9.h" +#include #else #include #endif @@ -40,7 +40,7 @@ #include #include #include -#include "_PlatformConsole.h" +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; // not used const cc_result ReturnCode_FileNotFound = ENOENT; @@ -56,8 +56,25 @@ cc_bool Platform_ReadonlyFilesystem; /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ -static u32 last_raw; -static u64 base_time; +static uint32_t last_raw; +static uint64_t base_time; + +static uint32_t GetTimerValues(void) { + uint16_t lo = TIMER_DATA(0); + uint16_t hi = TIMER_DATA(1); + + // Lo timer can possibly overflow between reading lo and hi + uint16_t lo_again = TIMER_DATA(0); + uint16_t hi_again = TIMER_DATA(1); + + // Check if lo timer has overflowed + if (lo_again < lo) { + // If so, use known stable timer read values instead + lo = lo_again; + hi = hi_again; + } + return lo | (hi << 16); +} cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; @@ -66,7 +83,7 @@ cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { } cc_uint64 Stopwatch_Measure(void) { - u32 raw = cpuGetTiming(); + uint32_t raw = GetTimerValues(); // Since counter is only a 32 bit integer, it overflows after a minute or two if (last_raw > 0xF0000000 && raw < 0x10000000) { base_time += 0x100000000ULL; @@ -76,6 +93,20 @@ cc_uint64 Stopwatch_Measure(void) { return base_time + raw; } +static void Stopwatch_Init(void) { + // Turn off both timers + TIMER_CR(0) = 0; + TIMER_CR(1) = 0; + + // Reset timer values to 0 + TIMER_DATA(0) = 0; + TIMER_DATA(1) = 0; + + // Turn on timer 1, with timer 1 incrementing timer 0 on overflow + TIMER_CR(1) = TIMER_CASCADE | TIMER_ENABLE; + TIMER_CR(0) = TIMER_ENABLE; +} + static void LogNocash(const char* msg, int len) { // Can only be up to 120 bytes total char buffer[120]; @@ -185,6 +216,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return 0; @@ -511,13 +544,8 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { if (res || *writable) return res; /* https://stackoverflow.com/questions/29479953/so-error-value-after-successful-socket-operation */ -#ifdef BUILD_DSI socklen_t resultSize = sizeof(socklen_t); getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize); -#else - int resultSize = sizeof(int); - getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize); -#endif return res; } @@ -588,7 +616,7 @@ void Platform_Init(void) { InitFilesystem(); InitNetworking(); - cpuStartTiming(1); + Stopwatch_Init(); } void Platform_Free(void) { } @@ -614,6 +642,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -624,4 +654,8 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } -#endif + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/Window_NDS.c b/src/nds/Window_NDS.c similarity index 87% rename from src/Window_NDS.c rename to src/nds/Window_NDS.c index f722b6ff4..c8907a1ad 100644 --- a/src/Window_NDS.c +++ b/src/nds/Window_NDS.c @@ -1,16 +1,14 @@ -#include "Core.h" -#if defined CC_BUILD_NDS -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "Graphics.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Camera.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Camera.h" #include #include #include @@ -256,13 +254,34 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* -*#########################################################################################################################*/ +*#########################################################################################################################*/ +static const BindMapping defaults_nds[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0xD5, PadBind_Defaults); + int port = Gamepad_Connect(0xD5, defaults_nds); int mods = keysDown() | keysHeld(); Gamepad_SetButton(port, CCPAD_L, mods & KEY_L); @@ -379,4 +398,4 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { return ERR_NOT_SUPPORTED; } -#endif + diff --git a/src/ps1/Graphics_PS1.c b/src/ps1/Graphics_PS1.c index ac73191e4..94b5a3b43 100644 --- a/src/ps1/Graphics_PS1.c +++ b/src/ps1/Graphics_PS1.c @@ -154,7 +154,7 @@ static void SetupContexts(int w, int h) { static GfxResourceID white_square; static cc_bool cullingEnabled; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // dummy texture (grey works better in menus than white) @@ -164,7 +164,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/ps1/Platform_PS1.c b/src/ps1/Platform_PS1.c index 0f96bc8d7..4cb69485e 100644 --- a/src/ps1/Platform_PS1.c +++ b/src/ps1/Platform_PS1.c @@ -1,4 +1,9 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -106,6 +111,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ERR_NOT_SUPPORTED; } @@ -167,80 +174,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { ChangeClearPAD(0); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* @@ -264,6 +197,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -275,3 +210,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/ps1/Window_PS1.c b/src/ps1/Window_PS1.c index 71f69ab90..41952b1fc 100644 --- a/src/ps1/Window_PS1.c +++ b/src/ps1/Window_PS1.c @@ -142,22 +142,22 @@ static const BindMapping pad_defaults[BIND_COUNT] = { [BIND_LOOK_DOWN] = { CCPAD_4, CCPAD_DOWN }, [BIND_LOOK_LEFT] = { CCPAD_4, CCPAD_LEFT }, [BIND_LOOK_RIGHT] = { CCPAD_4, CCPAD_RIGHT }, - [BIND_FORWARD] = { CCPAD_UP, 0 }, - [BIND_BACK] = { CCPAD_DOWN, 0 }, - [BIND_LEFT] = { CCPAD_LEFT, 0 }, - [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, - [BIND_JUMP] = { CCPAD_1, 0 }, - [BIND_SET_SPAWN] = { CCPAD_START, 0 }, - [BIND_INVENTORY] = { CCPAD_3, 0 }, + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, - [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, - [BIND_HOTBAR_LEFT] = { CCPAD_ZL, 0 }, - [BIND_HOTBAR_RIGHT] = { CCPAD_ZR, 0 } + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } }; static char pad_buff[2][34]; diff --git a/src/ps2/Graphics_PS2.c b/src/ps2/Graphics_PS2.c index aeb5ef898..22b586973 100644 --- a/src/ps2/Graphics_PS2.c +++ b/src/ps2/Graphics_PS2.c @@ -46,7 +46,7 @@ static qword_t* Q; static GfxResourceID white_square; static int primitive_type; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 4x4 dummy white texture @@ -57,7 +57,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } @@ -434,15 +434,14 @@ static void ConvertTexture_Palette(cc_uint8* dst, struct Bitmap* bmp, int rowWid static int Log2Dimension(int len) { return Math_ilog2(Math_NextPowOf2(len)); } -GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; - struct GPUTexture* tex = (struct GPUTexture*)memalign(16, 32 + size); - +static void GPUTexture_Init(struct GPUTexture* tex, struct Bitmap* bmp) { tex->width = bmp->width; tex->height = bmp->height; tex->log2_w = Log2Dimension(bmp->width); tex->log2_h = Log2Dimension(bmp->height); +} +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { BitmapCol palette[MAX_PAL_4BPP_ENTRIES] QWORD_ALIGNED; int pal_count = 0; int pal_index = -1; @@ -460,6 +459,10 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, //Platform_Log4("%i, c%i (%i x %i)", &pal_index, &pal_count, &bmp->width, &bmp->height); if (pal_index >= 0) { + struct GPUTexture* tex = memalign(16, 32 + bmp->width * bmp->height); + if (!tex) return 0; + GPUTexture_Init(tex, bmp); + tex->format = GS_PSM_4; tex->pal_index = pal_index; ConvertTexture_Palette((cc_uint8*)tex->pixels, bmp, rowWidth, palette, pal_count); @@ -490,7 +493,12 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, UploadToVRAM(tex, TEXMEM_4BPP_TO_VRAM(base)); return realloc(tex, sizeof(struct GPUTexture)); } + return tex; } else { + struct GPUTexture* tex = memalign(16, 32 + bmp->width * bmp->height * 4); + if (!tex) return 0; + GPUTexture_Init(tex, bmp); + tex->format = GS_PSM_32; CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, @@ -500,8 +508,8 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, // TODO fix properly. alignup instead //int blocks = SIZE_TO_BLOCKS(size, TEXMEM_BLOCK_SIZE); size = blocks / (2048 / 64); //Platform_Log4("32BPP: b %i / p %i (%i X %i)", &size, &blocks, &bmp->width, &bmp->height); + return tex; } - return tex; } static void UpdateTextureBuffer(int context, struct GPUTexture* tex, unsigned buf_addr) { diff --git a/src/ps2/Platform_PS2.c b/src/ps2/Platform_PS2.c index 1e43b9dce..14b0e0df3 100644 --- a/src/ps2/Platform_PS2.c +++ b/src/ps2/Platform_PS2.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -150,6 +153,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return fioMkdir(path->buffer); } @@ -748,6 +753,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -759,3 +766,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/ps2/Window_PS2.c b/src/ps2/Window_PS2.c index a421c3f93..990f0444d 100644 --- a/src/ps2/Window_PS2.c +++ b/src/ps2/Window_PS2.c @@ -227,6 +227,27 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_ps2[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static char padBuf0[256] __attribute__((aligned(64))); static char padBuf1[256] __attribute__((aligned(64))); @@ -299,7 +320,7 @@ static void ProcessPad(int i, float delta) { int ret = padRead(i, 0, &pad); if (ret == 0) return; - int port = Gamepad_Connect(0x503 + i, PadBind_Defaults); + int port = Gamepad_Connect(0x503 + i, defaults_ps2); ProcessPadInput(port, delta, &pad); } diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index b1f635be6..bfecf1303 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -6,13 +6,11 @@ #include #include #include +#include "rsx_gpu.h" static gcmContextData* context; static u32 cur_fb; -#define CB_SIZE 0x100000 // TODO: smaller command buffer? -#define HOST_SIZE (32 * 1024 * 1024) - /*########################################################################################################################* *----------------------------------------------------- Vertex Shaders ----------------------------------------------------* @@ -101,7 +99,7 @@ static void FP_Load(FragmentProgram* fp, const u8* source) { fp->buffer = (u32*)rsxMemalign(128, size); Mem_Copy(fp->buffer, fp->ucode, size); - rsxAddressToOffset(fp->buffer, &fp->offset); + gcmAddressToOffset(fp->buffer, &fp->offset); } static void LoadFragmentPrograms(void) { @@ -132,34 +130,49 @@ static u32 depth_offset; static u32* depth_buffer; #define GCM_LABEL_INDEX 255 -static u32 slabelval = 1; +static u32 labelID = 1; + +#define CB_SIZE (1024 * 1024) // TODO: smaller command buffer? +#define HOST_SIZE (32 * 1024 * 1024) + +#define uint_to_ptr(raw) ((void*)((uintptr_t)(raw))) +#define ptr_to_uint(raw) ((uint32_t)((uintptr_t)(raw))) +extern s32 gcmInitBodyEx(uint32_t ctx, uint32_t cbSize, uint32_t ioSize, uint32_t ioBuf); static void CreateContext(void) { - void* host_addr = memalign(1024 * 1024, HOST_SIZE); - rsxInit(&context, CB_SIZE, HOST_SIZE, host_addr); + void* host_buf = memalign(1024 * 1024, HOST_SIZE); + + // PS3 pointers are 32 bits in size, but our pointers are 64 bits + uint32_t ctx_ptr = 0; + int res = gcmInitBodyEx(ptr_to_uint(&ctx_ptr), CB_SIZE, HOST_SIZE, ptr_to_uint(host_buf)); + if (res) Process_Abort2(res, "gcmInitBody failed"); + + context = uint_to_ptr(ctx_ptr); + rsxHeapInit(); } static void WaitRSXFinish(void) { - rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, slabelval); + rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, labelID); rsxFlushBuffer(context); - while (*(vu32*)gcmGetLabelAddress(GCM_LABEL_INDEX) != slabelval) + while (*(vu32*)gcmGetLabelAddress(GCM_LABEL_INDEX) != labelID) usleep(30); - slabelval++; + labelID++; } static void WaitRSXIdle(void) { - rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, slabelval); - rsxSetWaitLabel(context, GCM_LABEL_INDEX, slabelval); + rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, labelID); + rsxSetWaitLabel(context, GCM_LABEL_INDEX, labelID); - slabelval++; + labelID++; WaitRSXFinish(); } static void ConfigureVideo(void) { - videoState state; WaitRSXIdle(); + + videoState state; videoGetState(0, 0, &state); videoConfiguration vconfig = { 0 }; @@ -179,7 +192,7 @@ static void AllocColorSurface(u32 i) { color_pitch = DisplayInfo.Width * 4; color_buffer[i] = (u32*)rsxMemalign(64, DisplayInfo.Height * color_pitch); - rsxAddressToOffset(color_buffer[i], &color_offset[i]); + gcmAddressToOffset(color_buffer[i], &color_offset[i]); gcmSetDisplayBuffer(i, color_offset[i], color_pitch, DisplayInfo.Width, DisplayInfo.Height); } @@ -188,7 +201,7 @@ static void AllocDepthSurface(void) { depth_pitch = DisplayInfo.Width * 4; depth_buffer = (u32*)rsxMemalign(64, DisplayInfo.Height * depth_pitch); - rsxAddressToOffset(depth_buffer, &depth_offset); + gcmAddressToOffset(depth_buffer, &depth_offset); } @@ -269,7 +282,7 @@ cc_bool Gfx_TryRestoreContext(void) { return true; } cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -279,7 +292,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } @@ -287,7 +300,7 @@ void Gfx_FreeState(void) { u32* Gfx_AllocImage(u32* offset, s32 w, s32 h) { u32* pixels = (u32*)rsxMemalign(64, w * h * 4); - rsxAddressToOffset(pixels, offset); + gcmAddressToOffset(pixels, offset); return pixels; } @@ -305,11 +318,11 @@ void Gfx_TransferImage(u32 offset, s32 w, s32 h) { static cc_uint32 clearColor; void Gfx_SetFaceCulling(cc_bool enabled) { - rsxSetCullFaceEnable(context, enabled); + RSX_set_cull_face(context, enabled); } static void SetAlphaBlend(cc_bool enabled) { - rsxSetBlendEnable(context, enabled); + RSX_set_alpha_blend(context, enabled); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } @@ -322,25 +335,19 @@ void Gfx_ClearColor(PackedCol color) { } void Gfx_SetDepthWrite(cc_bool enabled) { - rsxSetDepthWriteEnable(context, enabled); + RSX_set_depth_write(context, enabled); } void Gfx_SetDepthTest(cc_bool enabled) { - rsxSetDepthTestEnable(context, enabled); + RSX_set_depth_test(context, enabled); } static void SetAlphaTest(cc_bool enabled) { - rsxSetAlphaTestEnable(context, enabled); + RSX_set_alpha_test(context, enabled); } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - unsigned mask = 0; - if (r) mask |= GCM_COLOR_MASK_R; - if (g) mask |= GCM_COLOR_MASK_G; - if (b) mask |= GCM_COLOR_MASK_B; - if (a) mask |= GCM_COLOR_MASK_A; - - rsxSetColorMask(context, mask); + RSX_set_color_write_mask(context, r, g, b, a); } void Gfx_DepthOnlyRendering(cc_bool depthOnly) { @@ -414,9 +421,9 @@ static void ResetFrameState(void) { rsxSetClearColor(context, clearColor); rsxSetClearDepthStencil(context, 0xFFFFFFFF); - rsxSetDepthFunc(context, GCM_LEQUAL); - rsxSetDepthWriteEnable(context, true); - rsxSetDepthTestEnable(context, true); + RSX_set_depth_func(context, GCM_LEQUAL); + RSX_set_depth_write(context, true); + RSX_set_depth_test(context, true); rsxSetUserClipPlaneControl(context, GCM_USER_CLIP_PLANE_DISABLE, GCM_USER_CLIP_PLANE_DISABLE, @@ -447,11 +454,7 @@ void Gfx_BeginFrame(void) { } void Gfx_ClearBuffers(GfxBuffers buffers) { - int targets = 0; - if (buffers & GFX_BUFFER_COLOR) targets |= (GCM_CLEAR_R | GCM_CLEAR_G | GCM_CLEAR_B | GCM_CLEAR_A); - if (buffers & GFX_BUFFER_DEPTH) targets |= (GCM_CLEAR_S | GCM_CLEAR_Z); - - rsxClearSurface(context, targets); + RSX_clear_buffers(context, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); } void Gfx_EndFrame(void) { @@ -483,16 +486,10 @@ void Gfx_SetViewport(int x, int y, int w, int h) { offset[3] = 0.0f; rsxSetViewport(context, x, y, w, h, zmin, zmax, scale, offset); - - // TODO: even needed? - for (int i = 0; i < 8; i++) - { - rsxSetViewportClip(context, i, w, h); - } } void Gfx_SetScissor(int x, int y, int w, int h) { - rsxSetScissor(context, x, y, w, h); + RSX_set_scissor_rect(context, x, y, w, h); } @@ -502,7 +499,7 @@ void Gfx_SetScissor(int x, int y, int w, int h) { static int vb_size; GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - return 1;/* TODO */ + return (void*)1; } void Gfx_BindIb(GfxResourceID ib) { } @@ -518,7 +515,7 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { void Gfx_BindVb(GfxResourceID vb) { u32 offset; - rsxAddressToOffset(vb, &offset); + gcmAddressToOffset(vb, &offset); if (gfx_format == VERTEX_FORMAT_TEXTURED) { rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_POS, 0, offset, @@ -644,7 +641,7 @@ void Gfx_BindTexture(GfxResourceID texId) { /* TODO */ u32 offset; - rsxAddressToOffset(tex->pixels, &offset); + gcmAddressToOffset(tex->pixels, &offset); gcmTexture texture; texture.format = GCM_TEXTURE_FORMAT_A8R8G8B8 | GCM_TEXTURE_FORMAT_SWZ; diff --git a/src/ps3/Platform_PS3.c b/src/ps3/Platform_PS3.c index 28c8a4b70..f3043337d 100644 --- a/src/ps3/Platform_PS3.c +++ b/src/ps3/Platform_PS3.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -60,10 +63,14 @@ TimeMS DateTime_CurrentUTC(void) { } void DateTime_CurrentLocal(struct cc_datetime* t) { - struct timeval cur; + time_t cur_sec; struct tm loc_time; - gettimeofday(&cur, NULL); - localtime_r(&cur.tv_sec, &loc_time); + + u64 sec, nsec; + sysGetCurrentTime(&sec, &nsec); + + cur_sec = sec; + localtime_r(&cur_sec, &loc_time); t->year = loc_time.tm_year + 1900; t->month = loc_time.tm_mon + 1; @@ -113,6 +120,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -482,6 +491,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -492,3 +503,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/ps3/Window_PS3.c b/src/ps3/Window_PS3.c index ffd5f702c..68078be90 100644 --- a/src/ps3/Window_PS3.c +++ b/src/ps3/Window_PS3.c @@ -271,6 +271,27 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_ps3[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static padInfo pad_info; static padData pad_data[MAX_PORT_NUM]; static cc_bool circle_main; @@ -333,7 +354,7 @@ void Gamepads_Process(float delta) { if (!pad_info.status[i]) continue; ioPadGetData(i, &pad_data[i]); - int port = Gamepad_Connect(0x503 + i, PadBind_Defaults); + int port = Gamepad_Connect(0x503 + i, defaults_ps3); ProcessPadInput(port, delta, &pad_data[i]); } } diff --git a/src/ps3/rsx_gpu.h b/src/ps3/rsx_gpu.h new file mode 100644 index 000000000..acea10951 --- /dev/null +++ b/src/ps3/rsx_gpu.h @@ -0,0 +1,132 @@ +/*########################################################################################################################* +*-----------------------------------------------------GPU commands--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: shared with nv2a (Xbox) GPU +#define RSX_MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) + +// disables the default increment behaviour when writing multiple registers +// E.g. with RSX_3D_COMMAND(cmd, 4): +// - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 +// - disable: REG = v1, REG = v2, REG = v3, REG = v4 +#define RSX_WRITE_SAME_REGISTER 0x40000000 + +#define RSX_COMMAND(subchan, cmd, num_params) (((num_params) << 18) | ((subchan) << 13) | (cmd)) +#define RSX_3D_COMMAND(cmd, num_params) RSX_COMMAND(0, cmd, num_params) + +#include + + +/*########################################################################################################################* +*---------------------------------------------------GPU command buffer----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* RSX_reserve(gcmContextData* ctx, int count) { + if (ctx->current + count > ctx->end) { + // This flushes the command buffer to GPU via DMA + // TODO: returns 0 if fails, but not checked for?? + rsxContextCallback(ctx, count); + } + + uint32_t* p = ctx->current; + ctx->current += count; + return p; +} + +static CC_INLINE uint32_t* RSX_reserve_command(gcmContextData* context, uint32_t cmd, int num_params) { + uint32_t* p = RSX_reserve(context, num_params + 1); + *p++ = RSX_3D_COMMAND(cmd, num_params); + return p; +} + +#define RSX_append_single_command(context, cmd, value) \ + uint32_t* p = RSX_reserve_command(ctx, cmd, 1); \ + *p++ = value; + + +/*########################################################################################################################* +*-----------------------------------------------------Raster control------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_set_scissor_rect(gcmContextData* ctx, int x, int y, int w, int h) { + // NV40TCL_SCISSOR_HORIZ, then NV40TCL_SCISSOR_VERTI + uint32_t* p = RSX_reserve_command(ctx, NV40TCL_SCISSOR_HORIZ, 2); + *p++ = x | (w << 16); + *p++ = y | (h << 16); +} + +static CC_INLINE void RSX_set_color_write_mask(gcmContextData* ctx, int r, int g, int b, int a) { + uint32_t mask = 0; + if (r) mask |= GCM_COLOR_MASK_R; + if (g) mask |= GCM_COLOR_MASK_G; + if (b) mask |= GCM_COLOR_MASK_B; + if (a) mask |= GCM_COLOR_MASK_A; + + RSX_append_single_command(ctx, NV40TCL_COLOR_MASK, mask); +} + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_set_depth_write(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_WRITE_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_depth_test(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_TEST_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_depth_func(gcmContextData* ctx, int func) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_FUNC, func); +} + + +static CC_INLINE void RSX_set_alpha_test(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_alpha_test_func(gcmContextData* ctx, int func) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_FUNC, func); +} + +static CC_INLINE void RSX_set_alpha_test_ref(gcmContextData* ctx, int ref) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_REF, ref); +} + + +static CC_INLINE void RSX_set_alpha_blend(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_BLEND_ENABLE, enabled); +} + + +static CC_INLINE void RSX_set_cull_face(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_CULL_FACE_ENABLE, enabled); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex attributes---------------------------------------------------* +*#########################################################################################################################*/ +/*static CC_INLINE void RSX_set_vertex_attrib_format(gcmContextData* ctx, int attrib, int format, int size, int stride) { + uint32_t mask = + RSX_MASK(NV40TCL_VTXFMT_TYPE_MASK, format) | + RSX_MASK(NV40TCL_VTXFMT_SIZE_MASK, size) | + RSX_MASK(NV40TCL_VTXFMT_STRIDE_MASK, stride); + + RSX_append_single_command(ctx, NV40TCL_VTXFMT(attrib), mask); +} + +// NOTE: GCM_LOCATION_RSX implicitly assumed for location +static CC_INLINE void RSX_set_vertex_attrib_pointer(gcmContextData* ctx, int attrib, uint32_t addr) { + RSX_append_single_command(ctx, NV40TCL_VTXBUF_ADDRESS(attrib), addr); +}*/ + + +/*########################################################################################################################* +*------------------------------------------------------Buffer clearing----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_clear_buffers(gcmContextData* ctx, int color, int depth) { + uint32_t targets = 0; + if (color) targets |= (GCM_CLEAR_R | GCM_CLEAR_G | GCM_CLEAR_B | GCM_CLEAR_A); + if (depth) targets |= (GCM_CLEAR_S | GCM_CLEAR_Z); + + RSX_append_single_command(ctx, NV40TCL_CLEAR_BUFFERS, targets); +} diff --git a/src/Platform_PS4.c b/src/ps4/Platform_PS4.c similarity index 88% rename from src/Platform_PS4.c rename to src/ps4/Platform_PS4.c index fa0f99546..c7f1677a9 100644 --- a/src/Platform_PS4.c +++ b/src/ps4/Platform_PS4.c @@ -1,16 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_PS4 - #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" + #include #include #include @@ -31,7 +32,7 @@ #include #include #include -#include "_PlatformConsole.h" +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const cc_result ReturnCode_FileNotFound = ENOENT; @@ -39,7 +40,6 @@ const cc_result ReturnCode_DirectoryExists = EEXIST; const cc_result ReturnCode_SocketInProgess = EINPROGRESS; const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; const cc_result ReturnCode_SocketDropped = EPIPE; -#define SUPPORTS_GETADDRINFO 1 const char* Platform_AppNameSuffix = " PS4"; cc_bool Platform_ReadonlyFilesystem; @@ -113,6 +113,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -180,25 +182,15 @@ static cc_result File_Do(cc_file* file, const char* path, int mode) { } cc_result File_Open(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDONLY); -#else - return File_Do(file, path->buffer, O_RDONLY | O_BINARY); -#endif } + cc_result File_Create(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_TRUNC); -#else - return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_TRUNC | O_BINARY); -#endif } + cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDWR | O_CREAT); -#else - return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_BINARY); -#endif } cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { @@ -375,12 +367,6 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { } -/*########################################################################################################################* -*--------------------------------------------------------Font/Text--------------------------------------------------------* -*#########################################################################################################################*/ -void Platform_LoadSysFonts(void) { } - - /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ @@ -490,27 +476,6 @@ void Socket_Close(cc_socket s) { close(s); } -#if defined CC_BUILD_DARWIN || defined CC_BUILD_BEOS -/* poll is broken on old OSX apparently https://daniel.haxx.se/docs/poll-vs-select.html */ -/* BeOS lacks support for poll */ -static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { - fd_set set; - struct timeval time = { 0 }; - int selectCount; - - FD_ZERO(&set); - FD_SET(s, &set); - - if (mode == SOCKET_POLL_READ) { - selectCount = select(s + 1, &set, NULL, NULL, &time); - } else { - selectCount = select(s + 1, NULL, &set, NULL, &time); - } - - if (selectCount == -1) { *success = false; return errno; } - *success = FD_ISSET(s, &set) != 0; return 0; -} -#else #include static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { struct pollfd pfd; @@ -525,7 +490,6 @@ static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { *success = (pfd.revents & flags) != 0; return 0; } -#endif cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { return Socket_Poll(s, SOCKET_POLL_READ, readable); @@ -569,6 +533,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + void Platform_Init(void) { Platform_LogConst("initing 2.."); } @@ -583,4 +549,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } -#endif + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/Window_PS4.c b/src/ps4/Window_PS4.c similarity index 91% rename from src/Window_PS4.c rename to src/ps4/Window_PS4.c index e11de6415..a19792b1b 100644 --- a/src/Window_PS4.c +++ b/src/ps4/Window_PS4.c @@ -1,17 +1,15 @@ -#include "Core.h" -#if defined CC_BUILD_PS4 -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "Graphics.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Logger.h" -#include "VirtualKeyboard.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Logger.h" +#include "../VirtualKeyboard.h" #include static cc_bool launcherMode; @@ -152,4 +150,3 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { return ERR_NOT_SUPPORTED; } -#endif diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index 3c5902df1..6a9eda4d1 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -9,6 +9,7 @@ #include #include #include +#include "ge_gpu.h" #define BUFFER_WIDTH 512 #define SCREEN_WIDTH 480 @@ -17,7 +18,9 @@ #define FB_SIZE (BUFFER_WIDTH * SCREEN_HEIGHT * 4) static unsigned int __attribute__((aligned(16))) list[262144]; -#define GE_CMD_TEXTUREMAPENABLE 0x1E +static cc_uint8* gfx_vertices; +static int gfx_fields; + /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* @@ -26,13 +29,11 @@ static int formatFields[] = { GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_3D, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D }; -static ScePspFMatrix4 identity; static void guInit(void) { void* framebuffer0 = (void*)0; void* framebuffer1 = (void*)FB_SIZE; void* depthbuffer = (void*)(FB_SIZE + FB_SIZE); - Mem_Copy(&identity, &Matrix_Identity, sizeof(ScePspFMatrix4)); sceGuInit(); sceGuStart(GU_DIRECT, list); @@ -53,8 +54,7 @@ static void guInit(void) { sceGuClearDepth(65535); // sceGuClearDepth(0); sceGuDepthRange(0, 65535); // sceGuDepthRange(65535, 0); - - sceGuSetMatrix(GU_MODEL, &identity); + GE_upload_world_matrix((const float*)&Matrix_Identity); sceGuColor(0xffffffff); sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); sceGuDisable(GU_SCISSOR_TEST); @@ -63,7 +63,7 @@ static void guInit(void) { sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); sceGuFinish(); - sceGuSync(0,0); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); } @@ -74,6 +74,7 @@ void Gfx_Create(void) { Gfx.MaxTexWidth = 512; Gfx.MaxTexHeight = 512; + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; Gfx.Created = true; gfx_vsync = true; @@ -86,7 +87,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -96,13 +97,86 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } #define GU_Toggle(cap) if (enabled) { sceGuEnable(cap); } else { sceGuDisable(cap); } + + +/*########################################################################################################################* +*---------------------------------------------------------Swizzling-------------------------------------------------------* +*#########################################################################################################################*/ +// PSP swizzled textures are 16 bytes X 8 rows = 4 '32 bit' pixels X 8 rows +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) { + *maskX = 0b00011; // 2 linear X bits + *maskY = 0b11100; // 3 linear Y bits + + // Adjust for lower 2 X and 2 Y linear bits + w >>= 3; + h >>= 4; + int shift = 5; + + for (; w > 0; w >>= 1) { + *maskX += 0x01 << shift; + shift += 1; + } + + for (; h > 0; h >>= 1) { + *maskY += 0x01 << shift; + shift += 1; + } +} + +static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) { + int src_w = bmp->width, src_h = bmp->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = bmp->scan0 + y * rowWidth; + X = 0; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + +static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h, + int originX, int originY) { + int src_w = part->width, src_h = part->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } + for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } + unsigned startX = X; + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = part->scan0 + y * rowWidth; + X = startX; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + + /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ @@ -113,38 +187,29 @@ typedef struct CCTexture_ { } CCTexture; GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + // Swizzled texture assumes at least 16 bytes x 8 rows + int size = max(16 * 8, dst_w * dst_h * 4); CCTexture* tex = (CCTexture*)memalign(16, 16 + size); - tex->width = bmp->width; - tex->height = bmp->height; + tex->width = dst_w; + tex->height = dst_h; - CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, - bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, - bmp->width, bmp->height); + UploadFullTexture(bmp, rowWidth, tex->pixels, dst_w, dst_h); return tex; } void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { CCTexture* tex = (CCTexture*)texId; - BitmapCol* dst = (tex->pixels + x) + y * tex->width; + UploadPartialTexture(part, rowWidth, tex->pixels, tex->width, tex->height, x, y); - CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, - part->scan0, rowWidth * BITMAPCOLOR_SIZE, - part->width, part->height); // TODO: Do line by line and only invalidate the actually changed parts of lines? - sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4); + // TODO: Invalidate full tex->size in case of very small textures? + sceKernelDcacheWritebackInvalidateRange(tex->pixels, (tex->width * tex->height) * 4); } -/*void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { - CCTexture* tex = (CCTexture*)texId; - cc_uint32* dst = (tex->pixels + x) + y * tex->width; - - for (int yy = 0; yy < part->height; yy++) { - Mem_Copy(dst + (y + yy) * tex->width, part->scan0 + yy * rowWidth, part->width * 4); - } -}*/ - void Gfx_DeleteTexture(GfxResourceID* texId) { GfxResourceID data = *texId; if (data) Mem_Free(data); @@ -158,7 +223,7 @@ void Gfx_BindTexture(GfxResourceID texId) { CCTexture* tex = (CCTexture*)texId; if (!tex) tex = white_square; - sceGuTexMode(GU_PSM_8888,0,0,0); + sceGuTexMode(GU_PSM_8888, 0, 0, 1); sceGuTexImage(0, tex->width, tex->height, tex->width, tex->pixels); } @@ -188,7 +253,7 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { } void Gfx_SetDepthWrite(cc_bool enabled) { - sceGuDepthMask(enabled ? 0 : 0xffffffff); + sceGuDepthMask(enabled ? 0 : 0xffffffff); } void Gfx_SetDepthTest(cc_bool enabled) { GU_Toggle(GU_DEPTH_TEST); } @@ -274,11 +339,13 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { if (buffers & GFX_BUFFER_DEPTH) targets |= GU_DEPTH_BUFFER_BIT; sceGuClear(targets); + // Clear involves draw commands + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_EndFrame(void) { sceGuFinish(); - sceGuSync(0, 0); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); if (gfx_vsync) sceDisplayWaitVblankStart(); sceGuSwapBuffers(); @@ -290,10 +357,6 @@ void Gfx_SetViewport(int x, int y, int w, int h) { } void Gfx_SetScissor (int x, int y, int w, int h) { } -static cc_uint8* gfx_vertices; -static int gfx_fields; - - /*########################################################################################################################* *----------------------------------------------------------Buffers--------------------------------------------------------* *#########################################################################################################################*/ @@ -305,7 +368,10 @@ GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { return gfx_indices; } -void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_BindIb(GfxResourceID ib) { + // TODO doesn't work properly + //GE_set_index_buffer(ib); +} void Gfx_DeleteIb(GfxResourceID* ib) { } @@ -394,12 +460,14 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) { /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ -static int matrix_modes[] = { GU_PROJECTION, GU_VIEW }; -static ScePspFMatrix4 tmp_matrix; // 16 byte aligned - void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { - Mem_Copy(&tmp_matrix, matrix, sizeof(ScePspFMatrix4)); - sceGuSetMatrix(matrix_modes[type], &tmp_matrix); + const float* m = (const float*)matrix; + + if (type == MATRIX_PROJ) { + GE_upload_proj_matrix(m); + } else { + GE_upload_view_matrix(m); + } } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { @@ -435,23 +503,28 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { } else { sceGuDisable(GU_TEXTURE_2D); } + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_DrawVb_Lines(int verticesCount) { - sceGuDrawArray(GU_LINES, gfx_fields, verticesCount, NULL, gfx_vertices); + // More efficient to set "indexed 16 bit" as default in Gfx_SetVertexFormat, + // rather than in every single triangle draw command + GE_set_vertex_format(gfx_fields); + sceGuDrawArray(GU_LINES, 0, verticesCount, NULL, gfx_vertices); + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices + startVertex * gfx_stride); } void Gfx_DrawVb_IndexedTris(int verticesCount) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices); } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED); } diff --git a/src/psp/Platform_PSP.c b/src/psp/Platform_PSP.c index adf48ab32..d66c390ae 100644 --- a/src/psp/Platform_PSP.c +++ b/src/psp/Platform_PSP.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -34,7 +37,10 @@ cc_bool Platform_ReadonlyFilesystem; PSP_MODULE_INFO("ClassiCube", PSP_MODULE_USER, 1, 0); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); -PSP_DISABLE_AUTOSTART_PTHREAD() // reduces .elf size by 140 kb +// Save 140 kb by not linking in pthreads +PSP_DISABLE_AUTOSTART_PTHREAD() +// Save 70kb by not linking in sprintf/setenv code etc +PSP_DISABLE_NEWLIB_TIMEZONE_SUPPORT() /*########################################################################################################################* @@ -107,6 +113,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { #define GetSCEResult(result) (result >= 0 ? 0 : result & 0xFFFF) +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int result = sceIoMkdir(path->buffer, 0777); return GetSCEResult(result); @@ -483,6 +491,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -493,3 +503,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/psp/Window_PSP.c b/src/psp/Window_PSP.c index ef2b6f5d3..652503976 100644 --- a/src/psp/Window_PSP.c +++ b/src/psp/Window_PSP.c @@ -83,6 +83,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_psp[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; @@ -125,7 +146,7 @@ static void ProcessCircleInput(int port, SceCtrlData* pad, float delta) { } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x503, PadBind_Defaults); + int port = Gamepad_Connect(0x503, defaults_psp); SceCtrlData pad; /* TODO implement */ diff --git a/src/psp/ge_gpu.h b/src/psp/ge_gpu.h new file mode 100644 index 000000000..80478b46e --- /dev/null +++ b/src/psp/ge_gpu.h @@ -0,0 +1,81 @@ +#include "../Funcs.h" + +// https://github.com/pspdev/pspsdk/blob/c84807b8503fdf031d089cc0c6363d2d87715974/src/gu/doc/commands.txt +// Hacky way to access GU's command buffer +extern struct GuDisplayListInternal +{ + unsigned int* start; + unsigned int* current; +} *gu_list; + +enum GE_COMMANDS { + GE_NOP = 0x00, + GE_SET_VB_ADDR = 0x01, + GE_SET_IB_ADDR = 0x02, + GE_SET_BASE_ADDR = 0x10, + GE_SET_VERTEX_FORMAT = 0x12, + GE_WORLDMATRIX_UPLOAD_INDEX = 0x3A, + GE_WORLDMATRIX_UPLOAD_DATA = 0x3B, + GE_VIEW_MATRIX_UPLOAD_INDEX = 0x3C, + GE_VIEW_MATRIX_UPLOAD_DATA = 0x3D, + GE_PROJ_MATRIX_UPLOAD_INDEX = 0x3E, + GE_PROJ_MATRIX_UPLOAD_DATA = 0x3F, + + GE_SET_DEPTH_MASK = 0xE7, + GE_SET_COLOR_MASK = 0xE8, + GE_SET_ALPHA_MASK = 0xE9, +}; + + +// upper 8 bits are opcode, lower 24 bits are argument +#define GE_OPCODE_SHIFT 24 +static CC_INLINE void GE_PushI(int cmd, int argument) { + *(gu_list->current++) = (cmd << GE_OPCODE_SHIFT) | (argument & 0xffffff); +} + +static CC_INLINE void GE_PushF(int cmd, float argument) { + union IntAndFloat raw; raw.f = argument; + *(gu_list->current++) = (cmd << GE_OPCODE_SHIFT) | (raw.u >> 8); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Matrix upload-------------------------------------------------------* +*#########################################################################################################################*/ +static void GE_upload_world_matrix(const float* matrix) { + GE_PushI(GE_WORLDMATRIX_UPLOAD_INDEX, 0); // uploading all 3x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 3; j++) + { + GE_PushF(GE_WORLDMATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} + +static void GE_upload_view_matrix(const float* matrix) { + GE_PushI(GE_VIEW_MATRIX_UPLOAD_INDEX, 0); // uploading all 3x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 3; j++) + { + GE_PushF(GE_VIEW_MATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} + +static void GE_upload_proj_matrix(const float* matrix) { + GE_PushI(GE_PROJ_MATRIX_UPLOAD_INDEX, 0); // uploading all 4x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + { + GE_PushF(GE_PROJ_MATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} + + +/*########################################################################################################################* +*----------------------------------------------------Vertex drawing-------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void GE_set_vertex_format(int format) { + GE_PushI(GE_SET_VERTEX_FORMAT, format); +} diff --git a/src/psvita/Graphics_PSVita.c b/src/psvita/Graphics_PSVita.c index 0b40def54..d2ba2025c 100644 --- a/src/psvita/Graphics_PSVita.c +++ b/src/psvita/Graphics_PSVita.c @@ -588,7 +588,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -599,7 +599,7 @@ void Gfx_RestoreState(void) { // TODO } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } @@ -673,9 +673,12 @@ static void GPUTextures_DeleteUnreferenced(void) { } } + +/*########################################################################################################################* +*---------------------------------------------------------Swizzling-------------------------------------------------------* +*#########################################################################################################################*/ // See Graphics_Dreamcast.c for twiddling explanation -static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, - unsigned* maskX, unsigned* maskY) { +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) { *maskX = 0; *maskY = 0; int shift = 0; @@ -699,18 +702,7 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, } } - -/*########################################################################################################################* -*---------------------------------------------------------Textures--------------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int dst_w = Math_NextPowOf2(bmp->width); - int dst_h = Math_NextPowOf2(bmp->height); - int size = dst_w * dst_h * 4; - - struct GPUTexture* tex = GPUTexture_Alloc(size); - cc_uint32* dst = tex->data; - +static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) { int src_w = bmp->width, src_h = bmp->height; unsigned maskX, maskY; unsigned X = 0, Y = 0; @@ -728,6 +720,46 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, } Y = (Y - maskY) & maskY; } +} + +static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h, + int originX, int originY) { + int src_w = part->width, src_h = part->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } + for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } + unsigned startX = X; + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = part->scan0 + y * rowWidth; + X = startX; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + int size = dst_w * dst_h * 4; + + struct GPUTexture* tex = GPUTexture_Alloc(size); + cc_uint32* dst = tex->data; + UploadFullTexture(bmp, rowWidth, dst, dst_w, dst_h); sceGxmTextureInitSwizzled(&tex->texture, dst, SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, dst_w, dst_h, 0); @@ -741,33 +773,12 @@ void Gfx_UpdateTexture(GfxResourceID texId, int originX, int originY, struct Bit struct GPUTexture* tex = (struct GPUTexture*)texId; int texWidth = sceGxmTextureGetWidth(&tex->texture); int texHeight = sceGxmTextureGetHeight(&tex->texture); - cc_uint32* dst = tex->data; - - int width = part->width, height = part->height; - unsigned maskX, maskY; - unsigned X = 0, Y = 0; - TwiddleCalcFactors(texWidth, texHeight, &maskX, &maskY); - // Calculate start twiddled X and Y values - for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } - for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } - unsigned startX = X; - - for (int y = 0; y < height; y++) - { - cc_uint32* src = part->scan0 + rowWidth * y; - X = startX; - - for (int x = 0; x < width; x++, src++) - { - dst[X | Y] = *src; - X = (X - maskX) & maskX; - } - Y = (Y - maskY) & maskY; - } + cc_uint32* dst = tex->data; + UploadPartialTexture(part, rowWidth, dst, texWidth, texHeight, originX, originY); // TODO: is it necessary to invalidate? probably just everything? - //sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4); + //sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * tex->height) * 4); } void Gfx_DeleteTexture(GfxResourceID* texId) { diff --git a/src/psvita/Platform_PSVita.c b/src/psvita/Platform_PSVita.c index 1bd5b9103..caa4023f9 100644 --- a/src/psvita/Platform_PSVita.c +++ b/src/psvita/Platform_PSVita.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -90,6 +93,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { #define GetSCEResult(result) (result >= 0 ? 0 : result & 0xFFFF) +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int result = sceIoMkdir(path->buffer, 0777); return GetSCEResult(result); @@ -439,6 +444,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -450,3 +457,6 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/psvita/Window_PSVita.c b/src/psvita/Window_PSVita.c index eb4d09c05..4648ddfb2 100644 --- a/src/psvita/Window_PSVita.c +++ b/src/psvita/Window_PSVita.c @@ -141,21 +141,21 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ -static const BindMapping vita_padbinds[BIND_COUNT] = { - [BIND_JUMP] = { CCPAD_1 }, - [BIND_SET_SPAWN] = { CCPAD_START }, - [BIND_CHAT] = { CCPAD_4 }, - [BIND_INVENTORY] = { CCPAD_3 }, - [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_SPEED] = { CCPAD_2, CCPAD_L }, - [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, - [BIND_FLY] = { CCPAD_2, CCPAD_R }, - [BIND_PLACE_BLOCK] = { CCPAD_L }, - [BIND_DELETE_BLOCK] = { CCPAD_R }, - [BIND_FLY_UP] = { CCPAD_UP }, - [BIND_FLY_DOWN] = { CCPAD_DOWN }, - [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, +static const BindMapping defaults_vita[BIND_COUNT] = { + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, [BIND_HOTBAR_RIGHT] = { CCPAD_RIGHT }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, }; static cc_bool circle_main; @@ -207,7 +207,7 @@ static void ProcessCircleInput(int port, int axis, int x, int y, float delta) { } static void ProcessPadInput(float delta) { - int port = Gamepad_Connect(0x503, vita_padbinds); + int port = Gamepad_Connect(0x503, defaults_vita); SceCtrlData pad; // sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that diff --git a/src/saturn/Graphics_Saturn.c b/src/saturn/Graphics_Saturn.c index ceb733911..4699c5691 100644 --- a/src/saturn/Graphics_Saturn.c +++ b/src/saturn/Graphics_Saturn.c @@ -96,7 +96,7 @@ static void CalcGouraudColours(void) { } static GfxResourceID white_square; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); struct Bitmap bmp; @@ -107,7 +107,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 4c8cd4f33..bdc901afb 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -1,4 +1,9 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -91,29 +96,31 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -static volatile cc_uint32 overflow_count; +#include "sh2_wdt.h" + +static void Stopwatch_Init(void) { + wdt_stop(); + + wdt_set_irq_number(CPU_INTC_INTERRUPT_WDT_ITI); + wdt_set_irq_priority(15); + cpu_intc_ihr_set(CPU_INTC_INTERRUPT_WDT_ITI, wdt_handler); + + wdt_enable(); +} cc_uint64 Stopwatch_Measure(void) { - return cpu_frt_count_get() + (overflow_count * 65536); + return wdt_total_ticks(); } +#define US_PER_SEC 1000000 +#define NTSC_320_CLOCK 26846587 + cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - cc_uint32 delta = end - beg; + cc_uint64 delta = end - beg; - // TODO still wrong?? and overflows?? and PAL detection ??? - return (delta * 1000) / CPU_FRT_NTSC_320_128_COUNT_1MS; -} - -static void ovf_handler(void) { overflow_count++; } - -static void Stopwatch_Init(void) { - //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); - cpu_frt_init(CPU_FRT_CLOCK_DIV_128); - cpu_frt_ovi_set(ovf_handler); - - cpu_frt_interrupt_priority_set(15); - cpu_frt_count_set(0); + // TODO still wrong?? PAL detection ??? + return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 1024); } @@ -135,6 +142,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ReturnCode_DirectoryExists; } @@ -197,80 +206,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { } } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* @@ -296,6 +231,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -306,3 +243,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/saturn/Window_Saturn.c b/src/saturn/Window_Saturn.c index c4ee28a94..c08a333f5 100644 --- a/src/saturn/Window_Saturn.c +++ b/src/saturn/Window_Saturn.c @@ -109,8 +109,8 @@ static const BindMapping saturn_defaults[BIND_COUNT] = { [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_DELETE_BLOCK] = { CCPAD_L, 0 }, - [BIND_PLACE_BLOCK] = { CCPAD_R, 0 } + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, }; void Gamepads_Init(void) { diff --git a/src/saturn/sh2_wdt.h b/src/saturn/sh2_wdt.h new file mode 100644 index 000000000..c1c0e4a51 --- /dev/null +++ b/src/saturn/sh2_wdt.h @@ -0,0 +1,73 @@ +static cc_uint32 wdt_overflows; + +// Interrupt Priority Request A +#define SH2_REG_IPRA ((volatile uint16_t *)0xFFFFFEE2) +#define SH2_IPRA_WDT_NUM 4 + +// Vector Number Setting Register WDT +#define SH2_REG_VCRWDT ((volatile uint16_t *)0xFFFFFEE4) +#define SH2_VCRWDT_NUM 8 + +// Watchdog Timer Counter +#define SH2_REG_WTCNT_R ((volatile uint8_t *)0xFFFFFE81) +#define SH2_REG_WTCNT_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCNT(val) (0x5A00 | (uint8_t)(val)) + +// Watchdog Timer Control/Status Register +#define SH2_REG_WTCSR_R ((volatile uint8_t *)0xFFFFFE80) +#define SH2_REG_WTCSR_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCSR(val) (0xA500 | (uint8_t)(val)) + +#define SH2_WTCSR_CLOCK_DIV_2 0 +#define SH2_WTCSR_CLOCK_DIV_64 1 +#define SH2_WTCSR_CLOCK_DIV_128 2 +#define SH2_WTCSR_CLOCK_DIV_256 3 +#define SH2_WTCSR_CLOCK_DIV_512 4 +#define SH2_WTCSR_CLOCK_DIV_1024 5 +#define SH2_WTCSR_CLOCK_DIV_4096 6 +#define SH2_WTCSR_CLOCK_DIV_8192 7 + +#define SH2_WTCSR_ENA_FLG 0x20 +#define SH2_WTCSR_OVF_FLG 0x80 + + +static CC_INLINE void wdt_set_irq_number(int irq_num) { + uint16_t vcrwdt = *SH2_REG_VCRWDT; + vcrwdt &= ~( 0x7F << SH2_VCRWDT_NUM); + vcrwdt |= (irq_num << SH2_VCRWDT_NUM); + + *SH2_REG_VCRWDT = vcrwdt; +} + +static CC_INLINE void wdt_set_irq_priority(uint8_t pri) { + uint16_t ipra = *SH2_REG_IPRA; + ipra &= ~(0xF << SH2_IPRA_WDT_NUM); + ipra |= (pri << SH2_IPRA_WDT_NUM); + + *SH2_REG_IPRA = ipra; +} + + +void __attribute__((interrupt_handler)) wdt_handler(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); + wdt_overflows++; +} + +static CC_INLINE void wdt_stop(void) { + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(SH2_WTCSR_CLOCK_DIV_1024); +} + +static CC_INLINE void wdt_enable(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + wtcr |= SH2_WTCSR_ENA_FLG; + // interval mode is 0 anyways + + *SH2_REG_WTCNT_W = SH2_CMD_WTCNT(0); + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); +} + +static CC_INLINE uint32_t wdt_total_ticks(void) { + return (*SH2_REG_WTCNT_R) | (wdt_overflows << 8); +} diff --git a/src/switch/Platform_Switch.c b/src/switch/Platform_Switch.c index 7cabda845..364bf2a1c 100644 --- a/src/switch/Platform_Switch.c +++ b/src/switch/Platform_Switch.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -128,6 +131,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, 0) == -1 ? errno : 0; } @@ -530,6 +535,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -541,3 +548,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/switch/Window_Switch.c b/src/switch/Window_Switch.c index 4521cb94a..25e168f9b 100644 --- a/src/switch/Window_Switch.c +++ b/src/switch/Window_Switch.c @@ -147,13 +147,36 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_switch[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } static void HandleButtons(int port, u64 mods) { - Gamepad_SetButton(port, CCPAD_L, mods & HidNpadButton_L); - Gamepad_SetButton(port, CCPAD_R, mods & HidNpadButton_R); + Gamepad_SetButton(port, CCPAD_L, mods & HidNpadButton_L); + Gamepad_SetButton(port, CCPAD_R, mods & HidNpadButton_R); + Gamepad_SetButton(port, CCPAD_ZL, mods & HidNpadButton_ZL); + Gamepad_SetButton(port, CCPAD_ZR, mods & HidNpadButton_ZR); Gamepad_SetButton(port, CCPAD_1, mods & HidNpadButton_A); Gamepad_SetButton(port, CCPAD_2, mods & HidNpadButton_B); @@ -179,7 +202,7 @@ static void ProcessJoystickInput(int port, int axis, HidAnalogStickState* pos, f } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x51C, PadBind_Defaults); + int port = Gamepad_Connect(0x51C, defaults_switch); u64 keys = padGetButtons(&pad); HandleButtons(port, keys); diff --git a/src/Audio_WiiU.c b/src/wiiu/Audio_WiiU.c similarity index 94% rename from src/Audio_WiiU.c rename to src/wiiu/Audio_WiiU.c index f3e38a1e2..7bff38766 100644 --- a/src/Audio_WiiU.c +++ b/src/wiiu/Audio_WiiU.c @@ -1,12 +1,9 @@ -#include "Core.h" - -#if defined CC_BUILD_WIIU #include -static cc_bool ax_inited; struct AudioContext { int count; }; -#include "_AudioBase.h" +#include "../_AudioBase.h" +static cc_bool ax_inited; cc_bool AudioBackend_Init(void) { if (ax_inited) return true; @@ -114,5 +111,4 @@ cc_result SoundContext_PollBusy(struct AudioContext* ctx, cc_bool* isBusy) { cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { return false; } -#endif diff --git a/src/Graphics_WiiU.c b/src/wiiu/Graphics_WiiU.c similarity index 94% rename from src/Graphics_WiiU.c rename to src/wiiu/Graphics_WiiU.c index fec7b881f..42006c299 100644 --- a/src/Graphics_WiiU.c +++ b/src/wiiu/Graphics_WiiU.c @@ -1,8 +1,7 @@ -#include "Core.h" -#ifdef CC_BUILD_WIIU -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Window.h" +#include "../_GraphicsBase.h" +#include "../Errors.h" +#include "../Window.h" + #include #include #include @@ -373,7 +372,12 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { buf->elemSize = strideSizes[fmt]; buf->elemCount = count; - if (GX2RCreateBuffer(buf)) return buf; + // TODO calculate directly, avoid GX2R + uint32_t align = GX2RGetBufferAlignment(buf->flags); + uint32_t size = GX2RGetBufferAllocationSize(buf); + + buf->buffer = MEMAllocFromDefaultHeapEx(size, align); + if (buf->buffer) return buf; // Something went wrong ?? TODO Mem_Free(buf); return NULL; @@ -383,25 +387,24 @@ void Gfx_DeleteVb(GfxResourceID* vb) { GX2RBuffer* buf = *vb; if (!buf) return; - GX2RDestroyBufferEx(buf, 0); - Mem_Free(buf); + MEMFreeToDefaultHeap(buf->buffer); + Mem_Free(buf); *vb = NULL; } void Gfx_BindVb(GfxResourceID vb) { GX2RBuffer* buf = (GX2RBuffer*)vb; - GX2RSetAttributeBuffer(buf, 0, buf->elemSize, 0); - //GX2SetAttribBuffer(0, + GX2SetAttribBuffer(0, buf->elemSize * buf->elemCount, buf->elemSize, buf->buffer); } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { GX2RBuffer* buf = (GX2RBuffer*)vb; - return GX2RLockBufferEx(buf, 0); + return buf->buffer; } void Gfx_UnlockVb(GfxResourceID vb) { GX2RBuffer* buf = (GX2RBuffer*)vb; - GX2RUnlockBufferEx(buf, 0); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, buf->buffer, buf->elemSize * buf->elemCount); } @@ -591,4 +594,3 @@ void Gfx_3DS_SetRenderScreen1(enum Screen3DS screen) { GX2SetContextState(screen == TOP_SCREEN ? tv_state : drc_state); } -#endif diff --git a/src/Platform_WiiU.c b/src/wiiu/Platform_WiiU.c similarity index 93% rename from src/Platform_WiiU.c rename to src/wiiu/Platform_WiiU.c index 8230d940d..3a280c5f8 100644 --- a/src/Platform_WiiU.c +++ b/src/wiiu/Platform_WiiU.c @@ -1,17 +1,18 @@ -#include "Core.h" -#if defined CC_BUILD_WIIU - #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" -#include "Audio.h" +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" +#include "../Audio.h" + #include #include #include @@ -40,7 +41,8 @@ #include #include #include -#include "_PlatformConsole.h" + +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const cc_result ReturnCode_FileNotFound = ENOENT; @@ -125,6 +127,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -466,6 +470,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -476,4 +482,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } -#endif + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/Window_WiiU.c b/src/wiiu/Window_WiiU.c similarity index 95% rename from src/Window_WiiU.c rename to src/wiiu/Window_WiiU.c index 99e807336..cfee1b5ee 100644 --- a/src/Window_WiiU.c +++ b/src/wiiu/Window_WiiU.c @@ -1,18 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_WIIU -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Graphics.h" -#include "Launcher.h" -#include "LBackend.h" -#include "VirtualKeyboard.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Graphics.h" +#include "../Launcher.h" +#include "../LBackend.h" +#include "../VirtualKeyboard.h" + #include #include #include @@ -488,4 +487,3 @@ void OnscreenKeyboard_SetText(const cc_string* text) { void OnscreenKeyboard_Close(void) { VirtualKeyboard_Close(); } -#endif diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index c59d4ac0b..158d2ce36 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -4,9 +4,9 @@ #include "../Window.h" #include +#include "nv2a_gpu.h" #define MAX_RAM_ADDR 0x03FFAFFF -#define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) // https://github.com/XboxDev/nxdk/blob/master/samples/triangle/main.c // https://xboxdevwiki.net/NV2A/Vertex_Shader#Output_registers @@ -17,23 +17,17 @@ // A lot of figuring out which GPU registers to use came from: // - comparing against pbgl and pbkit -static void LoadVertexShader(uint32_t* program, int programSize) { - uint32_t* p; - - // Set cursor for program upload - p = pb_begin(); - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, 0); - pb_end(p); +// Room for 136 vertex shader instructions +// Only need 3, so give 40 instructions to each +#define VS_COLOURED_OFFSET 0 +#define VS_TEXTURED_OFFSET 40 +#define VS_OFFSET_OFFSET 80 - // Copy program instructions (16 bytes each) - for (int i = 0; i < programSize / 16; i++) - { - p = pb_begin(); - pb_push(p++, NV097_SET_TRANSFORM_PROGRAM, 4); - Mem_Copy(p, &program[i * 4], 4 * 4); - p += 4; - pb_end(p); - } +static void LoadVertexShader(int offset, uint32_t* program, int programSize) { + uint32_t* p = pb_begin(); + p = NV2A_set_program_upload_offset(p, offset); + p = NV2A_upload_program(p, program, programSize); + pb_end(p); } static uint32_t vs_coloured_program[] = { @@ -42,6 +36,9 @@ static uint32_t vs_coloured_program[] = { static uint32_t vs_textured_program[] = { #include "../../misc/xbox/vs_textured.inl" }; +static uint32_t vs_offset_program[] = { + #include "../../misc/xbox/vs_offset.inl" +}; static void LoadFragmentShader_Coloured(void) { @@ -65,42 +62,36 @@ static void SetupShaders(void) { uint32_t *p; p = pb_begin(); - // Set run address of shader - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, 0); + p = NV2A_set_program_run_offset(p, 0); + p = NV2A_set_execution_mode_shaders(p); - // Set execution mode - p = pb_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, - MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) - | MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); - - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); - - - // resets "z perspective" flag - //p = pb_push1(p, NV097_SET_CONTROL0, 0); pb_end(p); } static void ResetState(void) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_ALPHA_FUNC, 0x04); // GL_GREATER & 0x0F - p = pb_push1(p, NV097_SET_ALPHA_REF, 0x7F); - p = pb_push1(p, NV097_SET_DEPTH_FUNC, 0x03); // GL_LEQUAL & 0x0F + p = NV2A_set_alpha_test_func(p, 0x04); // GL_GREATER & 0x0F + p = NV2A_set_alpha_test_ref(p, 0x7F); + p = NV2A_set_depth_func(p, 0x03); // GL_LEQUAL & 0x0F - p = pb_push1(p, NV097_SET_BLEND_FUNC_SFACTOR, NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA); - p = pb_push1(p, NV097_SET_BLEND_FUNC_DFACTOR, NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA); - p = pb_push1(p, NV097_SET_BLEND_EQUATION, NV097_SET_BLEND_EQUATION_V_FUNC_ADD); // TODO not needed? + p = NV2A_set_alpha_blend_src(p, NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA); + p = NV2A_set_alpha_blend_dst(p, NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA); + p = NV2A_set_alpha_blend_eq( p, NV097_SET_BLEND_EQUATION_V_FUNC_ADD); // TODO not needed? - p = pb_push1(p, NV097_SET_CULL_FACE, NV097_SET_CULL_FACE_V_FRONT); + p = NV2A_set_cull_face_mode(p, NV097_SET_CULL_FACE_V_FRONT); // the order ClassiCube specifies quad vertices in are in the wrong order // compared to what the GPU expects for front and back facing quads - - /*pb_push(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT, 16); p++; - for (int i = 0; i < 16; i++) - { - *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; - }*/ + + int width = pb_back_buffer_width(); + int height = pb_back_buffer_height(); + p = NV2A_set_clear_rect(p, 0, 0, width, height); + + pb_end(p); + + p = pb_begin(); + p = NV2A_reset_all_vertex_attribs(p); + p = NV2A_set_texture0_matrix(p, false); pb_end(p); } @@ -111,14 +102,17 @@ void Gfx_Create(void) { Gfx.MaxTexHeight = 512; // TODO: 1024? Gfx.Created = true; - InitDefaultResources(); - pb_init(); + InitDefaultResources(); pb_show_front_screen(); SetupShaders(); Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); ResetState(); Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; + + LoadVertexShader(VS_COLOURED_OFFSET, vs_coloured_program, sizeof(vs_coloured_program)); + LoadVertexShader(VS_TEXTURED_OFFSET, vs_textured_program, sizeof(vs_textured_program)); + LoadVertexShader(VS_OFFSET_OFFSET, vs_offset_program, sizeof(vs_offset_program)); // 1x1 dummy white texture struct Bitmap bmp; @@ -128,13 +122,13 @@ void Gfx_Create(void) { } void Gfx_Free(void) { - FreeDefaultResources(); - pb_kill(); + FreeDefaultResources(); + pb_show_debug_screen(); } cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { } -void Gfx_FreeState(void) { } +static void Gfx_RestoreState(void) { } +static void Gfx_FreeState(void) { } /*########################################################################################################################* @@ -255,30 +249,11 @@ void Gfx_BindTexture(GfxResourceID texId) { uint32_t* p; p = pb_begin(); - // set texture stage 0 state - p = pb_push1(p, NV097_SET_TEXTURE_OFFSET, (DWORD)tex->pixels & 0x03ffffff); - p = pb_push1(p, NV097_SET_TEXTURE_FORMAT, - MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | - MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | - MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | - MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V - MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 - p = pb_push1(p, NV097_SET_TEXTURE_CONTROL0, - NV097_SET_TEXTURE_CONTROL0_ENABLE | - MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); - p = pb_push1(p, NV097_SET_TEXTURE_ADDRESS, - 0x00010101); // modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) - p = pb_push1(p, NV097_SET_TEXTURE_FILTER, - 0x2000 | - MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | - MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter - - // set texture matrix state - p = pb_push1(p, NV097_SET_TEXTURE_MATRIX_ENABLE, 0); + p = NV2A_set_texture0_pointer(p, tex->pixels); + p = NV2A_set_texture0_format(p, tex->log2_w, tex->log2_h); + p = NV2A_set_texture0_control0(p, gfx_alphaTest); + p = NV2A_set_texture0_wrapmode(p); + p = NV2A_set_texture0_filter(p); pb_end(p); } @@ -286,15 +261,15 @@ void Gfx_BindTexture(GfxResourceID texId) { /*########################################################################################################################* *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ -static PackedCol clearColor; - void Gfx_ClearColor(PackedCol color) { - clearColor = color; + uint32_t* p = pb_begin(); + p = NV2A_set_clear_colour(p, color); + pb_end(p); } void Gfx_SetFaceCulling(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_CULL_FACE_ENABLE, enabled); + p = NV2A_set_cull_face(p, enabled); pb_end(p); } @@ -302,38 +277,33 @@ void Gfx_SetAlphaArgBlend(cc_bool enabled) { } static void SetAlphaBlend(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_BLEND_ENABLE, enabled); + p = NV2A_set_alpha_blend(p, enabled); pb_end(p); } static void SetAlphaTest(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); + p = NV2A_set_alpha_test(p, enabled); + p = NV2A_set_texture0_control0(p, gfx_alphaTest); pb_end(p); } void Gfx_SetDepthWrite(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_DEPTH_MASK, enabled); + p = NV2A_set_depth_write(p, enabled); pb_end(p); } void Gfx_SetDepthTest(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_DEPTH_TEST_ENABLE, enabled); + p = NV2A_set_depth_test(p, enabled); pb_end(p); } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - unsigned mask = 0; - if (r) mask |= NV097_SET_COLOR_MASK_RED_WRITE_ENABLE; - if (g) mask |= NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE; - if (b) mask |= NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; - if (a) mask |= NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; - uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_COLOR_MASK, mask); + p = NV2A_set_color_write_mask(p, r, g, b, a); pb_end(p); } @@ -364,17 +334,16 @@ void Gfx_BeginFrame(void) { pb_wait_for_vbl(); pb_reset(); pb_target_back_buffer(); + + uint32_t* p = pb_begin(); + p = NV2A_reset_control0(p); + pb_end(p); } void Gfx_ClearBuffers(GfxBuffers buffers) { - int width = pb_back_buffer_width(); - int height = pb_back_buffer_height(); - - // TODO do ourselves - if (buffers & GFX_BUFFER_DEPTH) - pb_erase_depth_stencil_buffer(0, 0, width, height); - if (buffers & GFX_BUFFER_COLOR) - pb_fill(0, 0, width, height, clearColor); + uint32_t* p = pb_begin(); + p = NV2A_clear_buffers(p, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); + pb_end(p); //pb_erase_text_screen(); while (pb_busy()) { } // Wait for completion TODO: necessary?? @@ -419,24 +388,14 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return AllocBuffer(count, strideSizes[fmt]); } -static uint32_t* PushAttribOffset(uint32_t* p, int index, cc_uint8* data) { - return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + index * 4, - (uint32_t)data & 0x03ffffff); -} - void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; uint32_t* p = pb_begin(); - - // TODO: Avoid the same code twice.. - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - p = PushAttribOffset(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); - p = PushAttribOffset(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); - p = PushAttribOffset(p, TEXTURE_ATTR_INDEX, gfx_vertices + 16); - } else { - p = PushAttribOffset(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); - p = PushAttribOffset(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); - } + + p = NV2A_set_vertex_attrib_pointer(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); + p = NV2A_set_vertex_attrib_pointer(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); + p = NV2A_set_vertex_attrib_pointer(p, TEXTURE_ATTR_INDEX, gfx_vertices + 16); + // Harmless to set TEXTURE_ATTR_INDEX, even when vertex format is coloured only pb_end(p); } @@ -469,17 +428,13 @@ void Gfx_SetFog(cc_bool enabled) { } void Gfx_SetFogCol(PackedCol color) { - int R = PackedCol_R(color); - int G = PackedCol_G(color); - int B = PackedCol_B(color); - int A = PackedCol_A(color); - uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_FOG_COLOR, - MASK(NV097_SET_FOG_COLOR_RED, R) | - MASK(NV097_SET_FOG_COLOR_GREEN, G) | - MASK(NV097_SET_FOG_COLOR_BLUE, B) | - MASK(NV097_SET_FOG_COLOR_ALPHA, A)); + + p = NV2A_set_fog_colour(p, + PackedCol_R(color), + PackedCol_G(color), + PackedCol_B(color), + PackedCol_A(color)); pb_end(p); } @@ -539,61 +494,75 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f matrix->row4.w = 0.0f;*/ } -void Gfx_OnWindowResize(void) { } - -static struct Vec4 vp_scale = { 320, -240, 8388608, 1 }; -static struct Vec4 vp_offset = { 320, 240, 8388608, 1 }; -static struct Matrix _view, _proj, _mvp; - -static void UpdateVSConstants(void) { - uint32_t* p; - p = pb_begin(); - - // resets "z perspective" flag - p = pb_push1(p, NV097_SET_CONTROL0, 0); - - // set shader constants cursor to C0 - p = pb_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96); - - // upload transformation matrix - pb_push(p++, NV097_SET_TRANSFORM_CONSTANT, 4*4); - Mem_Copy(p, &_mvp, 16 * 4); p += 16; - // Upload constants too - //struct Vec4 v = { 1, 1, 1, 1 }; - //Mem_Copy(p, &v, 4 * 4); p += 4; - // if necessary, look at vs.inl output for 'c[5]' etc.. - - pb_end(p); +void Gfx_OnWindowResize(void) { + Gfx_SetScissor( 0, 0, Game.Width, Game.Height); + Gfx_SetViewport(0, 0, Game.Width, Game.Height); } +//static struct Vec4 vp_scale = { 320, -240, 8388608, 1 }; +//static struct Vec4 vp_offset = { 320, 240, 8388608, 1 }; +static struct Vec4 vp_scale, vp_offset; +static struct Matrix _view, _proj, _mvp; +// TODO Upload constants too +// if necessary, look at vs.inl output for 'c[5]' etc.. + void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { struct Matrix* dst = type == MATRIX_PROJ ? &_proj : &_view; *dst = *matrix; - Matrix_Mul(&_mvp, &_view, &_proj); + struct Matrix final; struct Matrix vp = Matrix_Identity; vp.row1.x = vp_scale.x; vp.row2.y = vp_scale.y; - vp.row3.z = 8388608; + vp.row3.z = 8388608; // 2^24 / 2 vp.row4.x = vp_offset.x; vp.row4.y = vp_offset.y; - vp.row4.z = 8388608; + vp.row4.z = 8388608; // 2^24 / 2 - Matrix_Mul(&_mvp, &_mvp, &vp); - UpdateVSConstants(); + Matrix_Mul(&final, &_mvp, &vp); + + uint32_t* p; + p = pb_begin(); + p = NV2A_set_constant_upload_offset(p, 0); + p = NV2A_upload_constants(p, &final, 16); + pb_end(p); } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { Gfx_LoadMatrix(MATRIX_VIEW, view); Gfx_LoadMatrix(MATRIX_PROJ, proj); - Matrix_Mul(mvp, view, proj); + Mem_Copy(mvp, &_mvp, sizeof(struct Matrix)); +} + +static int tex_offset; + +static int CalcProgramOffset(void) { + if (tex_offset) + return VS_OFFSET_OFFSET; + if (gfx_format == VERTEX_FORMAT_TEXTURED) + return VS_TEXTURED_OFFSET; + + return VS_COLOURED_OFFSET; } void Gfx_EnableTextureOffset(float x, float y) { + struct Vec4 offset = { x, y, 0, 0 }; + uint32_t* p = pb_begin(); + tex_offset = true; + + p = NV2A_set_constant_upload_offset(p, 4); + p = NV2A_upload_constants(p, &offset, 4); + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); + pb_end(p); } void Gfx_DisableTextureOffset(void) { + uint32_t* p = pb_begin(); + tex_offset = false; + + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); + pb_end(p); } void Gfx_SetViewport(int x, int y, int w, int h) { @@ -604,10 +573,8 @@ void Gfx_SetViewport(int x, int y, int w, int h) { } void Gfx_SetScissor(int x, int y, int w, int h) { - uint32_t* p; - p = pb_begin(); - // NV097_SET_SURFACE_CLIP_HORIZONTAL followed by NV097_SET_SURFACE_CLIP_VERTICAL - p = pb_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, x | (w << 16), y | (h << 16)); + uint32_t* p = pb_begin(); + p = NV2A_set_clip_rect(p, x, y, w, h); pb_end(p); } @@ -618,92 +585,56 @@ void Gfx_SetScissor(int x, int y, int w, int h) { cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -static uint32_t* PushAttrib(uint32_t* p, int index, int format, int size, int stride) { - return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride)); -} - void Gfx_SetVertexFormat(VertexFormat fmt) { if (fmt == gfx_format) return; gfx_format = fmt; gfx_stride = strideSizes[fmt]; uint32_t* p = pb_begin(); - // Clear all attributes TODO optimise - pb_push(p++, NV097_SET_VERTEX_DATA_ARRAY_FORMAT,16); - for (int i = 0; i < 16; i++) - { - *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; - } - - // resets "z perspective" flag - //p = pb_push1(p, NV097_SET_CONTROL0, 0); - // TODO cache these.. if (fmt == VERTEX_FORMAT_TEXTURED) { - p = PushAttrib(p, VERTEX_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 3, SIZEOF_VERTEX_TEXTURED); - p = PushAttrib(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, - 4, SIZEOF_VERTEX_TEXTURED); - p = PushAttrib(p, TEXTURE_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 2, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, VERTEX_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 3, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, TEXTURE_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 2, SIZEOF_VERTEX_TEXTURED); } else { - p = PushAttrib(p, VERTEX_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 3, SIZEOF_VERTEX_COLOURED); - p = PushAttrib(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, - 4, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, VERTEX_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 3, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, TEXTURE_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 0, 0); } + + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); pb_end(p); if (fmt == VERTEX_FORMAT_TEXTURED) { - LoadVertexShader(vs_textured_program, sizeof(vs_textured_program)); LoadFragmentShader_Textured(); - } else { - LoadVertexShader(vs_coloured_program, sizeof(vs_coloured_program)); + } else { LoadFragmentShader_Coloured(); } } -static void DrawArrays(int mode, int start, int count) { - uint32_t *p = pb_begin(); - p = pb_push1(p, NV097_SET_BEGIN_END, mode); - - // NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so must be <= 256 - while (count > 0) - { - int batch_count = min(count, 256); - - p = pb_push1(p, 0x40000000 | NV097_DRAW_ARRAYS, - MASK(NV097_DRAW_ARRAYS_COUNT, (batch_count-1)) | - MASK(NV097_DRAW_ARRAYS_START_INDEX, start)); - - start += batch_count; - count -= batch_count; - } - - p = pb_push1(p, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END); - pb_end(p); -} - void Gfx_DrawVb_Lines(int verticesCount) { - DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount); } static void DrawIndexedVertices(int verticesCount, int startVertex) { - DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { - DrawIndexedVertices(verticesCount, startVertex); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } void Gfx_DrawVb_IndexedTris(int verticesCount) { - DrawIndexedVertices(verticesCount, 0); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, 0, verticesCount); } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - DrawIndexedVertices(verticesCount, startVertex); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } diff --git a/src/xbox/Platform_Xbox.c b/src/xbox/Platform_Xbox.c index ca1929076..ce6a1a933 100644 --- a/src/xbox/Platform_Xbox.c +++ b/src/xbox/Platform_Xbox.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../Funcs.h" @@ -31,13 +34,11 @@ cc_bool Platform_ReadonlyFilesystem; *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ void Platform_Log(const char* msg, int len) { - char tmp[2048 + 1]; + char tmp[2048 + 2]; len = min(len, 2048); - Mem_Copy(tmp, msg, len); tmp[len] = '\0'; + Mem_Copy(tmp, msg, len); tmp[len] = '\n'; tmp[len + 1] = '\0'; - // log to on-screen display - debugPrint("%s\n", tmp); - // log to cxbx-reloaded console + // log to cxbx-reloaded console or Xemu serial output OutputDebugStringA(tmp); } @@ -113,6 +114,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { *str = '\0'; } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!hdd_mounted) return ERR_NOT_SUPPORTED; @@ -461,6 +464,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -472,3 +477,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index f974f9a8a..3018b961d 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -13,6 +13,7 @@ #include #include #include +#include static cc_bool launcherMode; struct _DisplayData DisplayInfo; @@ -20,6 +21,8 @@ struct cc_window WindowInfo; void Window_PreInit(void) { XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); // TODO not call + pb_init(); + pb_show_debug_screen(); } void Window_Init(void) { @@ -83,6 +86,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_xbox[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static xid_dev_t* xid_ctrl; static xid_gamepad_in gp_state; @@ -168,10 +192,10 @@ static void HandleButtons(int port, xid_gamepad_in* gp) { Gamepad_SetButton(port, CCPAD_DOWN, mods & XINPUT_GAMEPAD_DPAD_DOWN); } -#define AXIS_SCALE 8192.0f +#define AXIS_SCALE 4096.0f static void HandleJoystick(int port, int axis, int x, int y, float delta) { - if (Math_AbsI(x) <= 4096) x = 0; - if (Math_AbsI(y) <= 4096) y = 0; + if (Math_AbsI(x) <= 6144) x = 0; + if (Math_AbsI(y) <= 6144) y = 0; Gamepad_SetAxis(port, axis, x / AXIS_SCALE, -y / AXIS_SCALE, delta); } @@ -181,7 +205,7 @@ void Gamepads_Process(float delta) { usbh_pooling_hubs(); #endif if (!xid_ctrl) return; - int port = Gamepad_Connect(0xB0, PadBind_Defaults); + int port = Gamepad_Connect(0xB0, defaults_xbox); HandleButtons(port, &gp_state); HandleJoystick(port, PAD_AXIS_LEFT, gp_state.leftStickX, gp_state.leftStickY, delta); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h new file mode 100644 index 000000000..750342c28 --- /dev/null +++ b/src/xbox/nv2a_gpu.h @@ -0,0 +1,314 @@ +/*########################################################################################################################* +*-----------------------------------------------------GPU commands--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: shared with RSX (PS3) GPU +#define NV2A_MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) + +// disables the default increment behaviour when writing multiple registers +// E.g. with NV2A_3D_COMMAND(cmd, 4): +// - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 +// - disable: REG = v1, REG = v2, REG = v3, REG = v4 +#define NV2A_WRITE_SAME_REGISTER 0x40000000 + +#define NV2A_COMMAND(subchan, cmd, num_params) (((num_params) << 18) | ((subchan) << 13) | (cmd)) +#define NV2A_3D_COMMAND(cmd, num_params) NV2A_COMMAND(SUBCH_3D, cmd, num_params) + +#define _NV_ALPHAKILL_EN (1 << 2) + +// Enables perspective correct texture interpolation +#define _NV_CONTROL0_TEX_PERSPECTIVE_ENABLE (1 << 20) + + +/*########################################################################################################################* +*-----------------------------------------------------GPU pushbuffer------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_push1(uint32_t* p, int cmd, uint32_t value) { + *p++ = NV2A_3D_COMMAND(cmd, 1); + *p++ = value; + return p; +} + +static CC_INLINE uint32_t* NV2A_push2(uint32_t* p, int cmd, uint32_t val1, uint32_t val2) { + *p++ = NV2A_3D_COMMAND(cmd, 2); + *p++ = val1; + *p++ = val2; + return p; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Misc commands-------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { + // resets "z perspective" flag, set "texture perspective flag" + return NV2A_push1(p, NV097_SET_CONTROL0, _NV_CONTROL0_TEX_PERSPECTIVE_ENABLE); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Raster control------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_clip_rect(uint32_t* p, int x, int y, int w, int h) { + // NV097_SET_SURFACE_CLIP_HORIZONTAL, then NV097_SET_SURFACE_CLIP_VERTICAL + return NV2A_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, + x | (w << 16), y | (h << 16)); +} + +static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, int b, int a) { + unsigned mask = 0; + if (r) mask |= NV097_SET_COLOR_MASK_RED_WRITE_ENABLE; + if (g) mask |= NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE; + if (b) mask |= NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; + if (a) mask |= NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; + + return NV2A_push1(p, NV097_SET_COLOR_MASK, mask); +} + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, int A) { + uint32_t mask = + NV2A_MASK(NV097_SET_FOG_COLOR_RED, R) | + NV2A_MASK(NV097_SET_FOG_COLOR_GREEN, G) | + NV2A_MASK(NV097_SET_FOG_COLOR_BLUE, B) | + NV2A_MASK(NV097_SET_FOG_COLOR_ALPHA, A); + + return NV2A_push1(p, NV097_SET_FOG_COLOR, mask); +} + + +static CC_INLINE uint32_t* NV2A_set_depth_write(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_DEPTH_MASK, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_depth_test(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_DEPTH_TEST_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_depth_func(uint32_t* p, int func) { + return NV2A_push1(p, NV097_SET_DEPTH_FUNC, func); +} + + +static CC_INLINE uint32_t* NV2A_set_alpha_test(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_test_func(uint32_t* p, int func) { + return NV2A_push1(p, NV097_SET_ALPHA_FUNC, func); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_test_ref(uint32_t* p, int ref) { + return NV2A_push1(p, NV097_SET_ALPHA_REF, ref); +} + + +static CC_INLINE uint32_t* NV2A_set_alpha_blend(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_BLEND_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_src(uint32_t* p, int factor) { + return NV2A_push1(p, NV097_SET_BLEND_FUNC_SFACTOR, factor); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_dst(uint32_t* p, int factor) { + return NV2A_push1(p, NV097_SET_BLEND_FUNC_DFACTOR, factor); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_eq(uint32_t* p, int equation) { + return NV2A_push1(p, NV097_SET_BLEND_EQUATION, equation); +} + + +static CC_INLINE uint32_t* NV2A_set_cull_face(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_CULL_FACE_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_cull_face_mode(uint32_t* p, int mode) { + return NV2A_push1(p, NV097_SET_CULL_FACE, mode); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Primitive drawing---------------------------------------------------* +*#########################################################################################################################*/ +// NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so each draw call count must be <= 256 +#define DA_BATCH_SIZE 256 + +static void NV2A_DrawArrays(int mode, unsigned start, unsigned count) { + uint32_t *p = pb_begin(); + p = NV2A_push1(p, NV097_SET_BEGIN_END, mode); + + // Ceiling division by DA_BATCH_SIZE + unsigned num_batches = (count + DA_BATCH_SIZE - 1) / DA_BATCH_SIZE; + *p++ = NV2A_3D_COMMAND(NV2A_WRITE_SAME_REGISTER | NV097_DRAW_ARRAYS, num_batches); + + while (count > 0) + { + int batch_count = min(count, DA_BATCH_SIZE); + + *p++ = NV2A_MASK(NV097_DRAW_ARRAYS_COUNT, batch_count-1) | + NV2A_MASK(NV097_DRAW_ARRAYS_START_INDEX, start); + + start += batch_count; + count -= batch_count; + } + + p = NV2A_push1(p, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END); + pb_end(p); +} + + +/*########################################################################################################################* +*--------------------------------------------------Vertex shader constants------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_constant_upload_offset(uint32_t* p, int offset) { + // set shader constants cursor to: C0 + offset + return NV2A_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96 + offset); +} + +static CC_INLINE uint32_t* NV2A_upload_constants(uint32_t* p, void* src, int num_dwords) { + *p++ = NV2A_3D_COMMAND(NV097_SET_TRANSFORM_CONSTANT, num_dwords); + Mem_Copy(p, src, num_dwords * 4); p += num_dwords; + return p; +} + + +/*########################################################################################################################* +*---------------------------------------------------Vertex shader programs-------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_program_upload_offset(uint32_t* p, int offset) { + return NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, offset); +} + +static CC_INLINE uint32_t* NV2A_upload_program(uint32_t* p, uint32_t* program, int size) { + // Copy program instructions (16 bytes each) + for (int i = 0; i < size / 16; i++, program += 4) + { + *p++ = NV2A_3D_COMMAND(NV097_SET_TRANSFORM_PROGRAM, 4); + Mem_Copy(p, program, 16); p += 4; + } + return p; +} + +static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) { + return NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, offset); +} + +static CC_INLINE uint32_t* NV2A_set_execution_mode_shaders(uint32_t* p) { + p = NV2A_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, + NV2A_MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) | + NV2A_MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); + + p = NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); + return p; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex attributes---------------------------------------------------* +*#########################################################################################################################*/ +// https://xboxdevwiki.net/NV2A/Vertex_Shader#Input_registers +// 16 input vertex attribute registers +#define NV2A_MAX_INPUT_ATTRIBS 16 + +static uint32_t* NV2A_reset_all_vertex_attribs(uint32_t* p) { + *p++ = NV2A_3D_COMMAND(NV097_SET_VERTEX_DATA_ARRAY_FORMAT, NV2A_MAX_INPUT_ATTRIBS); + + for (int i = 0; i < NV2A_MAX_INPUT_ATTRIBS; i++) + { + *p++ = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; + } + return p; +} + +static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int attrib, int format, int size, int stride) { + uint32_t mask = + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride); + + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + attrib * 4, mask); +} + +static uint32_t* NV2A_set_vertex_attrib_pointer(uint32_t* p, int attrib, cc_uint8* data) { + uint32_t offset = (uint32_t)data & 0x03ffffff; + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + attrib * 4, offset); +} + + +/*########################################################################################################################* +*------------------------------------------------------Buffer clearing----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_clear_rect(uint32_t* p, int x, int y, int w, int h) { + // Sets NV097_SET_CLEAR_RECT_HORIZONTAL then NV097_SET_CLEAR_RECT_VERTICAL + return NV2A_push2(p, NV097_SET_CLEAR_RECT_HORIZONTAL, + ((x + w - 1) << 16) | x, + ((y + h - 1) << 16) | y); +} + +static CC_INLINE uint32_t* NV2A_set_clear_colour(uint32_t* p, uint32_t colour) { + // Sets NV097_SET_ZSTENCIL_CLEAR_VALUE then NV097_SET_COLOR_CLEAR_VALUE + return NV2A_push2(p, NV097_SET_ZSTENCIL_CLEAR_VALUE, + 0xFFFFFF00, // (depth << 8) | stencil, + colour); +} + +static CC_INLINE uint32_t* NV2A_clear_buffers(uint32_t* p, int color, int depth) { + uint32_t mask = 0; + if (color) mask |= NV097_CLEAR_SURFACE_COLOR; + if (depth) mask |= NV097_CLEAR_SURFACE_Z; + if (depth) mask |= NV097_CLEAR_SURFACE_STENCIL; + + return NV2A_push1(p, NV097_CLEAR_SURFACE, mask); +} + + +/*########################################################################################################################* +*--------------------------------------------------------Texturing--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: API is hardcoded for one texture only, even though hardware supports multiple textures + +static CC_INLINE uint32_t* NV2A_set_texture0_control0(uint32_t* p, int texkill) { + return NV2A_push1(p, NV097_SET_TEXTURE_CONTROL0, + NV097_SET_TEXTURE_CONTROL0_ENABLE | + (texkill ? _NV_ALPHAKILL_EN : 0) | + NV2A_MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | + NV2A_MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); +} + +static uint32_t* NV2A_set_texture0_pointer(uint32_t* p, void* pixels) { + uint32_t offset = (uint32_t)pixels & 0x03ffffff; + return NV2A_push1(p, NV097_SET_TEXTURE_OFFSET, offset); +} + +static uint32_t* NV2A_set_texture0_format(uint32_t* p, unsigned log_u, unsigned log_v) { + return NV2A_push1(p, NV097_SET_TEXTURE_FORMAT, + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 +} + +static uint32_t* NV2A_set_texture0_wrapmode(uint32_t* p) { + return NV2A_push1(p, NV097_SET_TEXTURE_ADDRESS, + 0x00010101); // modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) +} + +static uint32_t* NV2A_set_texture0_filter(uint32_t* p) { + return NV2A_push1(p, NV097_SET_TEXTURE_FILTER, + 0x2000 | + NV2A_MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | + NV2A_MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter +} + +static uint32_t* NV2A_set_texture0_matrix(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_TEXTURE_MATRIX_ENABLE, enabled); +} + diff --git a/src/xbox360/Graphics_Xbox360.c b/src/xbox360/Graphics_Xbox360.c index c1d13e6a7..8bd0c1e73 100644 --- a/src/xbox360/Graphics_Xbox360.c +++ b/src/xbox360/Graphics_Xbox360.c @@ -57,7 +57,7 @@ static void CreateShaders(void) { void Gfx_Create(void) { if (!Gfx.Created) { CreateState(); - CreateShaders(); + //CreateShaders(); TODO } Gfx.Created = true; Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); @@ -177,7 +177,7 @@ void Gfx_SetAlphaArgBlend(cc_bool enabled) { // TODO } -void Gfx_ClearColor(PackedCol color) { +void Gfx_ClearColor(PackedCol color) { Xe_SetClearColor(xe, color); } @@ -231,7 +231,7 @@ void Gfx_DeleteVb(GfxResourceID* vb) { void Gfx_BindVb(GfxResourceID vb) { struct XenosVertexBuffer* xvb = (struct XenosVertexBuffer*)vb; - Xe_SetStreamSource(xe, 0, xvb, 0, gfx_stride); + //Xe_SetStreamSource(xe, 0, xvb, 0, gfx_stride); TODO } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { @@ -274,33 +274,33 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_stride = strideSizes[fmt]; if (fmt == VERTEX_FORMAT_COLOURED) { - Xe_SetTexture(xe, 0, NULL); - Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_col_ps, 0); - Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_col_vs, 0); + //Xe_SetTexture(xe, 0, NULL); TODO + //Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_col_ps, 0); TODO + //Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_col_vs, 0); TODO } else { - Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_tex_ps, 0); - Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_tex_vs, 0); + //Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_tex_ps, 0); TODO + //Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_tex_vs, 0); TODO } } void Gfx_DrawVb_Lines(int verticesCount) { Platform_Log1("DRAW_LINES: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_LINELIST, 0, verticesCount >> 1); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_LINELIST, 0, verticesCount >> 1); TODO } void Gfx_DrawVb_IndexedTris(int verticesCount) { Platform_Log1("DRAW_TRIS: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, 0, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, 0, verticesCount >> 2); TODO } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { Platform_Log1("DRAW_TRIS_RANGE: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); TODO } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { Platform_Log1("DRAW_TRIS_MAP: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); TODO } @@ -316,7 +316,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { Matrix_Mul(&_mvp, &_view, &_proj); // TODO: Is this a global uniform, or does it need to be reloaded on shader change? - Xe_SetVertexShaderConstantF(xe, 0, (float*)&_mvp, 4); + //Xe_SetVertexShaderConstantF(xe, 0, (float*)&_mvp, 4); TODO } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { diff --git a/src/xbox360/Platform_Xbox360.c b/src/xbox360/Platform_Xbox360.c index ff5864032..34626b334 100644 --- a/src/xbox360/Platform_Xbox360.c +++ b/src/xbox360/Platform_Xbox360.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../Funcs.h" @@ -101,6 +104,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return ENOSYS; @@ -335,6 +340,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* @@ -345,3 +352,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/xbox360/Window_Xbox360.c b/src/xbox360/Window_Xbox360.c index 71833c7b7..75f1c4559 100644 --- a/src/xbox360/Window_Xbox360.c +++ b/src/xbox360/Window_Xbox360.c @@ -85,6 +85,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_xbox360[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; @@ -131,7 +152,7 @@ static void HandleJoystick(int port, int axis, int x, int y, float delta) { void Gamepads_Process(float delta) { usb_do_poll(); - int port = Gamepad_Connect(0xB0360, PadBind_Defaults); + int port = Gamepad_Connect(0xB0360, defaults_xbox360); struct controller_data_s pad; int res = get_controller_data(&pad, 0); diff --git a/third_party/bearssl/aes_big_cbcdec.c b/third_party/bearssl/aes_big_cbcdec.c index d969a3bf1..0ea6df841 100644 --- a/third_party/bearssl/aes_big_cbcdec.c +++ b/third_party/bearssl/aes_big_cbcdec.c @@ -46,12 +46,12 @@ br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, unsigned char tmp[16]; int i; - memcpy(tmp, buf, 16); + br_memcpy(tmp, buf, 16); br_aes_big_decrypt(ctx->num_rounds, ctx->skey, buf); for (i = 0; i < 16; i ++) { buf[i] ^= ivbuf[i]; } - memcpy(ivbuf, tmp, 16); + br_memcpy(ivbuf, tmp, 16); buf += 16; len -= 16; } diff --git a/third_party/bearssl/aes_big_cbcenc.c b/third_party/bearssl/aes_big_cbcenc.c index 265e53b80..bd32af8e7 100644 --- a/third_party/bearssl/aes_big_cbcenc.c +++ b/third_party/bearssl/aes_big_cbcenc.c @@ -49,7 +49,7 @@ br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, buf[i] ^= ivbuf[i]; } br_aes_big_encrypt(ctx->num_rounds, ctx->skey, buf); - memcpy(ivbuf, buf, 16); + br_memcpy(ivbuf, buf, 16); buf += 16; len -= 16; } diff --git a/third_party/bearssl/aes_big_ctr.c b/third_party/bearssl/aes_big_ctr.c index 18fbb8467..97024c711 100644 --- a/third_party/bearssl/aes_big_ctr.c +++ b/third_party/bearssl/aes_big_ctr.c @@ -57,7 +57,7 @@ br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, while (len > 0) { unsigned char tmp[16]; - memcpy(tmp, iv, 12); + br_memcpy(tmp, iv, 12); br_enc32be(tmp + 12, cc ++); br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); if (len <= 16) { diff --git a/third_party/bearssl/aes_x86ni.c b/third_party/bearssl/aes_x86ni.c index d5408f136..54c51efd7 100644 --- a/third_party/bearssl/aes_x86ni.c +++ b/third_party/bearssl/aes_x86ni.c @@ -205,7 +205,7 @@ x86ni_keysched(__m128i *sk, const void *key, size_t len) } /* see inner.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION unsigned br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) { @@ -213,12 +213,12 @@ br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) unsigned num_rounds; num_rounds = x86ni_keysched(sk, key, len); - memcpy(skni, sk, (num_rounds + 1) << 4); + br_memcpy(skni, sk, (num_rounds + 1) << 4); return num_rounds; } /* see inner.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION unsigned br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len) { diff --git a/third_party/bearssl/aes_x86ni_cbcdec.c b/third_party/bearssl/aes_x86ni_cbcdec.c index 862b1b5bd..903eb7916 100644 --- a/third_party/bearssl/aes_x86ni_cbcdec.c +++ b/third_party/bearssl/aes_x86ni_cbcdec.c @@ -46,7 +46,7 @@ br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, void *data, size_t len) diff --git a/third_party/bearssl/aes_x86ni_cbcenc.c b/third_party/bearssl/aes_x86ni_cbcenc.c index 85feecdb0..410ed36ee 100644 --- a/third_party/bearssl/aes_x86ni_cbcenc.c +++ b/third_party/bearssl/aes_x86ni_cbcenc.c @@ -46,7 +46,7 @@ br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, void *data, size_t len) diff --git a/third_party/bearssl/aes_x86ni_ctr.c b/third_party/bearssl/aes_x86ni_ctr.c index 1cddd6065..6223eb816 100644 --- a/third_party/bearssl/aes_x86ni_ctr.c +++ b/third_party/bearssl/aes_x86ni_ctr.c @@ -46,7 +46,7 @@ br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len) @@ -59,7 +59,7 @@ br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, unsigned u; buf = data; - memcpy(ivbuf, iv, 12); + br_memcpy(ivbuf, iv, 12); num_rounds = ctx->num_rounds; for (u = 0; u <= num_rounds; u ++) { sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); diff --git a/third_party/bearssl/aes_x86ni_ctrcbc.c b/third_party/bearssl/aes_x86ni_ctrcbc.c index f57fead68..1f211da2f 100644 --- a/third_party/bearssl/aes_x86ni_ctrcbc.c +++ b/third_party/bearssl/aes_x86ni_ctrcbc.c @@ -46,7 +46,7 @@ br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *data, size_t len) @@ -252,7 +252,7 @@ br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len) @@ -303,7 +303,7 @@ br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len) @@ -452,7 +452,7 @@ br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len) diff --git a/third_party/bearssl/aesctr_drbg.c b/third_party/bearssl/aesctr_drbg.c index 8dbd50102..93c08e962 100644 --- a/third_party/bearssl/aesctr_drbg.c +++ b/third_party/bearssl/aesctr_drbg.c @@ -33,7 +33,7 @@ br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, unsigned char tmp[16]; ctx->vtable = &br_aesctr_drbg_vtable; - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); aesctr->init(&ctx->sk.vtable, tmp, 16); ctx->cc = 0; br_aesctr_drbg_update(ctx, seed, len); @@ -47,7 +47,7 @@ br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) unsigned char iv[12]; buf = out; - memset(iv, 0, sizeof iv); + br_memset(iv, 0, sizeof iv); while (len > 0) { size_t clen; @@ -76,7 +76,7 @@ br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) /* * Run CTR. */ - memset(buf, 0, clen); + br_memset(buf, 0, clen); ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable, iv, ctx->cc, buf, clen); buf += clen; @@ -131,15 +131,15 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) * Use an all-one IV to get a fresh output block that depends on the * current seed. */ - memset(iv, 0xFF, sizeof iv); - memset(s, 0, 16); + br_memset(iv, 0xFF, sizeof iv); + br_memset(s, 0, 16); ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16); /* * Set G[] and H[] to conventional start values. */ - memset(G, 0xB6, sizeof G); - memset(H, 0x5A, sizeof H); + br_memset(G, 0xB6, sizeof G); + br_memset(H, 0x5A, sizeof H); /* * Process the concatenation of the current state and the seed @@ -153,9 +153,9 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) /* * Assemble new key H||m into tmp[]. */ - memcpy(tmp, H, 16); + br_memcpy(tmp, H, 16); if (first) { - memcpy(tmp + 16, s, 16); + br_memcpy(tmp + 16, s, 16); first = 0; } else { size_t clen; @@ -164,8 +164,8 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) break; } clen = len < 16 ? len : 16; - memcpy(tmp + 16, seed, clen); - memset(tmp + 16 + clen, 0, 16 - clen); + br_memcpy(tmp + 16, seed, clen); + br_memset(tmp + 16 + clen, 0, 16 - clen); seed = (const unsigned char *)seed + clen; len -= clen; } @@ -174,16 +174,16 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) /* * Compute new G and H values. */ - memcpy(iv, G, 12); - memcpy(newG, G, 16); + br_memcpy(iv, G, 12); + br_memcpy(newG, G, 16); ctx->sk.vtable->run(&ctx->sk.vtable, iv, br_dec32be(G + 12), newG, 16); iv[0] ^= 0x01; - memcpy(H, G, 16); + br_memcpy(H, G, 16); H[0] ^= 0x01; ctx->sk.vtable->run(&ctx->sk.vtable, iv, br_dec32be(G + 12), H, 16); - memcpy(G, newG, 16); + br_memcpy(G, newG, 16); } /* diff --git a/third_party/bearssl/asn1enc.c b/third_party/bearssl/asn1enc.c index 7a7496334..290035d45 100644 --- a/third_party/bearssl/asn1enc.c +++ b/third_party/bearssl/asn1enc.c @@ -88,6 +88,6 @@ br_asn1_encode_uint(void *dest, br_asn1_uint pp) lenlen = br_asn1_encode_length(buf, pp.asn1len); buf += lenlen; *buf = 0x00; - memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); + br_memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); return 1 + lenlen + pp.asn1len; } diff --git a/third_party/bearssl/bearssl_hash.h b/third_party/bearssl/bearssl_hash.h index 00c1e1d07..f924bc272 100644 --- a/third_party/bearssl/bearssl_hash.h +++ b/third_party/bearssl/bearssl_hash.h @@ -75,7 +75,7 @@ extern "C" { * Context for an ongoing computation. It is allocated by the * caller, and a pointer to it is passed to all functions. A * context contains no interior pointer, so it can be moved around - * and cloned (with a simple `memcpy()` or equivalent) in order to + * and cloned (with a simple `br_memcpy()` or equivalent) in order to * capture the function state at some point. Computations that use * distinct context structures are independent of each other. The * first field of `br_xxx_context` is always a pointer to the diff --git a/third_party/bearssl/bearssl_ssl.h b/third_party/bearssl/bearssl_ssl.h index 14d09d035..c5d38ed6c 100644 --- a/third_party/bearssl/bearssl_ssl.h +++ b/third_party/bearssl/bearssl_ssl.h @@ -34,6 +34,7 @@ #include "bearssl_prf.h" #include "bearssl_rand.h" #include "bearssl_x509.h" +#include "bearssl_stdlib.h" #ifdef __cplusplus extern "C" { @@ -1889,7 +1890,7 @@ static inline void br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, br_ssl_session_parameters *pp) { - memcpy(pp, &cc->session, sizeof *pp); + br_memcpy(pp, &cc->session, sizeof *pp); } /** @@ -1906,7 +1907,7 @@ static inline void br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, const br_ssl_session_parameters *pp) { - memcpy(&cc->session, pp, sizeof *pp); + br_memcpy(&cc->session, pp, sizeof *pp); } /** diff --git a/third_party/bearssl/bearssl_stdlib.h b/third_party/bearssl/bearssl_stdlib.h new file mode 100644 index 000000000..5fb35c2c0 --- /dev/null +++ b/third_party/bearssl/bearssl_stdlib.h @@ -0,0 +1,37 @@ +#ifndef BR_BEARSSL_STDLIB_H__ +#define BR_BEARSSL_STDLIB_H__ +/* ==== BEG ClassiCube specific ==== */ +static inline size_t br_strlen(const char* a) { + int i = 0; + while (*a++) i++; + return i; +} + +static inline size_t br_memcmp(const void* a, const void* b, size_t len) { + unsigned char* p1 = (unsigned char*)a; + unsigned char* p2 = (unsigned char*)b; + size_t i; + + for (i = 0; i < len; i++) + { + if (p1[i] < p2[i]) return -1; + if (p1[i] > p2[i]) return 1; + } + return 0; +} + +#ifdef CC_BUILD_NOSTDLIB + extern void* Mem_Copy(void* dst, const void* src, unsigned size); + extern void* Mem_Move(void* dst, const void* src, unsigned size); + extern void* Mem_Set(void* dst, unsigned char val, unsigned size); + + #define br_memcpy Mem_Copy + #define br_memmove Mem_Move + #define br_memset Mem_Set +#else + #define br_memcpy memcpy + #define br_memset memset + #define br_memmove memmove +#endif +/* ==== END ClassiCube specific ==== */ +#endif diff --git a/third_party/bearssl/ccm.c b/third_party/bearssl/ccm.c index 68cc913ec..d2dde6531 100644 --- a/third_party/bearssl/ccm.c +++ b/third_party/bearssl/ccm.c @@ -76,7 +76,7 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, tmp[0] = (aad_len > 0 ? 0x40 : 0x00) | (((unsigned)tag_len - 2) << 2) | (q - 1); - memcpy(tmp + 1, nonce, nonce_len); + br_memcpy(tmp + 1, nonce, nonce_len); for (u = 0; u < q; u ++) { tmp[15 - u] = (unsigned char)data_len; data_len >>= 8; @@ -93,7 +93,7 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, /* * Start CBC-MAC. */ - memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); + br_memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp); /* @@ -120,9 +120,9 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, * Make initial counter value and compute tag mask. */ ctx->ctr[0] = q - 1; - memcpy(ctx->ctr + 1, nonce, nonce_len); - memset(ctx->ctr + 1 + nonce_len, 0, q); - memset(ctx->tagmask, 0, sizeof ctx->tagmask); + br_memcpy(ctx->ctr + 1, nonce, nonce_len); + br_memset(ctx->ctr + 1 + nonce_len, 0, q); + br_memset(ctx->tagmask, 0, sizeof ctx->tagmask); (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->tagmask, sizeof ctx->tagmask); @@ -147,11 +147,11 @@ br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) clen = (sizeof ctx->buf) - ptr; if (clen > len) { - memcpy(ctx->buf + ptr, dbuf, len); + br_memcpy(ctx->buf + ptr, dbuf, len); ctx->ptr = ptr + len; return; } - memcpy(ctx->buf + ptr, dbuf, clen); + br_memcpy(ctx->buf + ptr, dbuf, clen); dbuf += clen; len -= clen; (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, @@ -169,7 +169,7 @@ br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) /* * Copy last partial block in the context buffer. */ - memcpy(ctx->buf, dbuf, ptr); + br_memcpy(ctx->buf, dbuf, ptr); ctx->ptr = ptr; } @@ -184,7 +184,7 @@ br_ccm_flip(br_ccm_context *ctx) */ ptr = ctx->ptr; if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + br_memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); ctx->ptr = 0; @@ -276,7 +276,7 @@ br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len) if (ptr != 0) { size_t u; - memset(ctx->buf, 0, sizeof ctx->buf); + br_memset(ctx->buf, 0, sizeof ctx->buf); (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf); if (encrypt) { @@ -314,7 +314,7 @@ br_ccm_get_tag(br_ccm_context *ctx, void *tag) */ ptr = ctx->ptr; if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + br_memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); } @@ -325,7 +325,7 @@ br_ccm_get_tag(br_ccm_context *ctx, void *tag) for (u = 0; u < ctx->tag_len; u ++) { ctx->cbcmac[u] ^= ctx->tagmask[u]; } - memcpy(tag, ctx->cbcmac, ctx->tag_len); + br_memcpy(tag, ctx->cbcmac, ctx->tag_len); return ctx->tag_len; } diff --git a/third_party/bearssl/chacha20_ct.c b/third_party/bearssl/chacha20_ct.c index 9961eb119..1159c85f2 100644 --- a/third_party/bearssl/chacha20_ct.c +++ b/third_party/bearssl/chacha20_ct.c @@ -50,10 +50,10 @@ br_chacha20_ct_run(const void *key, size_t clen; unsigned char tmp[64]; - memcpy(&state[0], CW, sizeof CW); - memcpy(&state[4], kw, sizeof kw); + br_memcpy(&state[0], CW, sizeof CW); + br_memcpy(&state[4], kw, sizeof kw); state[12] = cc; - memcpy(&state[13], ivw, sizeof ivw); + br_memcpy(&state[13], ivw, sizeof ivw); for (i = 0; i < 10; i ++) { #define QROUND(a, b, c, d) do { \ diff --git a/third_party/bearssl/chacha20_sse2.c b/third_party/bearssl/chacha20_sse2.c index 2905d09b4..79e442af3 100644 --- a/third_party/bearssl/chacha20_sse2.c +++ b/third_party/bearssl/chacha20_sse2.c @@ -40,20 +40,27 @@ br_chacha20_sse2_get(void) * If using 64-bit mode, then SSE2 opcodes should be automatically * available, since they are part of the ABI. * - * In 32-bit mode, not used due anymore to hitting an obscure possible compiler bug. + * In 32-bit mode, we use CPUID to detect the SSE2 feature. */ #if BR_amd64 return &br_chacha20_sse2_run; #else - return 0; + /* + * SSE2 support is indicated by bit 26 in EDX. + */ + if (br_cpuid(0, 0, 0, 0x04000000)) { + return &br_chacha20_sse2_run; + } else { + return 0; + } #endif } BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2") +BR_TARGET("sse2") BR_SSE_FUNCTION uint32_t br_chacha20_sse2_run(const void *key, const void *iv, uint32_t cc, void *data, size_t len) @@ -72,7 +79,7 @@ br_chacha20_sse2_run(const void *key, kw0 = _mm_loadu_si128(key); kw1 = _mm_loadu_si128((const void *)((const unsigned char *)key + 16)); ivtmp[0] = cc; - memcpy(ivtmp + 1, iv, 12); + br_memcpy(ivtmp + 1, iv, 12); iw = _mm_loadu_si128((const void *)ivtmp); cw = _mm_loadu_si128((const void *)CW); one = _mm_set_epi32(0, 0, 0, 1); diff --git a/third_party/bearssl/config.h b/third_party/bearssl/config.h index ff6fabc40..09791b8ba 100644 --- a/third_party/bearssl/config.h +++ b/third_party/bearssl/config.h @@ -32,20 +32,6 @@ * non-zero integer (normally 1). If the macro is not defined, then * autodetection applies. */ - -/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ -#ifdef NXDK -#define BR_AES_X86NI 0 -#define BR_ENABLE_INTRINSICS 0 -#define BR_SSE2 0 -#define BR_RDRAND 0 -#undef _WIN32 -#endif - -/* Rely on ClassiCube's implementation for RNG */ -#define BR_USE_WIN32_RAND 0 -#define BR_USE_URANDOM 0 -#define BR_USE_GETENTROPY 0 /* * When BR_64 is enabled, 64-bit integer types are assumed to be @@ -102,54 +88,6 @@ #define BR_NO_ARITH_SHIFT 1 */ -/* - * When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode - * to automatically obtain quality randomness for seeding its internal - * PRNG. Since that opcode is present only in recent x86 CPU, its - * support is dynamically tested; if the current CPU does not support - * it, then another random source will be used, such as /dev/urandom or - * CryptGenRandom(). - * -#define BR_RDRAND 1 - */ - -/* - * When BR_USE_GETENTROPY is enabled, the SSL engine will use the - * getentropy() function to obtain quality randomness for seeding its - * internal PRNG. On Linux and FreeBSD, getentropy() is implemented by - * the standard library with the system call getrandom(); on OpenBSD, - * getentropy() is the system call, and there is no getrandom() wrapper, - * hence the use of the getentropy() function for maximum portability. - * - * If the getentropy() call fails, and BR_USE_URANDOM is not explicitly - * disabled, then /dev/urandom will be used as a fallback mechanism. On - * FreeBSD and OpenBSD, this does not change much, since /dev/urandom - * will block if not enough entropy has been obtained since last boot. - * On Linux, /dev/urandom might not block, which can be troublesome in - * early boot stages, which is why getentropy() is preferred. - * -#define BR_USE_GETENTROPY 1 - */ - -/* - * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom - * to automatically obtain quality randomness for seeding its internal - * PRNG. - * -#define BR_USE_URANDOM 1 - */ - -/* - * When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32 - * (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to - * automatically obtain quality randomness for seeding its internal PRNG. - * - * Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the - * former takes precedence. - * -#define BR_USE_WIN32_RAND 1 - */ - /* * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with * inline assembly which is shorter and/or faster. This should be used @@ -185,16 +123,6 @@ #define BR_SSE2 1 */ -/* - * When BR_POWER8 is enabled, the AES implementation using the POWER ISA - * 2.07 opcodes (available on POWER8 processors and later) is compiled. - * If this is not enabled explicitly, then that implementation will be - * compiled only if a compatible compiler is detected, _and_ the target - * architecture is POWER8 or later. - * -#define BR_POWER8 1 - */ - /* * When BR_INT128 is enabled, then code using the 'unsigned __int64' * and 'unsigned __int128' types will be used to leverage 64x64->128 diff --git a/third_party/bearssl/ec_c25519_i31.c b/third_party/bearssl/ec_c25519_i31.c index f8ffc2c24..4b6389f3b 100644 --- a/third_party/bearssl/ec_c25519_i31.c +++ b/third_party/bearssl/ec_c25519_i31.c @@ -61,7 +61,7 @@ print_int_mont(const char *name, const uint32_t *x) size_t u; printf("%s = ", name); - memcpy(y, x, sizeof y); + br_memcpy(y, x, sizeof y); br_i31_from_monty(y, C255_P, P0I); br_i31_encode(tmp, sizeof tmp, y); for (u = 0; u < sizeof tmp; u ++) { @@ -132,11 +132,11 @@ c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) uint32_t ctl; uint32_t t[10]; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); ctl = br_i31_add(t, b, 1); ctl |= NOT(br_i31_sub(t, C255_P, 0)); br_i31_sub(t, C255_P, ctl); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -144,9 +144,9 @@ c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) { uint32_t t[10]; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); br_i31_add(t, C255_P, br_i31_sub(t, b, 1)); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -155,7 +155,7 @@ c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) uint32_t t[10]; br_i31_montymul(t, a, b, C255_P, P0I); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -224,17 +224,17 @@ api_mul(unsigned char *G, size_t Glen, * into Montgomery representation. */ br_i31_montymul(x1, a, C255_R2, C255_P, P0I); - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); br_i31_zero(z2, C255_P[0]); - memcpy(x2, z2, sizeof z2); + br_memcpy(x2, z2, sizeof z2); x2[1] = 0x13000000; - memcpy(z3, x2, sizeof x2); + br_memcpy(z3, x2, sizeof x2); /* * kb[] is in big-endian notation, but possibly shorter than k[]. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -307,12 +307,12 @@ api_mul(unsigned char *G, size_t Glen, * square-and-multiply algorithm; we mutualise most non-squarings * since the exponent contains almost only ones. */ - memcpy(a, z2, sizeof z2); + br_memcpy(a, z2, sizeof z2); for (i = 0; i < 15; i ++) { c255_mul(a, a, a); c255_mul(a, a, z2); } - memcpy(b, a, sizeof a); + br_memcpy(b, a, sizeof a); for (i = 0; i < 14; i ++) { int j; @@ -332,7 +332,7 @@ api_mul(unsigned char *G, size_t Glen, /* * To avoid a dependency on br_i31_from_monty(), we use * a Montgomery multiplication with 1. - * memcpy(x2, b, sizeof b); + * br_memcpy(x2, b, sizeof b); * br_i31_from_monty(x2, C255_P, P0I); */ br_i31_zero(a, C255_P[0]); @@ -352,7 +352,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m31.c b/third_party/bearssl/ec_c25519_m31.c index 1dd6d514f..619135bac 100644 --- a/third_party/bearssl/ec_c25519_m31.c +++ b/third_party/bearssl/ec_c25519_m31.c @@ -44,7 +44,7 @@ print_int(const char *name, const uint32_t *x) return; } } - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); for (u = 0; u < 9; u ++) { uint64_t w; int j, k; @@ -348,7 +348,7 @@ reduce_final_f255(uint32_t *d) uint32_t cc; int i; - memcpy(t, d, sizeof t); + br_memcpy(t, d, sizeof t); cc = 19; for (i = 0; i < 9; i ++) { uint32_t w; @@ -647,15 +647,15 @@ api_mul(unsigned char *G, size_t Glen, * into Montgomery representation. */ x1[8] = le8_to_le30(x1, G, 32); - memcpy(x3, x1, sizeof x1); - memset(z2, 0, sizeof z2); - memset(x2, 0, sizeof x2); + br_memcpy(x3, x1, sizeof x1); + br_memset(z2, 0, sizeof z2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z3, 0, sizeof z3); + br_memset(z3, 0, sizeof z3); z3[0] = 1; - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -728,12 +728,12 @@ api_mul(unsigned char *G, size_t Glen, * square-and-multiply algorithm; we mutualise most non-squarings * since the exponent contains almost only ones. */ - memcpy(a, z2, sizeof z2); + br_memcpy(a, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_square(a, a); f255_mul(a, a, z2); } - memcpy(b, a, sizeof a); + br_memcpy(b, a, sizeof a); for (i = 0; i < 14; i ++) { int j; @@ -762,7 +762,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m62.c b/third_party/bearssl/ec_c25519_m62.c index 6b058eb1b..516e9d4ce 100644 --- a/third_party/bearssl/ec_c25519_m62.c +++ b/third_party/bearssl/ec_c25519_m62.c @@ -403,22 +403,22 @@ api_mul(unsigned char *G, size_t Glen, x1[4] = (br_dec64le(&G[24]) >> 12) & MASK51; /* - * We can use memset() to clear values, because exact-width types + * We can use br_memset() to clear values, because exact-width types * like uint64_t are guaranteed to have no padding bits or * trap representations. */ - memset(x2, 0, sizeof x2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z2, 0, sizeof z2); - memcpy(x3, x1, sizeof x1); - memcpy(z3, x2, sizeof x2); + br_memset(z2, 0, sizeof z2); + br_memcpy(x3, x1, sizeof x1); + br_memcpy(z3, x2, sizeof x2); /* * The multiplier is provided in big-endian notation, and * possibly shorter than 32 bytes. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -499,12 +499,12 @@ api_mul(unsigned char *G, size_t Glen, * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize * most non-squarings. We use x1 and x3, now useless, as temporaries. */ - memcpy(x1, z2, sizeof z2); + br_memcpy(x1, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_mul(x1, x1, x1); f255_mul(x1, x1, z2); } - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); for (i = 0; i < 14; i ++) { int j; @@ -549,7 +549,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m64.c b/third_party/bearssl/ec_c25519_m64.c index df4883467..7fca81b4e 100644 --- a/third_party/bearssl/ec_c25519_m64.c +++ b/third_party/bearssl/ec_c25519_m64.c @@ -645,22 +645,22 @@ api_mul(unsigned char *G, size_t Glen, x1[3] = br_dec64le(&G[24]) & MASK63; /* - * We can use memset() to clear values, because exact-width types + * We can use br_memset() to clear values, because exact-width types * like uint64_t are guaranteed to have no padding bits or * trap representations. */ - memset(x2, 0, sizeof x2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z2, 0, sizeof z2); - memcpy(x3, x1, sizeof x1); - memcpy(z3, x2, sizeof x2); + br_memset(z2, 0, sizeof z2); + br_memcpy(x3, x1, sizeof x1); + br_memcpy(z3, x2, sizeof x2); /* * The multiplier is provided in big-endian notation, and * possibly shorter than 32 bytes. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -730,12 +730,12 @@ api_mul(unsigned char *G, size_t Glen, * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize * most non-squarings. We use x1 and x3, now useless, as temporaries. */ - memcpy(x1, z2, sizeof z2); + br_memcpy(x1, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_mul(x1, x1, x1); f255_mul(x1, x1, z2); } - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); for (i = 0; i < 14; i ++) { int j; @@ -775,7 +775,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_p256_m31.c b/third_party/bearssl/ec_p256_m31.c index b185937e1..b93fda714 100644 --- a/third_party/bearssl/ec_p256_m31.c +++ b/third_party/bearssl/ec_p256_m31.c @@ -690,7 +690,7 @@ p256_to_affine(p256_jacobian *P) * two dozen multiplications here with an addition chain, but * this would require a bit more code, and extra stack buffers. */ - memcpy(t1, P->z, sizeof P->z); + br_memcpy(t1, P->z, sizeof P->z); for (i = 0; i < 30; i ++) { square_f256(t1, t1); mul_f256(t1, t1, P->z); @@ -701,7 +701,7 @@ p256_to_affine(p256_jacobian *P) * multiplications to set bits to 1; we multiply by the original z * for setting 1 bit, and by t1 for setting 31 bits. */ - memcpy(t2, P->z, sizeof P->z); + br_memcpy(t2, P->z, sizeof P->z); for (i = 1; i < 256; i ++) { square_f256(t2, t2); switch (i) { @@ -976,8 +976,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1085,9 +1085,9 @@ p256_decode(p256_jacobian *P, const void *src, size_t len) /* * Copy coordinates to the point structure. */ - memcpy(P->x, tx, sizeof tx); - memcpy(P->y, ty, sizeof ty); - memset(P->z, 0, sizeof P->z); + br_memcpy(P->x, tx, sizeof tx); + br_memcpy(P->y, ty, sizeof ty); + br_memset(P->z, 0, sizeof P->z); P->z[0] = 1; return EQ(bad, 0); } @@ -1136,7 +1136,7 @@ p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) /* * We start with Q = 0. We process multiplier bits 2 by 2. */ - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (xlen -- > 0) { int k; @@ -1272,7 +1272,7 @@ lookup_Gwin(p256_jacobian *T, uint32_t idx) uint32_t k; size_t u; - memset(xy, 0, sizeof xy); + br_memset(xy, 0, sizeof xy); for (k = 0; k < 15; k ++) { uint32_t m; @@ -1281,9 +1281,9 @@ lookup_Gwin(p256_jacobian *T, uint32_t idx) xy[u] |= m & Gwin[k][u]; } } - memcpy(T->x, &xy[0], sizeof T->x); - memcpy(T->y, &xy[9], sizeof T->y); - memset(T->z, 0, sizeof T->z); + br_memcpy(T->x, &xy[0], sizeof T->x); + br_memcpy(T->y, &xy[9], sizeof T->y); + br_memset(T->z, 0, sizeof T->z); T->z[0] = 1; } @@ -1305,7 +1305,7 @@ p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (xlen -- > 0) { int k; diff --git a/third_party/bearssl/ec_p256_m62.c b/third_party/bearssl/ec_p256_m62.c index a43179052..6e3814ede 100644 --- a/third_party/bearssl/ec_p256_m62.c +++ b/third_party/bearssl/ec_p256_m62.c @@ -498,13 +498,13 @@ f256_invert(uint64_t *d, const uint64_t *a) uint64_t r[5], t[5]; int i; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); for (i = 0; i < 30; i ++) { f256_montysquare(t, t); f256_montymul(t, t, a); } - memcpy(r, t, sizeof t); + br_memcpy(r, t, sizeof t); for (i = 224; i >= 0; i --) { f256_montysquare(r, r); switch (i) { @@ -521,7 +521,7 @@ f256_invert(uint64_t *d, const uint64_t *a) break; } } - memcpy(d, r, sizeof r); + br_memcpy(d, r, sizeof r); } /* @@ -703,9 +703,9 @@ point_decode(p256_jacobian *P, const unsigned char *buf) * Return the point in Jacobian coordinates (and Montgomery * representation). */ - memcpy(P->x, x, sizeof x); - memcpy(P->y, y, sizeof y); - memcpy(P->z, F256_R, sizeof F256_R); + br_memcpy(P->x, x, sizeof x); + br_memcpy(P->y, y, sizeof y); + br_memcpy(P->z, F256_R, sizeof F256_R); return r; } @@ -994,8 +994,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1117,8 +1117,8 @@ p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1254,7 +1254,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (klen -- > 0) { int i; @@ -1283,7 +1283,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, * problem because we will use it only if the * bits are non-zero. */ - memset(&T, 0, sizeof T); + br_memset(&T, 0, sizeof T); for (n = 0; n < 15; n ++) { m = -(uint64_t)EQ(bits, n + 1); T.x[0] |= m & W[n].x[0]; @@ -1399,14 +1399,14 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) * extra one with coordinate Z = 1 (in Montgomery representation). */ for (i = 0; (i + 1) < num; i += 2) { - memcpy(zt, jac[i].z, sizeof zt); - memcpy(jac[i].z, jac[i + 1].z, sizeof zt); - memcpy(jac[i + 1].z, zt, sizeof zt); + br_memcpy(zt, jac[i].z, sizeof zt); + br_memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + br_memcpy(jac[i + 1].z, zt, sizeof zt); f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); } if ((num & 1) != 0) { - memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); - memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + br_memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + br_memcpy(jac[num - 1].z, F256_R, sizeof F256_R); } /* @@ -1425,7 +1425,7 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); } if ((n & 1) != 0) { - memmove(z[n >> 1], z[n], sizeof zt); + br_memmove(z[n >> 1], z[n], sizeof zt); } } diff --git a/third_party/bearssl/ec_p256_m64.c b/third_party/bearssl/ec_p256_m64.c index 71a527c36..0d8a9d64d 100644 --- a/third_party/bearssl/ec_p256_m64.c +++ b/third_party/bearssl/ec_p256_m64.c @@ -561,13 +561,13 @@ f256_invert(uint64_t *d, const uint64_t *a) uint64_t r[4], t[4]; int i; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); for (i = 0; i < 30; i ++) { f256_montysquare(t, t); f256_montymul(t, t, a); } - memcpy(r, t, sizeof t); + br_memcpy(r, t, sizeof t); for (i = 224; i >= 0; i --) { f256_montysquare(r, r); switch (i) { @@ -584,7 +584,7 @@ f256_invert(uint64_t *d, const uint64_t *a) break; } } - memcpy(d, r, sizeof r); + br_memcpy(d, r, sizeof r); } /* @@ -713,9 +713,9 @@ point_decode(p256_jacobian *P, const unsigned char *buf) * Return the point in Jacobian coordinates (and Montgomery * representation). */ - memcpy(P->x, x, sizeof x); - memcpy(P->y, y, sizeof y); - memcpy(P->z, F256_R, sizeof F256_R); + br_memcpy(P->x, x, sizeof x); + br_memcpy(P->y, y, sizeof y); + br_memcpy(P->z, F256_R, sizeof F256_R); return r; } @@ -1014,8 +1014,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1137,8 +1137,8 @@ p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1272,7 +1272,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (klen -- > 0) { int i; @@ -1301,7 +1301,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, * problem because we will use it only if the * bits are non-zero. */ - memset(&T, 0, sizeof T); + br_memset(&T, 0, sizeof T); for (n = 0; n < 15; n ++) { m = -(uint64_t)EQ(bits, n + 1); T.x[0] |= m & W[n].x[0]; @@ -1415,14 +1415,14 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) * extra one with coordinate Z = 1 (in Montgomery representation). */ for (i = 0; (i + 1) < num; i += 2) { - memcpy(zt, jac[i].z, sizeof zt); - memcpy(jac[i].z, jac[i + 1].z, sizeof zt); - memcpy(jac[i + 1].z, zt, sizeof zt); + br_memcpy(zt, jac[i].z, sizeof zt); + br_memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + br_memcpy(jac[i + 1].z, zt, sizeof zt); f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); } if ((num & 1) != 0) { - memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); - memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + br_memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + br_memcpy(jac[num - 1].z, F256_R, sizeof F256_R); } /* @@ -1441,7 +1441,7 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); } if ((n & 1) != 0) { - memmove(z[n >> 1], z[n], sizeof zt); + br_memmove(z[n >> 1], z[n], sizeof zt); } } diff --git a/third_party/bearssl/ec_prime_i31.c b/third_party/bearssl/ec_prime_i31.c index b205f367a..56fc6ca66 100644 --- a/third_party/bearssl/ec_prime_i31.c +++ b/third_party/bearssl/ec_prime_i31.c @@ -461,8 +461,8 @@ run_code(jacobian *P1, const jacobian *P2, /* * Copy the two operands in the dedicated registers. */ - memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); - memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); /* * Run formulas. @@ -484,7 +484,7 @@ run_code(jacobian *P1, const jacobian *P2, unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; case 0: - memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); + br_memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); break; case 1: ctl = br_i31_add(t[d], t[a], 1); @@ -513,7 +513,7 @@ run_code(jacobian *P1, const jacobian *P2, /* * Copy back result. */ - memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); return r; } @@ -523,7 +523,7 @@ set_one(uint32_t *x, const uint32_t *p) size_t plen; plen = (p[0] + 63) >> 5; - memset(x, 0, plen * sizeof *x); + br_memset(x, 0, plen * sizeof *x); x[0] = p[0]; x[1] = 0x00000001; } @@ -531,7 +531,7 @@ set_one(uint32_t *x, const uint32_t *p) static void point_zero(jacobian *P, const curve_params *cc) { - memset(P, 0, sizeof *P); + br_memset(P, 0, sizeof *P); P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; } @@ -568,9 +568,9 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, uint32_t qz; jacobian P2, P3, Q, T, U; - memcpy(&P2, P, sizeof P2); + br_memcpy(&P2, P, sizeof P2); point_double(&P2, cc); - memcpy(&P3, P, sizeof P3); + br_memcpy(&P3, P, sizeof P3); point_add(&P3, &P2, cc); point_zero(&Q, cc); @@ -584,8 +584,8 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, point_double(&Q, cc); point_double(&Q, cc); - memcpy(&T, P, sizeof T); - memcpy(&U, &Q, sizeof U); + br_memcpy(&T, P, sizeof T); + br_memcpy(&U, &Q, sizeof U); bits = (*x >> k) & (uint32_t)3; bnz = NEQ(bits, 0); CCOPY(EQ(bits, 2), &T, &P2, sizeof T); @@ -597,7 +597,7 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, } x ++; } - memcpy(P, &Q, sizeof Q); + br_memcpy(P, &Q, sizeof Q); } /* @@ -652,8 +652,8 @@ point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) * Convert coordinates and check that the point is valid. */ zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t); - memcpy(Q.c[0], cc->R2, zlen); - memcpy(Q.c[1], cc->b, zlen); + br_memcpy(Q.c[0], cc->R2, zlen); + br_memcpy(Q.c[1], cc->b, zlen); set_one(Q.c[2], cc->p); r &= ~run_code(P, &Q, cc, code_check); return r; @@ -677,7 +677,7 @@ point_encode(void *dst, const jacobian *P, const curve_params *cc) xbl -= (xbl >> 5); plen = (xbl + 7) >> 3; buf[0] = 0x04; - memcpy(&Q, P, sizeof *P); + br_memcpy(&Q, P, sizeof *P); set_one(T.c[2], cc->p); run_code(&Q, &T, cc, code_affine); br_i31_encode(buf + 1, plen, Q.c[0]); @@ -752,7 +752,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ecdsa_atr.c b/third_party/bearssl/ecdsa_atr.c index 3a11226e4..c4c1e932a 100644 --- a/third_party/bearssl/ecdsa_atr.c +++ b/third_party/bearssl/ecdsa_atr.c @@ -126,9 +126,9 @@ br_ecdsa_asn1_to_raw(void *sig, size_t sig_len) */ zlen = rlen > slen ? rlen : slen; sig_len = zlen << 1; - memset(tmp, 0, sig_len); - memcpy(tmp + zlen - rlen, r, rlen); - memcpy(tmp + sig_len - slen, s, slen); - memcpy(sig, tmp, sig_len); + br_memset(tmp, 0, sig_len); + br_memcpy(tmp + zlen - rlen, r, rlen); + br_memcpy(tmp + sig_len - slen, s, slen); + br_memcpy(sig, tmp, sig_len); return sig_len; } diff --git a/third_party/bearssl/ecdsa_i31_vrfy_asn1.c b/third_party/bearssl/ecdsa_i31_vrfy_asn1.c index 4161aaaa3..5e9db87a7 100644 --- a/third_party/bearssl/ecdsa_i31_vrfy_asn1.c +++ b/third_party/bearssl/ecdsa_i31_vrfy_asn1.c @@ -42,7 +42,7 @@ br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, if (sig_len > ((sizeof rsig) >> 1)) { return 0; } - memcpy(rsig, sig, sig_len); + br_memcpy(rsig, sig, sig_len); sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); } diff --git a/third_party/bearssl/ecdsa_i31_vrfy_raw.c b/third_party/bearssl/ecdsa_i31_vrfy_raw.c index 259477fdb..f1e76c1c4 100644 --- a/third_party/bearssl/ecdsa_i31_vrfy_raw.c +++ b/third_party/bearssl/ecdsa_i31_vrfy_raw.c @@ -113,7 +113,7 @@ br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, * the inversion (because (1/s)*R = 1/(s/R)). */ br_i31_from_monty(s, n, n0i); - memcpy(tx, cd->order, nlen); + br_memcpy(tx, cd->order, nlen); tx[nlen - 1] -= 2; br_i31_modpow(s, tx, nlen, n, n0i, t1, t2); @@ -143,7 +143,7 @@ br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, * Compute the point x*Q + y*G. */ ulen = cd->generator_len; - memcpy(eU, pk->q, ulen); + br_memcpy(eU, pk->q, ulen); res = impl->muladd(eU, NULL, ulen, tx, nlen, ty, nlen, cd->curve); diff --git a/third_party/bearssl/gcm.c b/third_party/bearssl/gcm.c index ede5f0872..bb6911ec1 100644 --- a/third_party/bearssl/gcm.c +++ b/third_party/bearssl/gcm.c @@ -66,8 +66,8 @@ br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh) * with an all-zero IV and a zero counter, to CTR-encrypt an * all-zero block. */ - memset(ctx->h, 0, sizeof ctx->h); - memset(iv, 0, sizeof iv); + br_memset(ctx->h, 0, sizeof ctx->h); + br_memset(iv, 0, sizeof iv); (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h); } @@ -85,21 +85,21 @@ br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len) * (both 12-byte IV and 32-bit counter). */ if (len == 12) { - memcpy(ctx->j0_1, iv, 12); + br_memcpy(ctx->j0_1, iv, 12); ctx->j0_2 = 1; } else { unsigned char ty[16], tmp[16]; - memset(ty, 0, sizeof ty); + br_memset(ty, 0, sizeof ty); ctx->gh(ty, ctx->h, iv, len); - memset(tmp, 0, 8); + br_memset(tmp, 0, 8); br_enc64be(tmp + 8, (uint64_t)len << 3); ctx->gh(ty, ctx->h, tmp, 16); - memcpy(ctx->j0_1, ty, 12); + br_memcpy(ctx->j0_1, ty, 12); ctx->j0_2 = br_dec32be(ty + 12); } ctx->jc = ctx->j0_2 + 1; - memset(ctx->y, 0, sizeof ctx->y); + br_memset(ctx->y, 0, sizeof ctx->y); ctx->count_aad = 0; ctx->count_ctr = 0; } @@ -120,11 +120,11 @@ br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) clen = 16 - ptr; if (len < clen) { - memcpy(ctx->buf + ptr, data, len); + br_memcpy(ctx->buf + ptr, data, len); ctx->count_aad += (uint64_t)len; return; } - memcpy(ctx->buf + ptr, data, clen); + br_memcpy(ctx->buf + ptr, data, clen); ctx->gh(ctx->y, ctx->h, ctx->buf, 16); data = (const unsigned char *)data + clen; len -= clen; @@ -138,7 +138,7 @@ br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) */ dlen = len & ~(size_t)15; ctx->gh(ctx->y, ctx->h, data, dlen); - memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); + br_memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); ctx->count_aad += (uint64_t)len; } @@ -216,7 +216,7 @@ br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len) */ size_t u; - memset(ctx->buf, 0, sizeof ctx->buf); + br_memset(ctx->buf, 0, sizeof ctx->buf); ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, ctx->buf, 16); for (u = 0; u < len; u ++) { @@ -259,7 +259,7 @@ br_gcm_get_tag(br_gcm_context *ctx, void *tag) * Tag is the GHASH output XORed with the encryption of the * nonce with the initial counter value. */ - memcpy(tag, ctx->y, 16); + br_memcpy(tag, ctx->y, 16); (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16); } @@ -270,7 +270,7 @@ br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len) unsigned char tmp[16]; br_gcm_get_tag(ctx, tmp); - memcpy(tag, tmp, len); + br_memcpy(tag, tmp, len); } /* see bearssl_aead.h */ diff --git a/third_party/bearssl/ghash_ctmul.c b/third_party/bearssl/ghash_ctmul.c index 362320252..8a10ce772 100644 --- a/third_party/bearssl/ghash_ctmul.c +++ b/third_party/bearssl/ghash_ctmul.c @@ -232,8 +232,8 @@ br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) buf += 16; len -= 16; } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); src = tmp; len = 0; } @@ -332,7 +332,7 @@ br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); } - memcpy(yw, zw + 4, sizeof yw); + br_memcpy(yw, zw + 4, sizeof yw); } /* diff --git a/third_party/bearssl/ghash_ctmul64.c b/third_party/bearssl/ghash_ctmul64.c index a46f16fee..cd762fa74 100644 --- a/third_party/bearssl/ghash_ctmul64.c +++ b/third_party/bearssl/ghash_ctmul64.c @@ -105,8 +105,8 @@ br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len) buf += 16; len -= 16; } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); src = tmp; len = 0; } diff --git a/third_party/bearssl/ghash_pclmul.c b/third_party/bearssl/ghash_pclmul.c index a58e7dc02..87da300d0 100644 --- a/third_party/bearssl/ghash_pclmul.c +++ b/third_party/bearssl/ghash_pclmul.c @@ -228,7 +228,7 @@ pclmulqdq11(__m128i x, __m128i y) } while (0) /* see bearssl_hash.h */ -BR_TARGET("ssse3,pclmul") +BR_TARGET("ssse3,pclmul") BR_SSE_FUNCTION void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) { @@ -250,8 +250,8 @@ br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) buf2 = buf1 + (num4 << 6); num1 = (len + 15) >> 4; if ((len & 15) != 0) { - memcpy(tmp, buf2, len); - memset(tmp + len, 0, (num1 << 4) - len); + br_memcpy(tmp, buf2, len); + br_memset(tmp + len, 0, (num1 << 4) - len); buf2 = tmp; } diff --git a/third_party/bearssl/hmac.c b/third_party/bearssl/hmac.c index b43879887..b4ab81d83 100644 --- a/third_party/bearssl/hmac.c +++ b/third_party/bearssl/hmac.c @@ -42,11 +42,11 @@ process_key(const br_hash_class **hc, void *ks, size_t blen, u; blen = block_size(*hc); - memcpy(tmp, key, key_len); + br_memcpy(tmp, key, key_len); for (u = 0; u < key_len; u ++) { tmp[u] ^= (unsigned char)bb; } - memset(tmp + key_len, bb, blen - key_len); + br_memset(tmp + key_len, bb, blen - key_len); (*hc)->init(hc); (*hc)->update(hc, tmp, blen); (*hc)->state(hc, ks); @@ -85,7 +85,7 @@ br_hmac_init(br_hmac_context *ctx, blen = block_size(dig); dig->init(&ctx->dig.vtable); dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen); - memcpy(ctx->kso, kc->kso, sizeof kc->kso); + br_memcpy(ctx->kso, kc->kso, sizeof kc->kso); hlen = br_digest_size(dig); if (out_len > 0 && out_len < hlen) { hlen = out_len; @@ -117,6 +117,6 @@ br_hmac_out(const br_hmac_context *ctx, void *out) hlen = br_digest_size(dig); dig->update(&hc.vtable, tmp, hlen); dig->out(&hc.vtable, tmp); - memcpy(out, tmp, ctx->out_len); + br_memcpy(out, tmp, ctx->out_len); return ctx->out_len; } diff --git a/third_party/bearssl/hmac_ct.c b/third_party/bearssl/hmac_ct.c index e1c1d8024..546903767 100644 --- a/third_party/bearssl/hmac_ct.c +++ b/third_party/bearssl/hmac_ct.c @@ -150,7 +150,7 @@ br_hmac_outCT(const br_hmac_context *ctx, * Hash state is obtained whenever we reach a full block. This * is the result we want if and only if u == kz. */ - memset(tmp2, 0, sizeof tmp2); + br_memset(tmp2, 0, sizeof tmp2); for (u = 0; u < km; u ++) { uint32_t v; uint32_t d, e, x0, x1; @@ -188,6 +188,6 @@ br_hmac_outCT(const br_hmac_context *ctx, dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs); dig->update(&hc.vtable, tmp2, hlen); dig->out(&hc.vtable, tmp2); - memcpy(out, tmp2, ctx->out_len); + br_memcpy(out, tmp2, ctx->out_len); return ctx->out_len; } diff --git a/third_party/bearssl/hmac_drbg.c b/third_party/bearssl/hmac_drbg.c index d746756df..46f70087c 100644 --- a/third_party/bearssl/hmac_drbg.c +++ b/third_party/bearssl/hmac_drbg.c @@ -33,8 +33,8 @@ br_hmac_drbg_init(br_hmac_drbg_context *ctx, ctx->vtable = &br_hmac_drbg_vtable; hlen = br_digest_size(digest_class); - memset(ctx->K, 0x00, hlen); - memset(ctx->V, 0x01, hlen); + br_memset(ctx->K, 0x00, hlen); + br_memset(ctx->V, 0x01, hlen); ctx->digest_class = digest_class; br_hmac_drbg_update(ctx, seed, len); } @@ -64,7 +64,7 @@ br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len) if (clen > len) { clen = len; } - memcpy(buf, ctx->V, clen); + br_memcpy(buf, ctx->V, clen); buf += clen; len -= clen; } diff --git a/third_party/bearssl/i31_encode.c b/third_party/bearssl/i31_encode.c index b6b40c456..2ccadca88 100644 --- a/third_party/bearssl/i31_encode.c +++ b/third_party/bearssl/i31_encode.c @@ -35,7 +35,7 @@ br_i31_encode(void *dst, size_t len, const uint32_t *x) xlen = (x[0] + 31) >> 5; if (xlen == 0) { - memset(dst, 0, len); + br_memset(dst, 0, len); return; } buf = (unsigned char *)dst + len; diff --git a/third_party/bearssl/i31_moddiv.c b/third_party/bearssl/i31_moddiv.c index 995059119..0444b0b39 100644 --- a/third_party/bearssl/i31_moddiv.c +++ b/third_party/bearssl/i31_moddiv.c @@ -323,9 +323,9 @@ br_i31_moddiv(uint32_t *x, const uint32_t *y, const uint32_t *m, uint32_t m0i, b = a + len; u = x + 1; v = b + len; - memcpy(a, y + 1, len * sizeof *y); - memcpy(b, m + 1, len * sizeof *m); - memset(v, 0, len * sizeof *v); + br_memcpy(a, y + 1, len * sizeof *y); + br_memcpy(b, m + 1, len * sizeof *m); + br_memset(v, 0, len * sizeof *v); /* * Loop below ensures that a and b are reduced by some bits each, diff --git a/third_party/bearssl/i31_modpow.c b/third_party/bearssl/i31_modpow.c index 4ef3f5d5a..eaeeb9e2c 100644 --- a/third_party/bearssl/i31_modpow.c +++ b/third_party/bearssl/i31_modpow.c @@ -49,7 +49,7 @@ br_i31_modpow(uint32_t *x, * * Note that there is no need to call br_i32_from_monty(). */ - memcpy(t1, x, mlen); + br_memcpy(t1, x, mlen); br_i31_to_monty(t1, m); br_i31_zero(x, m[0]); x[1] = 1; @@ -60,6 +60,6 @@ br_i31_modpow(uint32_t *x, br_i31_montymul(t2, x, t1, m, m0i); CCOPY(ctl, x, t2, mlen); br_i31_montymul(t2, t1, t1, m, m0i); - memcpy(t1, t2, mlen); + br_memcpy(t1, t2, mlen); } } diff --git a/third_party/bearssl/i31_modpow2.c b/third_party/bearssl/i31_modpow2.c index 0b8f8cf7e..43248e395 100644 --- a/third_party/bearssl/i31_modpow2.c +++ b/third_party/bearssl/i31_modpow2.c @@ -71,9 +71,9 @@ br_i31_modpow_opt(uint32_t *x, * t2[k] is set to x^k (for k >= 1). */ if (win_len == 1) { - memcpy(t2, x, mlen); + br_memcpy(t2, x, mlen); } else { - memcpy(t2 + mwlen, x, mlen); + br_memcpy(t2 + mwlen, x, mlen); base = t2 + mwlen; for (u = 2; u < ((unsigned)1 << win_len); u ++) { br_i31_montymul(base + mwlen, base, x, m, m0i); @@ -121,7 +121,7 @@ br_i31_modpow_opt(uint32_t *x, */ for (i = 0; i < k; i ++) { br_i31_montymul(t1, x, x, m, m0i); - memcpy(x, t1, mlen); + br_memcpy(x, t1, mlen); } /* diff --git a/third_party/bearssl/i31_muladd.c b/third_party/bearssl/i31_muladd.c index eecd9e2c6..479d802ba 100644 --- a/third_party/bearssl/i31_muladd.c +++ b/third_party/bearssl/i31_muladd.c @@ -83,14 +83,14 @@ br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) hi = x[mlen]; if (mblr == 0) { a0 = x[mlen]; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + br_memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); x[1] = z; a1 = x[mlen]; b0 = m[mlen]; } else { a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & 0x7FFFFFFF; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + br_memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); x[1] = z; a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & 0x7FFFFFFF; diff --git a/third_party/bearssl/i31_reduce.c b/third_party/bearssl/i31_reduce.c index 5c9523ed1..74bba6a9a 100644 --- a/third_party/bearssl/i31_reduce.c +++ b/third_party/bearssl/i31_reduce.c @@ -46,7 +46,7 @@ br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) a_bitlen = a[0]; alen = (a_bitlen + 31) >> 5; if (a_bitlen < m_bitlen) { - memcpy(x + 1, a + 1, alen * sizeof *a); + br_memcpy(x + 1, a + 1, alen * sizeof *a); for (u = alen; u < mlen; u ++) { x[u + 1] = 0; } @@ -58,7 +58,7 @@ br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) * We must thus copy N-1 words, and input the remaining words * one by one. */ - memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); + br_memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); x[mlen] = 0; for (u = 1 + alen - mlen; u > 0; u --) { br_i31_muladd_small(x, a[u], m); diff --git a/third_party/bearssl/i62_modpow2.c b/third_party/bearssl/i62_modpow2.c index 2db537f0a..d75e3795b 100644 --- a/third_party/bearssl/i62_modpow2.c +++ b/third_party/bearssl/i62_modpow2.c @@ -154,7 +154,7 @@ montymul(uint64_t *d, const uint64_t *x, const uint64_t *y, size_t u, num4; num4 = 1 + ((num - 1) & ~(size_t)3); - memset(d, 0, num * sizeof *d); + br_memset(d, 0, num * sizeof *d); dh = 0; for (u = 0; u < num; u ++) { size_t v; @@ -335,11 +335,11 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, * t2[k] is set to x^k (for k >= 1). */ if (win_len == 1) { - memcpy(t2, x, mw62num * sizeof *x); + br_memcpy(t2, x, mw62num * sizeof *x); } else { uint64_t *base; - memcpy(t2 + mw62num, x, mw62num * sizeof *x); + br_memcpy(t2 + mw62num, x, mw62num * sizeof *x); base = t2 + mw62num; for (u = 2; u < ((unsigned)1 << win_len); u ++) { montymul(base + mw62num, base, x, m, mw62num, m0i); @@ -401,7 +401,7 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, */ for (i = 0; i < k; i ++) { montymul(t1, x, x, m, mw62num, m0i); - memcpy(x, t1, mw62num * sizeof *x); + br_memcpy(x, t1, mw62num * sizeof *x); } /* @@ -413,7 +413,7 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, if (win_len > 1) { uint64_t *base; - memset(t2, 0, mw62num * sizeof *t2); + br_memset(t2, 0, mw62num * sizeof *t2); base = t2 + mw62num; for (u = 1; u < ((uint32_t)1 << k); u ++) { uint64_t mask; diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index 3cc6b4c09..e17ea7bae 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -35,6 +35,23 @@ #include "config.h" #include "bearssl.h" +/* ==== BEG ClassiCube specific ==== */ +#include "bearssl_stdlib.h" + +/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ +/* Also disable when compiling the legacy windows 9x build */ +#if defined NXDK || defined CC_BUILD_NOSTDLIB + #define BR_AES_X86NI 0 + #define BR_ENABLE_INTRINSICS 0 + #define BR_SSE2 0 +#endif + +/* intrin.h doesn't exist in older TinyC */ +#if defined __TINYC__ + #define BR_INT128 0 +#endif +/* ==== END ClassiCube specific ==== */ + /* * On MSVC, disable the warning about applying unary minus on an * unsigned type: it is standard, we do it all the time, and for @@ -290,106 +307,22 @@ #endif /* - * RDRAND intrinsics are available on x86 (32-bit and 64-bit) with - * GCC 4.6+, Clang 3.7+ and MSC 2012+. + * Detect support for unaligned accesses with known endianness. + * + * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned + * accesses. + * + * POWER/PowerPC allows unaligned accesses when big-endian. */ -#ifndef BR_RDRAND -#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012) -#define BR_RDRAND 1 -#endif +#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED + +#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 +#define BR_LE_UNALIGNED 1 +#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ + && __BIG_ENDIAN__ +#define BR_BE_UNALIGNED 1 #endif -/* - * Determine type of OS for random number generation. Macro names and - * values are documented on: - * https://sourceforge.net/p/predef/wiki/OperatingSystems/ - * - * Win32's CryptGenRandom() should be available on Windows systems. - * - * /dev/urandom should work on all Unix-like systems (including macOS X). - * - * getentropy() is present on Linux (Glibc 2.25+), FreeBSD (12.0+) and - * OpenBSD (5.6+). For OpenBSD, there does not seem to be easy to use - * macros to test the minimum version, so we just assume that it is - * recent enough (last version without getentropy() has gone out of - * support in May 2015). - * - * Ideally we should use getentropy() on macOS (10.12+) too, but I don't - * know how to test the exact OS version with preprocessor macros. - * - * TODO: enrich the list of detected system. - */ - -#ifndef BR_USE_URANDOM -#if defined _AIX \ - || defined __ANDROID__ \ - || defined __FreeBSD__ \ - || defined __NetBSD__ \ - || defined __OpenBSD__ \ - || defined __DragonFly__ \ - || defined __linux__ \ - || (defined __sun && (defined __SVR4 || defined __svr4__)) \ - || (defined __APPLE__ && defined __MACH__) -#define BR_USE_URANDOM 1 -#endif -#endif - -#ifndef BR_USE_GETENTROPY -#if (defined __linux__ \ - && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \ - || (defined __FreeBSD__ && __FreeBSD__ >= 12) \ - || defined __OpenBSD__ -#define BR_USE_GETENTROPY 1 -#endif -#endif - -#ifndef BR_USE_WIN32_RAND -#if defined _WIN32 || defined _WIN64 -#define BR_USE_WIN32_RAND 1 -#endif -#endif - -/* - * POWER8 crypto support. We rely on compiler macros for the - * architecture, since we do not have a reliable, simple way to detect - * the required support at runtime (we could try running an opcode, and - * trapping the exception or signal on illegal instruction, but this - * induces some non-trivial OS dependencies that we would prefer to - * avoid if possible). - */ -#ifndef BR_POWER8 -#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__) -#define BR_POWER8 1 -#endif -#endif - -/* - * Detect endinanness on POWER8. - */ -#if BR_POWER8 -#if defined BR_POWER8_LE -#undef BR_POWER8_BE -#if BR_POWER8_LE -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_BE 1 -#endif -#elif defined BR_POWER8_BE -#undef BR_POWER8_LE -#if BR_POWER8_BE -#define BR_POWER8_LE 0 -#else -#define BR_POWER8_LE 1 -#endif -#else -#if __LITTLE_ENDIAN__ -#define BR_POWER8_LE 1 -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_LE 0 -#define BR_POWER8_BE 1 -#endif -#endif #endif /* @@ -408,21 +341,11 @@ * * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned * accesses. - * - * POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and - * later also allow unaligned accesses when little-endian. */ -#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED +#if !defined BR_LE_UNALIGNED #if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 #define BR_LE_UNALIGNED 1 -#elif BR_POWER8_BE -#define BR_BE_UNALIGNED 1 -#elif BR_POWER8_LE -#define BR_LE_UNALIGNED 1 -#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ - && __BIG_ENDIAN__ -#define BR_BE_UNALIGNED 1 #endif #endif @@ -697,7 +620,7 @@ static inline void br_multihash_copyimpl(br_multihash_context *dst, const br_multihash_context *src) { - memcpy((void *)dst->impl, src->impl, sizeof src->impl); + br_memcpy((void *)dst->impl, src->impl, sizeof src->impl); } /* ==================================================================== */ @@ -1207,7 +1130,7 @@ static inline void br_i32_zero(uint32_t *x, uint32_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); + br_memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); } /* @@ -1355,7 +1278,7 @@ static inline void br_i31_zero(uint32_t *x, uint32_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); + br_memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); } /* @@ -1509,7 +1432,7 @@ static inline void br_i15_zero(uint16_t *x, uint16_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); + br_memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); } uint32_t br_i15_iszero(const uint16_t *x); @@ -2477,6 +2400,18 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, #endif +/* BEG classicube specific */ +/* Fix issue where 32 bit GCC aligns stack to 4 bytes, but will still */ +/* generate instructions expecting the stack to be _16_ byte aligned */ +/* https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html */ +/* TODO is this needed for MSVC ? */ +#if (BR_GCC || BR_CLANG) && BR_i386 && !BR_amd64 + #define BR_SSE_FUNCTION __attribute__((force_align_arg_pointer)) +#else + #define BR_SSE_FUNCTION +#endif +/* END classicube specific */ + /* ==================================================================== */ #endif diff --git a/third_party/bearssl/md5.c b/third_party/bearssl/md5.c index 0df7abe01..bf8a9ffd8 100644 --- a/third_party/bearssl/md5.c +++ b/third_party/bearssl/md5.c @@ -119,7 +119,7 @@ void br_md5_init(br_md5_context *cc) { cc->vtable = &br_md5_vtable; - memcpy(cc->val, br_md5_IV, sizeof cc->val); + br_memcpy(cc->val, br_md5_IV, sizeof cc->val); cc->count = 0; } @@ -139,7 +139,7 @@ br_md5_update(br_md5_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -160,15 +160,15 @@ br_md5_out(const br_md5_context *cc, void *dst) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_md5_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64le(buf + 56, cc->count << 3); br_md5_round(buf, val); diff --git a/third_party/bearssl/md5sha1.c b/third_party/bearssl/md5sha1.c index f701aeede..63767d8e2 100644 --- a/third_party/bearssl/md5sha1.c +++ b/third_party/bearssl/md5sha1.c @@ -29,8 +29,8 @@ void br_md5sha1_init(br_md5sha1_context *cc) { cc->vtable = &br_md5sha1_vtable; - memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); - memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); + br_memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); + br_memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); cc->count = 0; } @@ -50,7 +50,7 @@ br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -76,17 +76,17 @@ br_md5sha1_out(const br_md5sha1_context *cc, void *dst) count = cc->count; ptr = (size_t)count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val_md5, cc->val_md5, sizeof val_md5); - memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val_md5, cc->val_md5, sizeof val_md5); + br_memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_md5_round(buf, val_md5); br_sha1_round(buf, val_sha1); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } count <<= 3; br_enc64le(buf + 56, count); diff --git a/third_party/bearssl/multihash.c b/third_party/bearssl/multihash.c index b6df2e0ed..a91fcf11d 100644 --- a/third_party/bearssl/multihash.c +++ b/third_party/bearssl/multihash.c @@ -77,7 +77,7 @@ br_multihash_zero(br_multihash_context *ctx) * This is not standard, but yields very short and efficient code, * and it works "everywhere". */ - memset(ctx, 0, sizeof *ctx); + br_memset(ctx, 0, sizeof *ctx); } /* see bearssl_hash.h */ @@ -117,7 +117,7 @@ br_multihash_update(br_multihash_context *ctx, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(ctx->buf + ptr, buf, clen); + br_memcpy(ctx->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; diff --git a/third_party/bearssl/poly1305_ctmul.c b/third_party/bearssl/poly1305_ctmul.c index 150e610a9..1e9ef8d91 100644 --- a/third_party/bearssl/poly1305_ctmul.c +++ b/third_party/bearssl/poly1305_ctmul.c @@ -78,8 +78,8 @@ poly1305_inner(uint32_t *acc, const uint32_t *r, const void *data, size_t len) * If there is a partial block, right-pad it with zeros. */ if (len < 16) { - memset(tmp, 0, sizeof tmp); - memcpy(tmp, buf, len); + br_memset(tmp, 0, sizeof tmp); + br_memcpy(tmp, buf, len); buf = tmp; len = 16; } @@ -158,7 +158,7 @@ br_poly1305_ctmul_run(const void *key, const void *iv, * Compute the MAC key. The 'r' value is the first 16 bytes of * pkey[]. */ - memset(pkey, 0, sizeof pkey); + br_memset(pkey, 0, sizeof pkey); ichacha(key, iv, 0, pkey, sizeof pkey); /* @@ -189,7 +189,7 @@ br_poly1305_ctmul_run(const void *key, const void *iv, /* * Accumulator is 0. */ - memset(acc, 0, sizeof acc); + br_memset(acc, 0, sizeof acc); /* * Process the additional authenticated data, ciphertext, and diff --git a/third_party/bearssl/poly1305_ctmulq.c b/third_party/bearssl/poly1305_ctmulq.c index b00683a68..1c31cbb10 100644 --- a/third_party/bearssl/poly1305_ctmulq.c +++ b/third_party/bearssl/poly1305_ctmulq.c @@ -241,8 +241,8 @@ poly1305_inner_small(uint64_t *acc, uint64_t *r, const void *data, size_t len) unsigned char tmp[16]; if (len < 16) { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); buf = tmp; len = 16; } @@ -327,7 +327,7 @@ br_poly1305_ctmulq_run(const void *key, const void *iv, * Compute the MAC key. The 'r' value is the first 16 bytes of * pkey[]. */ - memset(pkey, 0, sizeof pkey); + br_memset(pkey, 0, sizeof pkey); ichacha(key, iv, 0, pkey, sizeof pkey); /* diff --git a/third_party/bearssl/prf_md5sha1.c b/third_party/bearssl/prf_md5sha1.c index 3212833ab..67839ddb4 100644 --- a/third_party/bearssl/prf_md5sha1.c +++ b/third_party/bearssl/prf_md5sha1.c @@ -35,7 +35,7 @@ br_tls10_prf(void *dst, size_t len, s1 = secret; slen = (secret_len + 1) >> 1; - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_md5_vtable, s1, slen, label, seed_num, seed); br_tls_phash(dst, len, &br_sha1_vtable, diff --git a/third_party/bearssl/prf_sha256.c b/third_party/bearssl/prf_sha256.c index 76041de87..c809f2577 100644 --- a/third_party/bearssl/prf_sha256.c +++ b/third_party/bearssl/prf_sha256.c @@ -30,7 +30,7 @@ br_tls12_sha256_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, size_t seed_num, const br_tls_prf_seed_chunk *seed) { - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_sha256_vtable, secret, secret_len, label, seed_num, seed); } diff --git a/third_party/bearssl/prf_sha384.c b/third_party/bearssl/prf_sha384.c index c20c4e65f..40b63c0ce 100644 --- a/third_party/bearssl/prf_sha384.c +++ b/third_party/bearssl/prf_sha384.c @@ -30,7 +30,7 @@ br_tls12_sha384_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, size_t seed_num, const br_tls_prf_seed_chunk *seed) { - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_sha384_vtable, secret, secret_len, label, seed_num, seed); } diff --git a/third_party/bearssl/rsa_i31_pkcs1_vrfy.c b/third_party/bearssl/rsa_i31_pkcs1_vrfy.c index e79a002d7..03c01e3eb 100644 --- a/third_party/bearssl/rsa_i31_pkcs1_vrfy.c +++ b/third_party/bearssl/rsa_i31_pkcs1_vrfy.c @@ -35,7 +35,7 @@ br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, if (xlen > (sizeof sig)) { return 0; } - memcpy(sig, x, xlen); + br_memcpy(sig, x, xlen); if (!br_rsa_i31_public(sig, xlen, pk)) { return 0; } diff --git a/third_party/bearssl/rsa_i31_priv.c b/third_party/bearssl/rsa_i31_priv.c index b1e1244e2..0cb24b915 100644 --- a/third_party/bearssl/rsa_i31_priv.c +++ b/third_party/bearssl/rsa_i31_priv.c @@ -133,7 +133,7 @@ br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk) * Move the decoded p to another temporary buffer. */ mp = mq + 2 * fwlen; - memmove(mp, t1, fwlen * sizeof *t1); + br_memmove(mp, t1, fwlen * sizeof *t1); /* * Compute s2 = x^dq mod q. diff --git a/third_party/bearssl/rsa_i62_pkcs1_vrfy.c b/third_party/bearssl/rsa_i62_pkcs1_vrfy.c index 6519161b1..fb84a11ee 100644 --- a/third_party/bearssl/rsa_i62_pkcs1_vrfy.c +++ b/third_party/bearssl/rsa_i62_pkcs1_vrfy.c @@ -37,7 +37,7 @@ br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, if (xlen > (sizeof sig)) { return 0; } - memcpy(sig, x, xlen); + br_memcpy(sig, x, xlen); if (!br_rsa_i62_public(sig, xlen, pk)) { return 0; } diff --git a/third_party/bearssl/rsa_i62_priv.c b/third_party/bearssl/rsa_i62_priv.c index f0da60065..414278f01 100644 --- a/third_party/bearssl/rsa_i62_priv.c +++ b/third_party/bearssl/rsa_i62_priv.c @@ -135,7 +135,7 @@ br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk) * Move the decoded p to another temporary buffer. */ mp = (uint32_t *)(tmp + 2 * fwlen); - memmove(mp, t1, 2 * fwlen * sizeof *t1); + br_memmove(mp, t1, 2 * fwlen * sizeof *t1); /* * Compute s2 = x^dq mod q. diff --git a/third_party/bearssl/rsa_pkcs1_sig_unpad.c b/third_party/bearssl/rsa_pkcs1_sig_unpad.c index c8ae08fa8..aac4998e0 100644 --- a/third_party/bearssl/rsa_pkcs1_sig_unpad.c +++ b/third_party/bearssl/rsa_pkcs1_sig_unpad.c @@ -71,7 +71,7 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, * The comparison is valid because we made sure that the signature * is at least 11 bytes long. */ - if (memcmp(sig, pad1, sizeof pad1) != 0) { + if (br_memcmp(sig, pad1, sizeof pad1) != 0) { return 0; } for (u = sizeof pad1; u < sig_len; u ++) { @@ -93,7 +93,7 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, } else { x3 = hash_oid[0]; pad_len = x3 + 9; - memset(pad2, 0, pad_len); + br_memset(pad2, 0, pad_len); zlen = sig_len - u - hash_len; if (zlen == pad_len) { x2 = x3 + 2; @@ -109,13 +109,13 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, pad2[3] = 0x30; pad2[4] = x2; pad2[5] = 0x06; - memcpy(pad2 + 6, hash_oid, x3 + 1); + br_memcpy(pad2 + 6, hash_oid, x3 + 1); pad2[pad_len - 2] = 0x04; pad2[pad_len - 1] = hash_len; - if (memcmp(pad2, sig + u, pad_len) != 0) { + if (br_memcmp(pad2, sig + u, pad_len) != 0) { return 0; } } - memcpy(hash_out, sig + sig_len - hash_len, hash_len); + br_memcpy(hash_out, sig + sig_len - hash_len, hash_len); return 1; } diff --git a/third_party/bearssl/sha1.c b/third_party/bearssl/sha1.c index 4f65d8460..bce4baae8 100644 --- a/third_party/bearssl/sha1.c +++ b/third_party/bearssl/sha1.c @@ -101,7 +101,7 @@ void br_sha1_init(br_sha1_context *cc) { cc->vtable = &br_sha1_vtable; - memcpy(cc->val, br_sha1_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha1_IV, sizeof cc->val); cc->count = 0; } @@ -121,7 +121,7 @@ br_sha1_update(br_sha1_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -142,15 +142,15 @@ br_sha1_out(const br_sha1_context *cc, void *dst) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_sha1_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64be(buf + 56, cc->count << 3); br_sha1_round(buf, val); diff --git a/third_party/bearssl/sha2big.c b/third_party/bearssl/sha2big.c index 5be92ed56..badca0c59 100644 --- a/third_party/bearssl/sha2big.c +++ b/third_party/bearssl/sha2big.c @@ -156,7 +156,7 @@ sha2big_update(br_sha384_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -175,15 +175,15 @@ sha2big_out(const br_sha384_context *cc, void *dst, int num) size_t ptr; ptr = (size_t)cc->count & 127; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 112) { - memset(buf + ptr, 0, 128 - ptr); + br_memset(buf + ptr, 0, 128 - ptr); sha2big_round(buf, val); - memset(buf, 0, 112); + br_memset(buf, 0, 112); } else { - memset(buf + ptr, 0, 112 - ptr); + br_memset(buf + ptr, 0, 112 - ptr); } br_enc64be(buf + 112, cc->count >> 61); br_enc64be(buf + 120, cc->count << 3); @@ -196,7 +196,7 @@ void br_sha384_init(br_sha384_context *cc) { cc->vtable = &br_sha384_vtable; - memcpy(cc->val, IV384, sizeof IV384); + br_memcpy(cc->val, IV384, sizeof IV384); cc->count = 0; } @@ -235,7 +235,7 @@ void br_sha512_init(br_sha512_context *cc) { cc->vtable = &br_sha512_vtable; - memcpy(cc->val, IV512, sizeof IV512); + br_memcpy(cc->val, IV512, sizeof IV512); cc->count = 0; } diff --git a/third_party/bearssl/sha2small.c b/third_party/bearssl/sha2small.c index ca196559e..4accfb73f 100644 --- a/third_party/bearssl/sha2small.c +++ b/third_party/bearssl/sha2small.c @@ -215,7 +215,7 @@ sha2small_update(br_sha224_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -234,15 +234,15 @@ sha2small_out(const br_sha224_context *cc, void *dst, int num) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_sha2small_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64be(buf + 56, cc->count << 3); br_sha2small_round(buf, val); @@ -254,7 +254,7 @@ void br_sha224_init(br_sha224_context *cc) { cc->vtable = &br_sha224_vtable; - memcpy(cc->val, br_sha224_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha224_IV, sizeof cc->val); cc->count = 0; } @@ -293,7 +293,7 @@ void br_sha256_init(br_sha256_context *cc) { cc->vtable = &br_sha256_vtable; - memcpy(cc->val, br_sha256_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha256_IV, sizeof cc->val); cc->count = 0; } diff --git a/third_party/bearssl/ssl_client.c b/third_party/bearssl/ssl_client.c index 28c404b83..9f5f0dcf2 100644 --- a/third_party/bearssl/ssl_client.c +++ b/third_party/bearssl/ssl_client.c @@ -31,10 +31,10 @@ br_ssl_client_zero(br_ssl_client_context *cc) /* * For really standard C, we should explicitly set to NULL all * pointers, and 0 all other fields. However, on all our target - * architectures, a direct memset() will work, be faster, and + * architectures, a direct br_memset() will work, be faster, and * use a lot less code. */ - memset(cc, 0, sizeof *cc); + br_memset(cc, 0, sizeof *cc); } /* see bearssl_ssl.h */ @@ -64,12 +64,12 @@ br_ssl_client_reset(br_ssl_client_context *cc, if (server_name == NULL) { cc->eng.server_name[0] = 0; } else { - n = strlen(server_name) + 1; + n = br_strlen(server_name) + 1; if (n > sizeof cc->eng.server_name) { br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM); return 0; } - memcpy(cc->eng.server_name, server_name, n); + br_memcpy(cc->eng.server_name, server_name, n); } br_ssl_engine_hs_reset(&cc->eng, diff --git a/third_party/bearssl/ssl_engine.c b/third_party/bearssl/ssl_engine.c index 61f8c0ef4..1a52420a6 100644 --- a/third_party/bearssl/ssl_engine.c +++ b/third_party/bearssl/ssl_engine.c @@ -954,7 +954,7 @@ br_ssl_engine_set_suites(br_ssl_engine_context *cc, br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM); return; } - memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); + br_memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); cc->suites_num = suites_num; } diff --git a/third_party/bearssl/ssl_hs_client.c b/third_party/bearssl/ssl_hs_client.c index 1a1cf4b31..bd396965b 100644 --- a/third_party/bearssl/ssl_hs_client.c +++ b/third_party/bearssl/ssl_hs_client.c @@ -241,7 +241,7 @@ verify_SKE_sig(br_ssl_client_context *ctx, } if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len, hash_oid, hv_len, &pk->key.rsa, tmp) - || memcmp(tmp, hv, hv_len) != 0) + || br_memcmp(tmp, hv, hv_len) != 0) { return BR_ERR_BAD_SIGNATURE; } @@ -315,7 +315,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) return -BR_ERR_INVALID_ALGORITHM; } - memcpy(point, point_src, glen); + br_memcpy(point, point_src, glen); if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { return -BR_ERR_INVALID_ALGORITHM; } @@ -327,7 +327,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); ctx->eng.iec->mulgen(point, key, olen, curve); - memcpy(ctx->eng.pad, point, glen); + br_memcpy(ctx->eng.pad, point, glen); return (int)glen; } @@ -355,7 +355,7 @@ make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) if (point_len > sizeof point) { return -1; } - memcpy(point, pk->key.ec.q, point_len); + br_memcpy(point, pk->key.ec.q, point_len); if (!(*ctx->client_auth_vtable)->do_keyx( ctx->client_auth_vtable, point, &point_len)) { @@ -925,7 +925,7 @@ br_ssl_hs_client_run(void *t0ctx) #define T0_ROLL(x) do { \ size_t t0len = (size_t)(x); \ uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + br_memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_SWAP() do { \ @@ -1186,7 +1186,7 @@ br_ssl_hs_client_run(void *t0ctx) size_t len = (size_t)T0_POP(); void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - memset(addr, 0, len); + br_memset(addr, 0, len); } break; @@ -1235,7 +1235,7 @@ br_ssl_hs_client_run(void *t0ctx) if (clen > sizeof ENG->pad) { clen = sizeof ENG->pad; } - memcpy(ENG->pad, ENG->cert_cur, clen); + br_memcpy(ENG->pad, ENG->cert_cur, clen); ENG->cert_cur += clen; ENG->cert_len -= clen; T0_PUSH(clen); @@ -1246,8 +1246,8 @@ br_ssl_hs_client_run(void *t0ctx) /* copy-protocol-name */ size_t idx = T0_POP(); - size_t len = strlen(ENG->protocol_names[idx]); - memcpy(ENG->pad, ENG->protocol_names[idx], len); + size_t len = br_strlen(ENG->protocol_names[idx]); + br_memcpy(ENG->pad, ENG->protocol_names[idx], len); T0_PUSH(len); } @@ -1346,7 +1346,7 @@ br_ssl_hs_client_run(void *t0ctx) } len = 6; for (u = 0; u < ENG->protocol_names_num; u ++) { - len += 1 + strlen(ENG->protocol_names[u]); + len += 1 + br_strlen(ENG->protocol_names[u]); } T0_PUSH(len); @@ -1438,23 +1438,23 @@ br_ssl_hs_client_run(void *t0ctx) } break; case 48: { - /* memcmp */ + /* br_memcmp */ size_t len = (size_t)T0_POP(); void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); - int x = memcmp(addr1, addr2, len); + int x = br_memcmp(addr1, addr2, len); T0_PUSH((uint32_t)-(x == 0)); } break; case 49: { - /* memcpy */ + /* br_memcpy */ size_t len = (size_t)T0_POP(); void *src = (unsigned char *)ENG + (size_t)T0_POP(); void *dst = (unsigned char *)ENG + (size_t)T0_POP(); - memcpy(dst, src, len); + br_memcpy(dst, src, len); } break; @@ -1523,7 +1523,7 @@ br_ssl_hs_client_run(void *t0ctx) if ((size_t)len < clen) { clen = (size_t)len; } - memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + br_memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); if (ENG->record_type_in == BR_SSL_HANDSHAKE) { br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); } @@ -1591,10 +1591,10 @@ br_ssl_hs_client_run(void *t0ctx) } break; case 63: { - /* strlen */ + /* br_strlen */ void *str = (unsigned char *)ENG + (size_t)T0_POP(); - T0_PUSH((uint32_t)strlen(str)); + T0_PUSH((uint32_t)br_strlen(str)); } break; @@ -1766,7 +1766,7 @@ br_ssl_hs_client_run(void *t0ctx) const char *name; name = ENG->protocol_names[u]; - if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + if (len == br_strlen(name) && br_memcmp(ENG->pad, name, len) == 0) { T0_PUSH(u); T0_RET(); } @@ -1821,7 +1821,7 @@ br_ssl_hs_client_run(void *t0ctx) if ((size_t)len < clen) { clen = (size_t)len; } - memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + br_memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); if (ENG->record_type_out == BR_SSL_HANDSHAKE) { br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); } diff --git a/third_party/bearssl/ssl_io.c b/third_party/bearssl/ssl_io.c index 195261595..7d4eeabe1 100644 --- a/third_party/bearssl/ssl_io.c +++ b/third_party/bearssl/ssl_io.c @@ -159,7 +159,7 @@ br_sslio_read(br_sslio_context *ctx, void *dst, size_t len) if (alen > len) { alen = len; } - memcpy(dst, buf, alen); + br_memcpy(dst, buf, alen); br_ssl_engine_recvapp_ack(ctx->engine, alen); return (int)alen; } @@ -201,7 +201,7 @@ br_sslio_write(br_sslio_context *ctx, const void *src, size_t len) if (alen > len) { alen = len; } - memcpy(buf, src, alen); + br_memcpy(buf, src, alen); br_ssl_engine_sendapp_ack(ctx->engine, alen); return (int)alen; } diff --git a/third_party/bearssl/ssl_rec_cbc.c b/third_party/bearssl/ssl_rec_cbc.c index c38cbfdfb..70615292a 100644 --- a/third_party/bearssl/ssl_rec_cbc.c +++ b/third_party/bearssl/ssl_rec_cbc.c @@ -38,10 +38,10 @@ in_cbc_init(br_sslrec_in_cbc_context *cc, br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); cc->mac_len = mac_out_len; if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); + br_memset(cc->iv, 0, sizeof cc->iv); cc->explicit_IV = 1; } else { - memcpy(cc->iv, iv, bc_impl->block_size); + br_memcpy(cc->iv, iv, bc_impl->block_size); cc->explicit_IV = 0; } } @@ -91,7 +91,7 @@ cond_rotate(uint32_t ctl, unsigned char *buf, size_t len, size_t num) v = 0; } } - memcpy(buf, tmp, len); + br_memcpy(buf, tmp, len); } static unsigned char * @@ -163,7 +163,7 @@ cbc_decrypt(br_sslrec_in_cbc_context *cc, len_nomac = len_withmac - cc->mac_len; min_len -= cc->mac_len; rot_count = 0; - memset(tmp1, 0, cc->mac_len); + br_memset(tmp1, 0, cc->mac_len); v = 0; for (u = min_len; u < max_len; u ++) { tmp1[v] |= MUX(GE(u, len_nomac) & LT(u, len_withmac), @@ -278,10 +278,10 @@ out_cbc_init(br_sslrec_out_cbc_context *cc, br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); cc->mac_len = mac_out_len; if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); + br_memset(cc->iv, 0, sizeof cc->iv); cc->explicit_IV = 1; } else { - memcpy(cc->iv, iv, bc_impl->block_size); + br_memcpy(cc->iv, iv, bc_impl->block_size); cc->explicit_IV = 0; } } @@ -391,7 +391,7 @@ cbc_encrypt(br_sslrec_out_cbc_context *cc, * Add padding. */ plen = blen - (len & (blen - 1)); - memset(buf + len, (unsigned)plen - 1, plen); + br_memset(buf + len, (unsigned)plen - 1, plen); len += plen; /* diff --git a/third_party/bearssl/ssl_rec_ccm.c b/third_party/bearssl/ssl_rec_ccm.c index 92c329521..86b1efc35 100644 --- a/third_party/bearssl/ssl_rec_ccm.c +++ b/third_party/bearssl/ssl_rec_ccm.c @@ -37,7 +37,7 @@ gen_ccm_init(br_sslrec_ccm_context *cc, { cc->seq = 0; bc_impl->init(&cc->bc.vtable, key, key_len); - memcpy(cc->iv, iv, sizeof cc->iv); + br_memcpy(cc->iv, iv, sizeof cc->iv); cc->tag_len = tag_len; } @@ -79,8 +79,8 @@ ccm_decrypt(br_sslrec_ccm_context *cc, /* * Make nonce (implicit + explicit parts). */ - memcpy(nonce, cc->iv, sizeof cc->iv); - memcpy(nonce + 4, data, 8); + br_memcpy(nonce, cc->iv, sizeof cc->iv); + br_memcpy(nonce + 4, data, 8); /* * Assemble synthetic header for the AAD. @@ -161,7 +161,7 @@ ccm_encrypt(br_sslrec_ccm_context *cc, * Make nonce; the explicit part is an encoding of the sequence * number. */ - memcpy(nonce, cc->iv, sizeof cc->iv); + br_memcpy(nonce, cc->iv, sizeof cc->iv); br_enc64be(nonce + 4, cc->seq); /* @@ -187,7 +187,7 @@ ccm_encrypt(br_sslrec_ccm_context *cc, */ len += 8 + cc->tag_len; buf -= 13; - memcpy(buf + 5, nonce + 4, 8); + br_memcpy(buf + 5, nonce + 4, 8); buf[0] = (unsigned char)record_type; br_enc16be(buf + 1, version); br_enc16be(buf + 3, len); diff --git a/third_party/bearssl/ssl_rec_chapol.c b/third_party/bearssl/ssl_rec_chapol.c index 73b3c7855..2d4abafef 100644 --- a/third_party/bearssl/ssl_rec_chapol.c +++ b/third_party/bearssl/ssl_rec_chapol.c @@ -32,8 +32,8 @@ gen_chapol_init(br_sslrec_chapol_context *cc, cc->seq = 0; cc->ichacha = ichacha; cc->ipoly = ipoly; - memcpy(cc->key, key, sizeof cc->key); - memcpy(cc->iv, iv, sizeof cc->iv); + br_memcpy(cc->key, key, sizeof cc->key); + br_memcpy(cc->iv, iv, sizeof cc->iv); } static void @@ -51,7 +51,7 @@ gen_chapol_process(br_sslrec_chapol_context *cc, header[8] = (unsigned char)record_type; br_enc16be(header + 9, version); br_enc16be(header + 11, len); - memcpy(nonce, cc->iv, 12); + br_memcpy(nonce, cc->iv, 12); for (u = 0; u < 8; u ++) { nonce[11 - u] ^= (unsigned char)seq; seq >>= 8; diff --git a/third_party/bearssl/ssl_rec_gcm.c b/third_party/bearssl/ssl_rec_gcm.c index 70df2777b..349cc2e48 100644 --- a/third_party/bearssl/ssl_rec_gcm.c +++ b/third_party/bearssl/ssl_rec_gcm.c @@ -41,9 +41,9 @@ gen_gcm_init(br_sslrec_gcm_context *cc, cc->seq = 0; bc_impl->init(&cc->bc.vtable, key, key_len); cc->gh = gh_impl; - memcpy(cc->iv, iv, sizeof cc->iv); - memset(cc->h, 0, sizeof cc->h); - memset(tmp, 0, sizeof tmp); + br_memcpy(cc->iv, iv, sizeof cc->iv); + br_memset(cc->h, 0, sizeof cc->h); + br_memset(tmp, 0, sizeof tmp); bc_impl->run(&cc->bc.vtable, tmp, 0, cc->h, sizeof cc->h); } @@ -96,7 +96,7 @@ do_tag(br_sslrec_gcm_context *cc, br_enc16be(header + 11, len); br_enc64be(footer, (uint64_t)(sizeof header) << 3); br_enc64be(footer + 8, (uint64_t)len << 3); - memset(tag, 0, 16); + br_memset(tag, 0, 16); cc->gh(tag, cc->h, header, sizeof header); cc->gh(tag, cc->h, data, len); cc->gh(tag, cc->h, footer, sizeof footer); @@ -113,8 +113,8 @@ do_ctr(br_sslrec_gcm_context *cc, const void *nonce, void *data, size_t len, { unsigned char iv[12]; - memcpy(iv, cc->iv, 4); - memcpy(iv + 4, nonce, 8); + br_memcpy(iv, cc->iv, 4); + br_memcpy(iv + 4, nonce, 8); cc->bc.vtable->run(&cc->bc.vtable, iv, 2, data, len); cc->bc.vtable->run(&cc->bc.vtable, iv, 1, xortag, 16); } @@ -201,7 +201,7 @@ gcm_encrypt(br_sslrec_gcm_context *cc, buf = (unsigned char *)data; len = *data_len; - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); br_enc64be(buf - 8, cc->seq); do_ctr(cc, buf - 8, buf, len, tmp); do_tag(cc, record_type, version, buf, len, buf + len); diff --git a/third_party/bearssl/x509_minimal.c b/third_party/bearssl/x509_minimal.c index b3079deca..78d82777b 100644 --- a/third_party/bearssl/x509_minimal.c +++ b/third_party/bearssl/x509_minimal.c @@ -214,7 +214,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx, const br_hash_class *dn_hash_impl, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) { - memset(ctx, 0, sizeof *ctx); + br_memset(ctx, 0, sizeof *ctx); ctx->vtable = &br_x509_minimal_vtable; ctx->dn_hash_impl = dn_hash_impl; ctx->trust_anchors = trust_anchors; @@ -232,7 +232,7 @@ xm_start_chain(const br_x509_class **ctx, const char *server_name) cc->name_elts[u].status = 0; cc->name_elts[u].buf[0] = 0; } - memset(&cc->pkey, 0, sizeof cc->pkey); + br_memset(&cc->pkey, 0, sizeof cc->pkey); cc->num_certs = 0; cc->err = 0; cc->cpu.dp = cc->dp_stack; @@ -372,7 +372,7 @@ eqbigint(const unsigned char *b1, size_t len1, if (len1 != len2) { return 0; } - return memcmp(b1, b2, len1) == 0; + return br_memcmp(b1, b2, len1) == 0; } /* @@ -885,7 +885,7 @@ br_x509_minimal_run(void *t0ctx) #define T0_ROLL(x) do { \ size_t t0len = (size_t)(x); \ uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + br_memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_SWAP() do { \ @@ -1099,7 +1099,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = T0_POP(); unsigned char *src = (unsigned char *)CTX + T0_POP(); unsigned char *dst = (unsigned char *)CTX + T0_POP(); - memcpy(dst, src, len); + br_memcpy(dst, src, len); } break; @@ -1118,7 +1118,7 @@ br_x509_minimal_run(void *t0ctx) continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { + if (br_memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { continue; } kt = CTX->pkey.key_type; @@ -1144,7 +1144,7 @@ br_x509_minimal_run(void *t0ctx) case BR_KEYTYPE_EC: if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen - || memcmp(CTX->pkey.key.ec.q, + || br_memcmp(CTX->pkey.key.ec.q, ta->pkey.key.ec.q, ta->pkey.key.ec.qlen) != 0) { @@ -1179,7 +1179,7 @@ br_x509_minimal_run(void *t0ctx) continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { + if (br_memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { continue; } if (verify_signature(CTX, &ta->pkey) == 0) { @@ -1251,7 +1251,7 @@ br_x509_minimal_run(void *t0ctx) size_t qlen = T0_POP(); uint32_t curve = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); + br_memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); CTX->pkey.key_type = BR_KEYTYPE_EC; CTX->pkey.key.ec.curve = curve; CTX->pkey.key.ec.q = CTX->ee_pkey_data; @@ -1264,7 +1264,7 @@ br_x509_minimal_run(void *t0ctx) size_t elen = T0_POP(); size_t nlen = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); + br_memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); CTX->pkey.key_type = BR_KEYTYPE_RSA; CTX->pkey.key.rsa.n = CTX->ee_pkey_data; CTX->pkey.key.rsa.nlen = nlen; @@ -1287,7 +1287,7 @@ br_x509_minimal_run(void *t0ctx) ne = &CTX->name_elts[u]; if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { if (ok && ne->len > len) { - memcpy(ne->buf, CTX->pad + 1, len); + br_memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { @@ -1312,7 +1312,7 @@ br_x509_minimal_run(void *t0ctx) if (ok) { len = CTX->pad[0]; if (len < ne->len) { - memcpy(ne->buf, CTX->pad + 1, len); + br_memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { @@ -1389,7 +1389,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = a1[0]; int x; if (len == a2[0]) { - x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + x = -(br_memcmp(a1 + 1, a2 + 1, len) == 0); } else { x = 0; } @@ -1403,7 +1403,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = T0_POP(); const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); - T0_PUSHi(-(memcmp(a1, a2, len) == 0)); + T0_PUSHi(-(br_memcmp(a1, a2, len) == 0)); } break; @@ -1440,7 +1440,7 @@ br_x509_minimal_run(void *t0ctx) T0_PUSH(0); T0_RET(); } - n1 = strlen(CTX->server_name); + n1 = br_strlen(CTX->server_name); n2 = CTX->pad[0]; if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { T0_PUSHi(-1); @@ -1496,7 +1496,7 @@ br_x509_minimal_run(void *t0ctx) } len = oid[off]; if (len != 0 && len == CTX->pad[0] - && memcmp(oid + off + 1, + && br_memcmp(oid + off + 1, CTX->pad + 1, len) == 0) { T0_PUSH(u); @@ -1532,7 +1532,7 @@ br_x509_minimal_run(void *t0ctx) clen = (size_t)len; } if (addr != 0) { - memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + br_memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); } if (CTX->do_mhash) { br_multihash_update(&CTX->mhash, CTX->hbuf, clen); @@ -1672,7 +1672,7 @@ verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) { return BR_ERR_X509_BAD_SIGNATURE; } - if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { + if (br_memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { return BR_ERR_X509_BAD_SIGNATURE; } return 0; diff --git a/third_party/citro3d.c b/third_party/citro3d.c index d81d3a550..9d658e0a8 100644 --- a/third_party/citro3d.c +++ b/third_party/citro3d.c @@ -140,14 +140,6 @@ static void C3D_ImmDrawBegin(GPU_Primitive_t primitive); static void C3D_ImmSendAttrib(float x, float y, float z, float w); static void C3D_ImmDrawEnd(void); -static inline void C3D_ImmDrawRestartPrim(void) -{ - GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1); -} - - - - typedef struct { @@ -253,18 +245,13 @@ struct C3D_RenderTarget_tag // Flags for C3D_FrameBegin enum { - C3D_FRAME_SYNCDRAW = BIT(0), // Perform C3D_FrameSync before checking the GPU status C3D_FRAME_NONBLOCK = BIT(1), // Return false instead of waiting if the GPU is busy }; -static void C3D_FrameSync(void); - static bool C3D_FrameBegin(u8 flags); static bool C3D_FrameDrawOn(C3D_RenderTarget* target); -static void C3D_FrameSplit(u8 flags); static void C3D_FrameEnd(u8 flags); -static void C3D_RenderTargetDelete(C3D_RenderTarget* target); static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags); static inline void C3D_RenderTargetDetachOutput(C3D_RenderTarget* target) @@ -316,51 +303,6 @@ void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b) } - - -#define C3D_FVUNIF_COUNT 96 -#define C3D_IVUNIF_COUNT 4 - -static C3D_FVec C3D_FVUnif[C3D_FVUNIF_COUNT]; -static C3D_IVec C3D_IVUnif[C3D_IVUNIF_COUNT]; -static u16 C3D_BoolUnifs; - -static bool C3D_FVUnifDirty[C3D_FVUNIF_COUNT]; -static bool C3D_IVUnifDirty[C3D_IVUNIF_COUNT]; -static bool C3D_BoolUnifsDirty; - -static inline C3D_FVec* C3D_FVUnifWritePtr(int id, int size) -{ - int i; - for (i = 0; i < size; i ++) - C3D_FVUnifDirty[id+i] = true; - return &C3D_FVUnif[id]; -} - -static inline void C3D_FVUnifMtx4x4(int id, const C3D_Mtx* mtx) -{ - int i; - C3D_FVec* ptr = C3D_FVUnifWritePtr(id, 4); - for (i = 0; i < 4; i ++) - ptr[i] = mtx->r[i]; // Struct copy. -} - -static inline void C3D_FVUnifSet(int id, float x, float y, float z, float w) -{ - C3D_FVec* ptr = C3D_FVUnifWritePtr(id, 1); - ptr->x = x; - ptr->y = y; - ptr->z = z; - ptr->w = w; -} - -static void C3D_UpdateUniforms(void); - - - - - - typedef struct { u32 fragOpMode; @@ -452,19 +394,11 @@ static void C3Di_TexEnvBind(int id, C3D_TexEnv* env); static void C3Di_SetTex(int unit, C3D_Tex* tex); static void C3Di_EffectBind(C3D_Effect* effect); -static void C3Di_DirtyUniforms(void); -static void C3Di_LoadShaderUniforms(shaderInstance_s* si); -static void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type); - static bool C3Di_SplitFrame(u32** pBuf, u32* pSize); static void C3Di_RenderQueueInit(void); static void C3Di_RenderQueueExit(void); static void C3Di_RenderQueueWaitDone(void); -static void C3Di_RenderQueueEnableVBlank(void); -static void C3Di_RenderQueueDisableVBlank(void); - - @@ -533,8 +467,6 @@ static void C3D_DrawElements(GPU_Primitive_t primitive, int count) GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1); // Number of vertices GPUCMD_AddWrite(GPUREG_NUMVERTICES, count); - // First vertex - GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0); // Enable triangle element drawing mode if necessary GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 2, 0x100); GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 2, 0x100); @@ -896,20 +828,7 @@ static void C3D_ImmDrawEnd(void) static C3D_RenderTarget *linkedTarget[3]; static bool inFrame, inSafeTransfer; -static bool needSwapTop, needSwapBot, isTopStereo; -static u32 vblankCounter[2]; - -static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target); - -static void onVBlank0(void* unused) -{ - vblankCounter[0]++; -} - -static void onVBlank1(void* unused) -{ - vblankCounter[1]++; -} +static bool swapPending, isTopStereo; static void onQueueFinish(gxCmdQueue_s* queue) { @@ -922,61 +841,28 @@ static void onQueueFinish(gxCmdQueue_s* queue) gxCmdQueueClear(queue); } } - else + else if (swapPending) { - if (needSwapTop) - { - gfxScreenSwapBuffers(GFX_TOP, isTopStereo); - needSwapTop = false; - } - if (needSwapBot) - { - gfxScreenSwapBuffers(GFX_BOTTOM, false); - needSwapBot = false; - } + gfxScreenSwapBuffers(GFX_TOP, isTopStereo); + gfxScreenSwapBuffers(GFX_BOTTOM, false); } } -static void C3D_FrameSync(void) -{ - u32 cur[2]; - u32 start[2] = { vblankCounter[0], vblankCounter[1] }; - do - { - gspWaitForAnyEvent(); - cur[0] = vblankCounter[0]; - cur[1] = vblankCounter[1]; - } while (cur[0]==start[0] || cur[1]==start[1]); -} - static bool C3Di_WaitAndClearQueue(s64 timeout) { gxCmdQueue_s* queue = &C3Di_GetContext()->gxQueue; if (!gxCmdQueueWait(queue, timeout)) return false; + gxCmdQueueStop(queue); gxCmdQueueClear(queue); return true; } -static void C3Di_RenderQueueEnableVBlank(void) -{ - gspSetEventCallback(GSPGPU_EVENT_VBlank0, onVBlank0, NULL, false); - gspSetEventCallback(GSPGPU_EVENT_VBlank1, onVBlank1, NULL, false); -} - -static void C3Di_RenderQueueDisableVBlank(void) -{ - gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, false); - gspSetEventCallback(GSPGPU_EVENT_VBlank1, NULL, NULL, false); -} - static void C3Di_RenderQueueInit(void) { C3D_Context* ctx = C3Di_GetContext(); - C3Di_RenderQueueEnableVBlank(); - GX_BindQueue(&ctx->gxQueue); gxCmdQueueSetCallback(&ctx->gxQueue, onQueueFinish, NULL); gxCmdQueueRun(&ctx->gxQueue); @@ -987,8 +873,6 @@ static void C3Di_RenderQueueExit(void) C3Di_WaitAndClearQueue(-1); gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL); GX_BindQueue(NULL); - - C3Di_RenderQueueDisableVBlank(); } static void C3Di_RenderQueueWaitDone(void) @@ -1019,20 +903,15 @@ static bool C3D_FrameDrawOn(C3D_RenderTarget* target) return true; } -static void C3D_FrameSplit(u8 flags) -{ - u32 *cmdBuf, cmdBufSize; - if (!inFrame) return; - if (C3Di_SplitFrame(&cmdBuf, &cmdBufSize)) - GX_ProcessCommandList(cmdBuf, cmdBufSize*4, flags); -} - static void C3D_FrameEnd(u8 flags) { C3D_Context* ctx = C3Di_GetContext(); if (!inFrame) return; - C3D_FrameSplit(flags); + u32 *cmdBuf, cmdBufSize; + if (C3Di_SplitFrame(&cmdBuf, &cmdBufSize)) + GX_ProcessCommandList(cmdBuf, cmdBufSize*4, flags); + GPUCMD_SetBuffer(NULL, 0, 0); inFrame = false; @@ -1046,8 +925,7 @@ static void C3D_FrameEnd(u8 flags) C3D_RenderTarget* target; isTopStereo = false; - needSwapTop = true; - needSwapBot = true; + swapPending = true; for (int i = 2; i >= 0; i --) { @@ -1097,23 +975,6 @@ static void C3D_RenderTargetDepth(C3D_RenderTarget* target, GPU_DEPTHBUF depthFm C3D_FrameBufDepth(fb, depthBuf, depthFmt); } -static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target) -{ - vramFree(target->frameBuf.colorBuf); - vramFree(target->frameBuf.depthBuf); -} - -static void C3D_RenderTargetDelete(C3D_RenderTarget* target) -{ - if (inFrame) - svcBreak(USERBREAK_PANIC); // Shouldn't happen. - if (target->linked) - C3D_RenderTargetDetachOutput(target); - else - C3Di_WaitAndClearQueue(-1); - C3Di_RenderTargetDestroy(target); -} - static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags) { int id = 0; @@ -1180,132 +1041,6 @@ static void C3Di_SetTex(int unit, C3D_Tex* tex) } } - - - - - - - -static struct -{ - bool dirty; - int count; - float24Uniform_s* data; -} C3Di_ShaderFVecData; - -static bool C3Di_FVUnifEverDirty[C3D_FVUNIF_COUNT]; -static bool C3Di_IVUnifEverDirty[C3D_IVUNIF_COUNT]; - -static void C3D_UpdateUniforms(void) -{ - int i = 0; - - // Update FVec uniforms that come from shader constants - if (C3Di_ShaderFVecData.dirty) - { - while (i < C3Di_ShaderFVecData.count) - { - float24Uniform_s* u = &C3Di_ShaderFVecData.data[i++]; - GPUCMD_AddIncrementalWrites(GPUREG_VSH_FLOATUNIFORM_CONFIG, (u32*)u, 4); - C3D_FVUnifDirty[u->id] = false; - } - C3Di_ShaderFVecData.dirty = false; - i = 0; - } - - // Update FVec uniforms - while (i < C3D_FVUNIF_COUNT) - { - if (!C3D_FVUnifDirty[i]) - { - i ++; - continue; - } - - // Find the number of consecutive dirty uniforms - int j; - for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[j]; j ++); - - // Upload the uniforms - GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, 0x80000000|i); - GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)&C3D_FVUnif[i], (j-i)*4); - - // Clear the dirty flag - int k; - for (k = i; k < j; k ++) - { - C3D_FVUnifDirty[k] = false; - C3Di_FVUnifEverDirty[k] = true; - } - - // Advance - i = j; - } - - // Update IVec uniforms - for (i = 0; i < C3D_IVUNIF_COUNT; i ++) - { - if (!C3D_IVUnifDirty[i]) continue; - - GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+i, C3D_IVUnif[i]); - C3D_IVUnifDirty[i] = false; - C3Di_IVUnifEverDirty[i] = false; - } - - // Update bool uniforms - if (C3D_BoolUnifsDirty) - { - GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM, 0x7FFF0000 | C3D_BoolUnifs); - C3D_BoolUnifsDirty = false; - } -} - -static void C3Di_DirtyUniforms(void) -{ - int i; - C3D_BoolUnifsDirty = true; - if (C3Di_ShaderFVecData.count) - C3Di_ShaderFVecData.dirty = true; - for (i = 0; i < C3D_FVUNIF_COUNT; i ++) - C3D_FVUnifDirty[i] = C3D_FVUnifDirty[i] || C3Di_FVUnifEverDirty[i]; - for (i = 0; i < C3D_IVUNIF_COUNT; i ++) - C3D_IVUnifDirty[i] = C3D_IVUnifDirty[i] || C3Di_IVUnifEverDirty[i]; -} - -static void C3Di_LoadShaderUniforms(shaderInstance_s* si) -{ - if (si->boolUniformMask) - { - C3D_BoolUnifs &= ~si->boolUniformMask; - C3D_BoolUnifs |= si->boolUniforms; - } - - C3D_BoolUnifsDirty = true; - - if (si->intUniformMask) - { - int i; - for (i = 0; i < 4; i ++) - { - if (si->intUniformMask & BIT(i)) - { - C3D_IVUnif[i] = si->intUniforms[i]; - C3D_IVUnifDirty[i] = true; - } - } - } - C3Di_ShaderFVecData.dirty = true; - C3Di_ShaderFVecData.count = si->numFloat24Uniforms; - C3Di_ShaderFVecData.data = si->float24Uniforms; -} - - - - - - - static void C3Di_OnRestore(void) { C3D_Context* ctx = C3Di_GetContext(); @@ -1314,12 +1049,13 @@ static void C3Di_OnRestore(void) | C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode | C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_Gas | C3DiF_Reset; - C3Di_DirtyUniforms(); - if (ctx->fogLut) ctx->flags |= C3DiF_FogLut; } +#define GXQUEUE_MAX_ENTRIES 32 +static gxCmdEntry_s queue_entries[GXQUEUE_MAX_ENTRIES]; + static bool C3D_Init(size_t cmdBufSize) { int i; @@ -1334,13 +1070,8 @@ static bool C3D_Init(size_t cmdBufSize) if (!ctx->cmdBuf) return false; - ctx->gxQueue.maxEntries = 32; - ctx->gxQueue.entries = (gxCmdEntry_s*)malloc(ctx->gxQueue.maxEntries*sizeof(gxCmdEntry_s)); - if (!ctx->gxQueue.entries) - { - linearFree(ctx->cmdBuf); - return false; - } + ctx->gxQueue.maxEntries = GXQUEUE_MAX_ENTRIES; + ctx->gxQueue.entries = queue_entries; ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_Effect | C3DiF_TexStatus | C3DiF_TexAll | C3DiF_Reset; @@ -1520,8 +1251,6 @@ static void C3Di_UpdateContext(void) GPUCMD_AddWrites(GPUREG_FOG_LUT_DATA0, ctx->fogLut->data, 128); } } - - C3D_UpdateUniforms(); } static bool C3Di_SplitFrame(u32** pBuf, u32* pSize) @@ -1551,7 +1280,6 @@ static void C3D_Fini(void) return; C3Di_RenderQueueExit(); - free(ctx->gxQueue.entries); linearFree(ctx->cmdBuf); ctx->flags = 0; } @@ -1577,6 +1305,4 @@ static void C3D_BindProgram(shaderProgram_s* program) ctx->flags |= C3DiF_VshCode | C3DiF_GshCode; } } - - C3Di_LoadShaderUniforms(program->vertexShader); }