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