Merge branch 'master' of https://github.com/UnknownShadow200/ClassiCube into AndroidUI2

This commit is contained in:
UnknownShadow200 2024-05-16 18:31:12 +10:00
commit 14be9f0856
136 changed files with 2807 additions and 1846 deletions

View File

@ -1,5 +1,10 @@
name: Build latest (3DS)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-3ds
@ -7,7 +12,6 @@ concurrency:
jobs:
build-3DS:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: devkitpro/devkitarm:latest

View File

@ -1,5 +1,10 @@
name: Build latest (Dreamcast)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-dreamcast
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: kazade/dreamcast-sdk

View File

@ -1,5 +1,10 @@
name: Build latest (FreeBSD)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-freebsd
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: empterdose/freebsd-cross-build:11.4

View File

@ -1,5 +1,10 @@
name: Build latest (Haiku)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-haiku
@ -7,7 +12,6 @@ concurrency:
jobs:
build-haiku:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: haiku/cross-compiler:x86_64-r1beta4

View File

@ -1,5 +1,10 @@
name: Build latest (iOS)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-ios
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: macOS-11
steps:
- uses: actions/checkout@v3

View File

@ -1,5 +1,11 @@
name: Build latest (Linux)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
- ModernLighting
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-linux
@ -10,7 +16,6 @@ jobs:
# =============== 32 BIT LINUX ==============
# ===========================================
build-32:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
@ -64,7 +69,6 @@ jobs:
# =============== 64 BIT LINUX ==============
# ===========================================
build-64:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

View File

@ -1,5 +1,10 @@
name: Build latest (macOS 64 bit)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-mac64
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4

View File

@ -1,5 +1,10 @@
name: Build latest (N64)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-n64
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ghcr.io/dragonminded/libdragon:latest

View File

@ -1,5 +1,10 @@
name: Build latest (NDS)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-nds
@ -7,7 +12,6 @@ concurrency:
jobs:
build-DS:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: skylyrac/blocksds:dev-latest

View File

@ -1,5 +1,10 @@
name: Build latest (NetBSD)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-netbsd
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ghcr.io/cross-rs/x86_64-unknown-netbsd

View File

@ -1,5 +1,10 @@
name: Build latest (PS2)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-ps2
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ghcr.io/ps2dev/ps2sdk:latest

View File

@ -1,5 +1,10 @@
name: Build latest (PS3)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-ps3
@ -7,7 +12,6 @@ concurrency:
jobs:
build-PS3:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ghcr.io/classicube/minimal-psl1ght:latest

View File

@ -1,5 +1,10 @@
name: Build latest (PSP)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-psp
@ -7,7 +12,6 @@ concurrency:
jobs:
build-PSP:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: pspdev/pspdev:latest

View File

@ -1,5 +1,10 @@
name: Build latest (RPI)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-rpi
@ -10,7 +15,6 @@ jobs:
# ================ 32 BIT RPI ===============
# ===========================================
build-RPI32:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: dockcross/linux-armv6-lts
@ -59,7 +63,6 @@ jobs:
# ================ 64 BIT RPI ===============
# ===========================================
build-RPI64:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: dockcross/linux-arm64-lts

View File

@ -1,5 +1,10 @@
name: Build latest (Saturn)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-saturn
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ijacquez/yaul
@ -36,3 +40,9 @@ jobs:
with:
SOURCE_FILE: 'ClassiCube-saturn.iso'
DEST_NAME: 'ClassiCube-saturn.iso'
- uses: ./.github/actions/upload_build
if: ${{ always() && steps.compile.outcome == 'success' }}
with:
SOURCE_FILE: 'ClassiCube-saturn.cue'
DEST_NAME: 'ClassiCube-saturn.cue'

View File

@ -1,5 +1,10 @@
name: Build latest (Switch)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-switch
@ -7,7 +12,6 @@ concurrency:
jobs:
build-switch:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: devkitpro/devkita64:latest

View File

@ -1,5 +1,10 @@
name: Build latest (Vita)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-vita
@ -7,7 +12,6 @@ concurrency:
jobs:
build-Vita:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: vitasdk/vitasdk:latest

44
.github/workflows/build_webclient.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: Build latest (Webclient)
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-webclient
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
container:
image: trzeci/emscripten-fastcomp:1.39.0
steps:
- uses: actions/checkout@v4
- name: Compiles webclient
id: compile
run: |
cd src
emcc *.c -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 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' }}
with:
SOURCE_FILE: 'src/ClassiCube.js'
DEST_NAME: 'ClassiCube.js'
- uses: ./.github/actions/notify_success
if: ${{ always() && steps.compile.outcome == 'success' }}
with:
DESTINATION_URL: '${{ secrets.NOTIFY_URL }}'
WORKFLOW_NAME: 'webclient'

View File

@ -1,5 +1,10 @@
name: Build latest (Wii/GameCube)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-wiigc
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: devkitpro/devkitppc:latest

View File

@ -1,5 +1,10 @@
name: Build latest (WiiU)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-wiiu
@ -7,7 +12,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: devkitpro/devkitppc:latest

79
.github/workflows/build_win-arm.yml vendored Normal file
View File

@ -0,0 +1,79 @@
name: Build latest (Windows ARM32/64)
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-windows-arm
cancel-in-progress: true
jobs:
#============================================
# ============== ARM32 WINDOWS ==============
# ===========================================
build-32:
runs-on: ubuntu-latest
container:
image: dockcross/windows-armv7
steps:
- uses: actions/checkout@v4
- name: Compile ARM32 Windows builds
shell: bash
id: compile
env:
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn"
WIN32_FLAGS: "-mwindows -nostartfiles -Wl,-emain_real -DCC_NOMAIN"
run: |
LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\"
cd src
armv7-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-arm32-d3d11.exe $LATEST_FLAG -DCC_BUILD_MANUAL -DCC_BUILD_WIN -DCC_BUILD_D3D11 -DCC_BUILD_WINGUI -DCC_BUILD_WGL -DCC_BUILD_WINMM -DCC_BUILD_HTTPCLIENT -DCC_BUILD_SCHANNEL -lwinmm -limagehlp
- 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: 'src/cc-arm32-d3d11.exe'
DEST_NAME: 'ClassiCube-arm32-Direct3D11.exe'
#============================================
# ============== ARM64 WINDOWS ==============
# ===========================================
build-64:
runs-on: ubuntu-latest
container:
image: dockcross/windows-arm64
steps:
- uses: actions/checkout@v4
- name: Compile ARM64 Windows builds
shell: bash
id: compile
env:
COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn"
WIN64_FLAGS: "-mwindows -nostartfiles -Wl,-emain_real -DCC_NOMAIN"
run: |
LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\"
cd src
aarch64-w64-mingw32-gcc *.c ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-arm64-d3d11.exe $LATEST_FLAG -DCC_BUILD_MANUAL -DCC_BUILD_WIN -DCC_BUILD_D3D11 -DCC_BUILD_WINGUI -DCC_BUILD_WGL -DCC_BUILD_WINMM -DCC_BUILD_HTTPCLIENT -DCC_BUILD_SCHANNEL -lwinmm -limagehlp
- 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:
SOURCE_FILE: 'src/cc-arm64-d3d11.exe'
DEST_NAME: 'ClassiCube-arm64-Direct3D11.exe'

View File

@ -1,5 +1,11 @@
name: Build latest (Windows)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
- ModernLighting
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-windows
@ -10,7 +16,6 @@ jobs:
# ============== 32 BIT WINDOWS =============
# ===========================================
build-32:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@ -77,7 +82,6 @@ jobs:
# ============== 64 BIT WINDOWS =============
# ===========================================
build-64:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View File

@ -1,5 +1,10 @@
name: Build latest (Xbox)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-xbox
@ -7,7 +12,6 @@ concurrency:
jobs:
build-Xbox:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
container:
image: ghcr.io/xboxdev/nxdk:git-e955705a

View File

@ -1,13 +1,17 @@
name: Build latest (Xbox 360)
on: [push]
# trigger via either push to selected branches or on manual run
on:
push:
branches:
- master
workflow_dispatch:
concurrency:
group: ${{ github.ref }}-xbox360
cancel-in-progress: true
jobs:
build-Xbox:
if: github.ref_name == github.event.repository.default_branch
build-360:
runs-on: ubuntu-latest
container:
image: free60/libxenon

View File

@ -7,7 +7,6 @@ concurrency:
jobs:
build:
if: github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

8
.gitignore vendored
View File

@ -38,6 +38,12 @@ build-saturn/
cd/
# Microsoft console build results
build-360/
main.exe
main.lib
misc/xbox/ps_coloured.inl
misc/xbox/ps_textured.inl
misc/xbox/vs_coloured.inl
misc/xbox/vs_textured.inl
# Sony console build results
build-ps2/
build-ps3/
@ -91,6 +97,8 @@ CMakeCache.txt
#GCC object files
*.o
# Build dependency files
*.d
# Roslyn cache directories
*.ide/

View File

@ -506,7 +506,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@ -559,7 +559,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@ -573,7 +573,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -590,7 +590,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@ -1,4 +1,4 @@
Copyright (c) 2014 - 2022, UnknownShadow200
Copyright (c) 2014 - 2024, UnknownShadow200
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View File

@ -0,0 +1,93 @@
!r0 = clip flags
!r1 = GPU command
!r2 = temp
!r3 = prefetch address
!r4 = src pointer ARG
!r5 = dst pointer ARG
!r6 = quads count ARG
!r7 = ?
!fr0 = temp
!fr1 = u (0.0)
!fr2 = v (0.0)
!fr3 = c
!fr4 = x
!fr5 = y
!fr6 = z
!fr7 = w
!fr8 = VIEWPORT_HWIDTH
!fr9 = VIEWPORT_HHEIGHT
!fr10 = VIEWPORT_X_PLUS_HWIDTH
!fr11 = VIEWPORT_Y_PLUS_HHEIGHT
!fv4 = XYZW
#include "ViewportTransform.S"
.global _DrawColouredQuads
.align 4
.type _DrawColouredQuads,%function
_DrawColouredQuads:
! Setup
fldi0 fr1 ! U = 0
fldi0 fr2 ! V = 0
mov r4,r3 ! r3 = src
add #-32, r5 ! r5 -= sizeof(VERTEX)
ViewportTransformSetup _VP_COL_HWIDTH
.TRANSFORM_QUAD:
mov.l CMD_COL_VERT, r1 ! r1 = GPU VERT command
LoadColouredVertex
ProcessVertex1
LoadColouredVertex
ProcessVertex2
LoadColouredVertex
ProcessVertex3
LoadColouredVertex
ProcessVertex4 CMD_COL_EOS
! CLIPFLAGS TESTING
cmp/eq #0,r0 ! T = r0 == 0 (all points invisible)
bt/s .NO_POINTS_VISIBLE ! if T goto NO_POINTS_VISIBLE
nop
bra .SOME_POINTS_VISIBLE
nop
.NO_POINTS_VISIBLE:
bra .LOOP_END ! jump to loop end after executing instruction in delay slot
add #-128, r5 ! r5 -= 4 * sizeof(VERTEX), move back to 1 vertex before start of quad
.SOME_POINTS_VISIBLE:
.LOOP_END:
dt r6 ! r6--; T = r6 == 0
bf .TRANSFORM_QUAD ! if !T then goto TRANSFORM_QUAD
nop
add #32, r5 ! r5 += sizeof(VERTEX)
rts ! return after executing instruction in delay slot
mov r5,r0 ! r0 = r5
.align 2
CMD_COL_VERT: .long 0xe0000000
CMD_COL_EOS: .long 0xf0000000
.global _VP_COL_HWIDTH
.type _VP_COL_HWIDTH,%object
_VP_COL_HWIDTH: .long 0
.global _VP_COL_HHEIGHT
.type _VP_COL_HHEIGHT,%object
_VP_COL_HHEIGHT: .long 0
.global _VP_COL_X_PLUS_HWIDTH
.type _VP_COL_X_PLUS_HWIDTH,%object
_VP_COL_X_PLUS_HWIDTH: .long 0
.global _VP_COL_Y_PLUS_HHEIGHT
.type _VP_COL_Y_PLUS_HHEIGHT,%object
_VP_COL_Y_PLUS_HHEIGHT: .long 0

View File

@ -0,0 +1,91 @@
!r0 = clip flags
!r1 = GPU command
!r2 = temp
!r3 = prefetch address
!r4 = src pointer ARG
!r5 = dst pointer ARG
!r6 = quads count ARG
!r7 = ?
!fr0 = temp
!fr1 = u
!fr2 = v
!fr3 = c
!fr4 = x
!fr5 = y
!fr6 = z
!fr7 = w
!fr8 = VIEWPORT_HWIDTH
!fr9 = VIEWPORT_HHEIGHT
!fr10 = VIEWPORT_X_PLUS_HWIDTH
!fr11 = VIEWPORT_Y_PLUS_HHEIGHT
!fv4 = XYZW
#include "ViewportTransform.S"
.global _DrawTexturedQuads
.align 4
.type _DrawTexturedQuads,%function
_DrawTexturedQuads:
! Setup
mov r4,r3 ! r3 = src
add #-32, r5 ! r5 -= sizeof(VERTEX)
ViewportTransformSetup _VP_TEX_HWIDTH
.TRANSFORM_QUAD:
mov.l CMD_TEX_VERT, r1 ! r1 = GPU VERT command
LoadTexturedVertex
ProcessVertex1
LoadTexturedVertex
ProcessVertex2
LoadTexturedVertex
ProcessVertex3
LoadTexturedVertex
ProcessVertex4 CMD_TEX_EOS
! CLIPFLAGS TESTING
cmp/eq #0,r0 ! T = r0 == 0 (all points invisible)
bt/s .NO_POINTS_VISIBLE ! if T goto NO_POINTS_VISIBLE
nop
bra .SOME_POINTS_VISIBLE
nop
.NO_POINTS_VISIBLE:
bra .LOOP_END ! jump to loop end after executing instruction in delay slot
add #-128, r5 ! r5 -= 4 * sizeof(VERTEX), move back to prior quad, so that this invisible quad gets overwritten in next iteration
.SOME_POINTS_VISIBLE:
.LOOP_END:
dt r6 ! r6--; T = r6 == 0
bf .TRANSFORM_QUAD ! if !T then goto TRANSFORM_QUAD
nop
add #32, r5 ! r5 += sizeof(VERTEX)
rts ! return after executing instruction in delay slot
mov r5,r0 ! r0 = r5
.align 2
CMD_TEX_VERT: .long 0xe0000000
CMD_TEX_EOS: .long 0xf0000000
.global _VP_TEX_HWIDTH
.type _VP_TEX_HWIDTH,%object
_VP_TEX_HWIDTH: .long 0
.global _VP_TEX_HHEIGHT
.type _VP_TEX_HHEIGHT,%object
_VP_TEX_HHEIGHT: .long 0
.global _VP_TEX_X_PLUS_HWIDTH
.type _VP_TEX_X_PLUS_HWIDTH,%object
_VP_TEX_X_PLUS_HWIDTH: .long 0
.global _VP_TEX_Y_PLUS_HHEIGHT
.type _VP_TEX_Y_PLUS_HHEIGHT,%object
_VP_TEX_Y_PLUS_HHEIGHT: .long 0

View File

@ -1,8 +1,9 @@
BUILD_DIR := build-dc
SOURCE_DIRS := src third_party/bearssl/src
SOURCE_DIRS := src third_party/bearssl/src misc/dreamcast
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)))
OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o)))
CFLAGS :=-g -O1 -pipe -fno-math-errno -Ithird_party/bearssl/inc
GLDC_LIB=third_party/gldc/libGLdc.a
@ -21,8 +22,9 @@ default: $(CC_TEXTURES) $(GLDC_LIB) $(BUILD_DIR) $(TARGET).cdi
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(GLDC_LIB):
$(GLDC_LIB): FORCE
$(MAKE) -C third_party/gldc
FORCE: ;
# TODO add textures to misc folder ?
$(CC_TEXTURES):
@ -31,6 +33,9 @@ $(CC_TEXTURES):
$(BUILD_DIR)/%.o: src/%.c
kos-cc $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/%.o: misc/dreamcast/%.S
kos-cc -c $< -o $@
$(BUILD_DIR)/%.o: third_party/bearssl/src/%.c
kos-cc $(CFLAGS) -c $< -o $@

View File

@ -0,0 +1,161 @@
! =========================================================
! ========================= VERTEX LOADING ================
! =========================================================
.macro LoadColouredVertex
! PREPARE NEXT VERTEX
add #16, r3 ! r3 += VERTEX_STRIDE
pref @r3 ! PREFETCH r3 (next vertex)
add #64, r5 ! r5 += 2 * sizeof(VERTEX)
! LOAD XYZ
fmov @r4+, fr4 ! X = src->x
fmov @r4+, fr5 ! Y = src->y
fmov @r4+, fr6 ! Z = src->z
fldi1 fr7 ! W = 1.0
! TRANSFORM VERTEX
ftrv xmtrx, fv4 ! TRANSFORM(XYZW)
! LOAD ATTRIBUTES
fmov @r4+,fr3 ! C = src->color
.endm
.macro LoadTexturedVertex
! PREPARE NEXT VERTEX
add #24, r3 ! r3 += VERTEX_STRIDE
pref @r3 ! PREFETCH r3 (next vertex)
add #64, r5 ! r5 += 2 * sizeof(VERTEX)
! LOAD XYZ
fmov @r4+, fr4 ! X = src->x
fmov @r4+, fr5 ! Y = src->y
fmov @r4+, fr6 ! Z = src->z
fldi1 fr7 ! W = 1.0
! TRANSFORM VERTEX
ftrv xmtrx, fv4 ! TRANSFORM(XYZW)
! LOAD ATTRIBUTES
fmov @r4+,fr3 ! C = src->color
fmov @r4+,fr1 ! U = src->u
fmov @r4+,fr2 ! V = src->v
.endm
! =========================================================
! ========================= VERTEX OUTPUT =================
! =========================================================
! To take advantage of SH4 dual instruction processing, interleave
! the clipflag calculation and vertex output instructions
.macro ProcessVertex1
fmov.s fr7,@-r5 ! dst->w = W
fmov.s fr3,@-r5 ! dst->c = C
fneg fr7 ! W = -W
fmov.s fr2,@-r5 ! dst->v = V
fcmp/gt fr7,fr6 ! T = Z > W (i.e. Z > -W)
fmov.s fr1,@-r5 ! dst->u = U
movt r0 ! CLIPFLAGS = T
fmov.s fr6,@-r5 ! dst->z = Z
fmov.s fr5,@-r5 ! dst->y = Y
fmov.s fr4,@-r5 ! dst->x = X
mov.l r1,@-r5 ! dst->flags = CMD_VERT
.endm
.macro ProcessVertex2
fmov.s fr7,@-r5 ! dst->w = W
fmov.s fr3,@-r5 ! dst->c = C
fneg fr7 ! W = -W
fmov.s fr2,@-r5 ! dst->v = V
fcmp/gt fr7,fr6 ! T = Z > W (i.e. Z > -W)
fmov.s fr1,@-r5 ! dst->u = U
movt r2 ! tmp = T
fmov.s fr6,@-r5 ! dst->z = Z
add r2,r2 ! tmp = tmp + tmp
fmov.s fr5,@-r5 ! dst->y = Y
or r2,r0 ! CLIPFLAGS |= tmp (T << 1)
fmov.s fr4,@-r5 ! dst->x = X
mov.l r1,@-r5 ! dst->flags = CMD_VERT
.endm
.macro ProcessVertex3
fmov.s fr7,@-r5 ! dst->w = W
fmov.s fr3,@-r5 ! dst->c = C
fneg fr7 ! W = -W
fmov.s fr2,@-r5 ! dst->v = V
fcmp/gt fr7,fr6 ! T = Z > W (i.e. Z > -W)
fmov.s fr1,@-r5 ! dst->u = U
movt r2 ! tmp = T
fmov.s fr6,@-r5 ! dst->z = Z
fmov.s fr5,@-r5 ! dst->y = Y
shll2 r2 ! tmp = tmp << 2
fmov.s fr4,@-r5 ! dst->x = X
or r2,r0 ! CLIPFLAGS |= tmp (T << 2)
mov.l r1,@-r5 ! dst->flags = CMD_VERT
.endm
.macro ProcessVertex4 eos_addr
fmov.s fr7,@-r5 ! dst->w = W
fmov.s fr3,@-r5 ! dst->c = C
fneg fr7 ! W = -W
fmov.s fr2,@-r5 ! dst->v = V
fcmp/gt fr7,fr6 ! T = Z > W (i.e. Z > -W)
fmov.s fr1,@-r5 ! dst->u = U
movt r2 ! tmp = T
fmov.s fr6,@-r5 ! dst->z = Z
shll2 r2 ! tmp = tmp << 2
fmov.s fr5,@-r5 ! dst->y = Y
add r2,r2 ! tmp = (tmp << 2) + (tmp << 2)
fmov.s fr4,@-r5 ! dst->x = X
mov.l \eos_addr, r1 ! r1 = GPU EOS command
or r2,r0 ! CLIPFLAGS |= tmp (T << 3)
or r0,r1 ! r1 |= CLIPFLAGS
mov.l r1,@-r5 ! dst->flags = GPU EOS | CLIPFLAGS
.endm
! =========================================================
! ====================== VIEWPORT TRANSFORM ===============
! =========================================================
!r2 = return addr
!r0 = temp
!r5 = dst pointer
!fr0 = temp
!fr4 = temp
!fr5 = temp
!fr5 = temp
!fr8 = VIEWPORT_HWIDTH
!fr9 = VIEWPORT_HHEIGHT
!fr10 = VIEWPORT_X_PLUS_HWIDTH
!fr11 = VIEWPORT_Y_PLUS_HHEIGHT
.macro ViewportTransformSetup viewport_addr
mova \viewport_addr, r0
fmov.s @r0+,fr8 ! fr8 = VIEWPORT_HWIDTH
fmov.s @r0+,fr9 ! fr9 = VIEWPORT_HHEIGHT
fmov.s @r0+,fr10 ! fr10 = VIEWPORT_X_PLUS_HWIDTH
fmov.s @r0+,fr11 ! fr11 = VIEWPORT_Y_PLUS_HHEIGHT
nop ! align to even instructions
.endm
.macro ViewportTransformVertex
! INVERSE W CALCULATION
add #28, r5 ! r5 = &vertex->w
fmov.s @r5,fr0 ! fr0 = vertex->w
fmul fr0,fr0 ! fr0 = fr0 * fr0
add #-24, r5 ! r5 = &vertex->x
fsrra fr0 ! fr0 = 1 / sqrt(fr0) -> 1 / vertex->w
! TRANSFORM X
fmov.s @r5,fr4 ! fr4 = vertex->x
fmov fr10,fr5 ! fr5 = VIEWPORT_X_PLUS_HWIDTH
fmul fr8,fr4 ! fr4 = VIEWPORT_HWIDTH * vertex->x
fmac fr0,fr4,fr5 ! fr5 = fr0 * fr4 + fr5 -- (X * F * hwidth) + x_plus_hwidth
fmov.s fr5,@r5 ! vertex->x = fr5
add #4, r5 ! r5 = &vertex->y
! TRANSFORM Y
fmov.s @r5,fr4 ! fr4 = vertex->y
fmov fr11,fr5 ! fr5 = VIEWPORT_Y_PLUS_HHEIGHT
fmul fr9,fr4 ! fr4 = VIEWPORT_HHEIGHT * vertex->y
fmac fr0,fr4,fr5 ! fr5 = fr0 * fr4 + fr5 -- (Y * F * hheight) + y_plus_hheight
fmov.s fr5,@r5 ! vertex->y = fr5
add #4, r5 ! r5 = &vertex->z
! ASSIGN Z
fmov.s fr0,@r5 ! vertex->z = fr0
add #20, r5 ! r5 += 20 (points to start of next vertex)
.endm

View File

@ -16,10 +16,10 @@ SH_CFLAGS+= -Os -I. -DPLAT_SATURN
SH_LDFLAGS+=
IP_VERSION:= V1.000
IP_RELEASE_DATE:= 20160101
IP_RELEASE_DATE:= 20230101
IP_AREAS:= JTUBKAEL
IP_PERIPHERALS:= JAMKST
IP_TITLE:= VDP1 drawing
IP_TITLE:= ClassiCube
IP_MASTER_STACK_ADDR:= 0x06004000
IP_SLAVE_STACK_ADDR:= 0x06001E00
IP_1ST_READ_ADDR:= 0x06004000

View File

@ -78,14 +78,15 @@ export VPATH := $(foreach dir,$(SOURCES),$(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,$(DATA),$(notdir $(wildcard $(dir)/*.*))) \
$(foreach dir,$(SHADERS),$(notdir $(wildcard $(dir)/*.gsh)))
export LD := $(CC)
export LD := $(CXX)
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))

View File

@ -163,8 +163,8 @@ static void Png_Reconstruct(cc_uint8 type, cc_uint8 bytesPerPixel, cc_uint8* lin
/* 7.2 Scanlines */
#define PNG_Do_Grayscale(dstI, src, scale) rgb = (src) * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_8() rgb = src[0]; Bitmap_Set(*dst, rgb, rgb, rgb, 255); dst--; src -= 2;
#define PNG_Do_Grayscale_A__8() rgb = src[0]; Bitmap_Set(*dst, rgb, rgb, rgb, src[1]); dst--; src -= 1;
#define PNG_Do_Grayscale_8() rgb = src[0]; Bitmap_Set(*dst, rgb, rgb, rgb, 255); dst--; src -= 1;
#define PNG_Do_Grayscale_A__8() rgb = src[0]; Bitmap_Set(*dst, rgb, rgb, rgb, src[1]); dst--; src -= 2;
#define PNG_Do_RGB__8() Bitmap_Set(*dst, src[0], src[1], src[2], 255); dst--; src -= 3;
#define PNG_Do_RGB_A__8() Bitmap_Set(*dst, src[0], src[1], src[2], src[3]); dst++; src += 4;
#define PNG_Do_Palette__8() *dst-- = palette[*src--];
@ -489,11 +489,13 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) {
if (colorspace == PNG_COLOR_RGB_A) {
/* Prior line is no longer needed and can be overwritten now */
rowExpander(bmp->width, palette, &prior[1], Bitmap_GetRow(bmp, rowY - 1));
/* Current line is also no longer needed and can be overwritten now */
if (rowY == bmp->height - 1)
rowExpander(bmp->width, palette, &scanline[1], Bitmap_GetRow(bmp, rowY));
}
}
/* Current line is also no longer needed and can be overwritten now */
if (colorspace == PNG_COLOR_RGB_A && rowY == bmp->height - 1) {
rowExpander(bmp->width, palette, &scanline[1], Bitmap_GetRow(bmp, rowY));
}
}
/* Check if image fully decoded or not */

View File

@ -360,9 +360,16 @@ static void OutputChunkPartsMeta(int x, int y, int z, struct ChunkInfo* info) {
}
void Builder_MakeChunk(struct ChunkInfo* info) {
#ifdef CC_BUILD_SATURN
/* The Saturn build only has 16 kb stack, not large enough */
static BlockID chunk[EXTCHUNK_SIZE_3];
static cc_uint8 counts[CHUNK_SIZE_3 * FACE_COUNT];
static int bitFlags[1];
#else
BlockID chunk[EXTCHUNK_SIZE_3];
cc_uint8 counts[CHUNK_SIZE_3 * FACE_COUNT];
int bitFlags[EXTCHUNK_SIZE_3];
#endif
cc_bool allAir, allSolid, onBorder;
int xMax, yMax, zMax, totalVerts;
@ -761,6 +768,7 @@ static void NormalBuilder_SetActive(void) {
/*########################################################################################################################*
*-------------------------------------------------Advanced mesh builder---------------------------------------------------*
*#########################################################################################################################*/
#ifdef CC_BUILD_ADVLIGHTING
static Vec3 adv_minBB, adv_maxBB;
static int adv_initBitFlags, adv_baseOffset;
static int* adv_bitFlags;
@ -1259,6 +1267,9 @@ static void AdvBuilder_SetActive(void) {
Builder_RenderBlock = Adv_RenderBlock;
Builder_PrePrepareChunk = Adv_PrePrepareChunk;
}
#else
static void AdvBuilder_SetActive(void) { NormalBuilder_SetActive(); }
#endif
/*########################################################################################################################*

View File

@ -154,8 +154,10 @@ static Vec2 FirstPersonCamera_GetOrientation(struct LocalPlayer* p) {
return v;
}
static Vec3 FirstPersonCamera_GetPosition(struct LocalPlayer* p, float t) {
static Vec3 FirstPersonCamera_GetPosition(float t) {
struct LocalPlayer* p = Entities.CurPlayer;
struct Entity* e = &p->Base;
Vec3 camPos = Entity_GetEyePosition(e);
float yaw = e->Yaw * MATH_DEG2RAD;
PerspectiveCamera_CalcViewBobbing(p, t, 1);
@ -202,8 +204,10 @@ static float ThirdPersonCamera_GetZoom(struct LocalPlayer* p) {
return dist;
}
static Vec3 ThirdPersonCamera_GetPosition(struct LocalPlayer* p, float t) {
static Vec3 ThirdPersonCamera_GetPosition(float t) {
struct LocalPlayer* p = Entities.CurPlayer;
struct Entity* e = &p->Base;
float dist = ThirdPersonCamera_GetZoom(p);
Vec3 target, dir;
Vec2 rot;

View File

@ -51,7 +51,7 @@ struct Camera {
/* Returns the current orientation of the camera. */
Vec2 (*GetOrientation)(struct LocalPlayer* p);
/* Returns the current interpolated position of the camera. */
Vec3 (*GetPosition)(struct LocalPlayer* p, float t);
Vec3 (*GetPosition)(float t);
/* Called to update the camera's state. */
/* Typically, this is used to adjust yaw/pitch based on accumulated mouse movement. */

View File

@ -67,8 +67,8 @@ typedef void (*FP_Chat_AddOf)(const cc_string* text, int msgType);
/* Shorthand for Chat_AddOf(String_FromReadonly(raw), MSG_TYPE_NORMAL) */
void Chat_AddRaw(const char* raw);
void Chat_Add1(const char* format, const void* a1);
void Chat_Add2(const char* format, const void* a1, const void* a2);
void Chat_Add3(const char* format, const void* a1, const void* a2, const void* a3);
void Chat_Add4(const char* format, const void* a1, const void* a2, const void* a3, const void* a4);
CC_API void Chat_Add1(const char* format, const void* a1);
CC_API void Chat_Add2(const char* format, const void* a1, const void* a2);
CC_API void Chat_Add3(const char* format, const void* a1, const void* a2, const void* a3);
CC_API void Chat_Add4(const char* format, const void* a1, const void* a2, const void* a3, const void* a4);
#endif

View File

@ -561,7 +561,7 @@
<ClCompile Include="Window_SDL3.c" />
<ClCompile Include="Window_Switch.c" />
<ClCompile Include="Window_Web.c" />
<ClCompile Include="Window_WiiU.c" />
<ClCompile Include="Window_WiiU.cpp" />
<ClCompile Include="Window_Win.c" />
<ClCompile Include="Window_X11.c" />
<ClCompile Include="Window_Xbox.c" />

View File

@ -728,9 +728,6 @@
<ClCompile Include="Window_SDL3.c">
<Filter>Source Files\Window</Filter>
</ClCompile>
<ClCompile Include="Window_WiiU.c">
<Filter>Source Files\Window</Filter>
</ClCompile>
<ClCompile Include="Platform_NDS.c">
<Filter>Source Files\Platform</Filter>
</ClCompile>
@ -752,6 +749,9 @@
<ClCompile Include="Graphics_WiiU.c">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
<ClCompile Include="Window_WiiU.cpp">
<Filter>Source Files\Window</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\misc\windows\CCicon.rc">

View File

@ -267,6 +267,23 @@ static struct ChatCommand ClearDeniedCommand = {
}
};
static void MotdCommand_Execute(const cc_string* args, int argsCount) {
if (Server.IsSinglePlayer) {
Chat_AddRaw("&eThis command can only be used in multiplayer.");
return;
}
Chat_Add1("&eName: &f%s", &Server.Name);
Chat_Add1("&eMOTD: &f%s", &Server.MOTD);
}
static struct ChatCommand MotdCommand = {
"Motd", MotdCommand_Execute,
COMMAND_FLAG_UNSPLIT_ARGS,
{
"&a/client motd",
"&eDisplays the server's name and MOTD."
}
};
/*########################################################################################################################*
*-------------------------------------------------------DrawOpCommand-----------------------------------------------------*
@ -709,6 +726,7 @@ static void OnInit(void) {
Commands_Register(&ModelCommand);
Commands_Register(&TeleportCommand);
Commands_Register(&ClearDeniedCommand);
Commands_Register(&MotdCommand);
Commands_Register(&BlockEditCommand);
Commands_Register(&CuboidCommand);
Commands_Register(&ReplaceCommand);

View File

@ -67,9 +67,8 @@ enum SKIN_TYPE { SKIN_64x32, SKIN_64x64, SKIN_64x64_SLIM, SKIN_INVALID = 0xF0 };
#define Int32_MinValue ((cc_int32)-2147483647L - (cc_int32)1L)
#define Int32_MaxValue ((cc_int32)2147483647L)
/* Skins were moved to use Amazon S3, so link directly to avoid a pointless redirect */
#define SKINS_SERVER "http://cdn.classicube.net/skin"
#define UPDATES_SERVER "http://cs.classicube.net/client"
#define UPDATES_SERVER "http://cdn.classicube.net/client"
#define SERVICES_SERVER "https://www.classicube.net/api"
#define RESOURCE_SERVER "http://static.classicube.net"
/* Webpage where users can register for a new account */

View File

@ -124,6 +124,7 @@ typedef cc_uint8 cc_bool;
#define CC_BUILD_PLUGINS
#define CC_BUILD_ANIMATIONS
#define CC_BUILD_FILESYSTEM
#define CC_BUILD_ADVLIGHTING
/*#define CC_BUILD_GL11*/
#ifndef CC_BUILD_MANUAL
@ -297,7 +298,6 @@ typedef cc_uint8 cc_bool;
#elif defined __vita__
#define CC_BUILD_PSVITA
#define CC_BUILD_CONSOLE
#define CC_BUILD_LOWMEM
#define CC_BUILD_OPENAL
#define CC_BUILD_HTTPCLIENT
#define CC_BUILD_BEARSSL
@ -313,7 +313,6 @@ typedef cc_uint8 cc_bool;
#elif defined PLAT_PS3
#define CC_BUILD_PS3
#define CC_BUILD_CONSOLE
#define CC_BUILD_LOWMEM
#define CC_BUILD_OPENAL
#define CC_BUILD_HTTPCLIENT
#define CC_BUILD_BEARSSL
@ -347,6 +346,7 @@ typedef cc_uint8 cc_bool;
#define CC_BUILD_TOUCH
#undef CC_BUILD_RESOURCES
#undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */
#undef CC_BUILD_ADVLIGHTING
#elif defined __WIIU__
#define CC_BUILD_WIIU
#define CC_BUILD_CONSOLE
@ -354,6 +354,7 @@ typedef cc_uint8 cc_bool;
#define CC_BUILD_OPENAL
#define CC_BUILD_HTTPCLIENT
#define CC_BUILD_BEARSSL
#define CC_BUILD_SPLITSCREEN
#define CC_BUILD_TOUCH
#elif defined __SWITCH__
#define CC_BUILD_SWITCH
@ -375,6 +376,7 @@ typedef cc_uint8 cc_bool;
#undef CC_BUILD_RESOURCES
#undef CC_BUILD_NETWORKING
#undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */
#undef CC_BUILD_ADVLIGHTING
#undef CC_BUILD_FILESYSTEM
#elif defined OS2
#define CC_BUILD_OS2
@ -393,6 +395,7 @@ typedef cc_uint8 cc_bool;
#undef CC_BUILD_RESOURCES
#undef CC_BUILD_NETWORKING
#undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */
#undef CC_BUILD_ADVLIGHTING
#undef CC_BUILD_FILESYSTEM
#endif
#endif

View File

@ -243,7 +243,7 @@ static cc_result Huffman_Build(struct HuffmanTable* table, const cc_uint8* bitLe
* - set fast value to specify a 'value' value, and to skip 'len' bits
*/
if (len <= INFLATE_FAST_BITS) {
cc_int16 packed = (cc_int16)((len << INFLATE_FAST_BITS) | value);
cc_int16 packed = (cc_int16)((len << INFLATE_FAST_LEN_SHIFT) | value);
int codeword = table->firstCodewords[len] + (bl_offsets[len] - table->firstOffsets[len]);
codeword <<= (INFLATE_FAST_BITS - len);
@ -273,9 +273,9 @@ static int Huffman_Decode(struct InflateState* state, struct HuffmanTable* table
if (state->NumBits >= INFLATE_FAST_BITS) {
packed = table->fast[Inflate_PeekBits(state, INFLATE_FAST_BITS)];
if (packed >= 0) {
bits = packed >> INFLATE_FAST_BITS;
bits = packed >> INFLATE_FAST_LEN_SHIFT;
Inflate_ConsumeBits(state, bits);
return packed & 0x1FF;
return packed & INFLATE_FAST_VAL_MASK;
}
}

View File

@ -27,7 +27,11 @@ cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header);
#define INFLATE_MAX_DISTS 32
#define INFLATE_MAX_LITS_DISTS (INFLATE_MAX_LITS + INFLATE_MAX_DISTS)
#define INFLATE_MAX_BITS 16
#define INFLATE_FAST_BITS 9
#define INFLATE_FAST_LEN_SHIFT 9
#define INFLATE_FAST_VAL_MASK 0x1FF
#define INFLATE_WINDOW_SIZE 0x8000UL
#define INFLATE_WINDOW_MASK 0x7FFFUL

View File

@ -539,6 +539,12 @@ static void DrawBitmappedTextCore(struct Bitmap* bmp, struct DrawTextArgs* args,
static void DrawBitmappedText(struct Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
int offset = Drawer2D_ShadowOffset(args->font->size);
if (!fontBitmap.scan0) {
if (args->useShadow) FallbackFont_DrawText(args, bmp, x, y, true);
FallbackFont_DrawText(args, bmp, x, y, false);
return;
}
if (args->useShadow) {
DrawBitmappedTextCore(bmp, args, x + offset, y + offset, true);
}
@ -550,6 +556,8 @@ static int MeasureBitmappedWidth(const struct DrawTextArgs* args) {
int xPadding, width;
cc_string text;
if (!fontBitmap.scan0) return FallbackFont_TextWidth(args);
/* adjust coords to make drawn text match GDI fonts */
xPadding = Drawer2D_XPadding(point);
width = 0;

View File

@ -622,6 +622,11 @@ void LocalPlayerInput_Add(struct LocalPlayerInput* source) {
LinkedList_Append(source, sources_head, sources_tail);
}
void LocalPlayerInput_Remove(struct LocalPlayerInput* source) {
struct LocalPlayerInput* cur;
LinkedList_Remove(source, cur, sources_head, sources_tail);
}
float LocalPlayer_JumpHeight(struct LocalPlayer* p) {
return (float)PhysicsComp_CalcMaxHeight(p->Physics.JumpVel);
}
@ -887,7 +892,9 @@ cc_bool LocalPlayer_HandleSetSpawn(struct LocalPlayer* p) {
/* Spawn is normally centered to match vanilla Minecraft classic */
if (!p->Hacks.CanNoclip) {
p->Spawn = p->Base.Position;
/* Don't want to use Position because it is interpolated between prev and next. */
/* This means it can be halfway between stepping up a stair and clip through the floor. */
p->Spawn = p->Base.prev.pos;
} else {
p->Spawn.x = Math_Floor(p->Base.Position.x) + 0.5f;
p->Spawn.y = p->Base.Position.y;
@ -968,7 +975,7 @@ void LocalPlayers_MoveToSpawn(struct LocationUpdate* update) {
}
/* TODO: This needs to be before new map... */
Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, 0.0f);
Camera.CurrentPos = Camera.Active->GetPosition(0.0f);
}
void LocalPlayer_CalcDefaultSpawn(struct LocalPlayer* p, struct LocationUpdate* update) {
@ -1062,6 +1069,7 @@ static void Entities_Free(void) {
{
Entities_Remove((EntityID)i);
}
sources_head = NULL;
}
struct IGameComponent Entities_Component = {

View File

@ -231,6 +231,7 @@ struct LocalPlayerInput {
struct LocalPlayerInput* next;
};
void LocalPlayerInput_Add(struct LocalPlayerInput* source);
void LocalPlayerInput_Remove(struct LocalPlayerInput* source);
/* Represents the user/player's own entity. */
struct LocalPlayer {

View File

@ -19,7 +19,7 @@ static cc_bool shadows_boundTex;
static GfxResourceID shadows_VB;
static GfxResourceID shadows_tex;
static float shadow_radius, shadow_uvScale;
struct ShadowData { float y; BlockID Block; cc_uint8 A; };
struct ShadowData { float y; BlockID block; cc_uint8 alpha; };
/* Circle shadows extend at most 4 blocks vertically */
#define SHADOW_MAX_RANGE 4
@ -54,7 +54,7 @@ static void EntityShadow_DrawCoords(struct VertexTextured** vertices, struct Ent
z2 = min(z2, cen.z + shadow_radius); v2 = v2 <= 1.0f ? v2 : 1.0f;
v = *vertices;
col = PackedCol_Make(255, 255, 255, data->A);
col = PackedCol_Make(255, 255, 255, data->alpha);
v->x = x1; v->y = data->y; v->z = z1; v->Col = col; v->U = u1; v->V = v1; v++;
v->x = x2; v->y = data->y; v->z = z1; v->Col = col; v->U = u2; v->V = v1; v++;
@ -83,13 +83,13 @@ static void EntityShadow_DrawCircle(struct VertexTextured** vertices, struct Ent
Vec3 min, max, nMin, nMax;
int i;
x = (float)Math_Floor(x); z = (float)Math_Floor(z);
min = Blocks.MinBB[data[0].Block]; max = Blocks.MaxBB[data[0].Block];
min = Blocks.MinBB[data[0].block]; max = Blocks.MaxBB[data[0].block];
EntityShadow_DrawCoords(vertices, e, &data[0], x + min.x, z + min.z, x + max.x, z + max.z);
for (i = 1; i < 4; i++)
{
if (data[i].Block == BLOCK_AIR) return;
nMin = Blocks.MinBB[data[i].Block]; nMax = Blocks.MaxBB[data[i].Block];
if (data[i].block == BLOCK_AIR) return;
nMin = Blocks.MinBB[data[i].block]; nMax = Blocks.MaxBB[data[i].block];
EntityShadow_DrawCoords(vertices, e, &data[i], x + min.x, z + nMin.z, x + max.x, z + min.z);
EntityShadow_DrawCoords(vertices, e, &data[i], x + min.x, z + max.z, x + max.x, z + nMax.z);
@ -103,11 +103,12 @@ static void EntityShadow_DrawCircle(struct VertexTextured** vertices, struct Ent
static void EntityShadow_CalcAlpha(float playerY, struct ShadowData* data) {
float height = playerY - data->y;
if (height <= 6.0f) {
data->A = (cc_uint8)(160 - 160 * height / 6.0f);
data->y += 1.0f / 64.0f; return;
data->alpha = (cc_uint8)(160 - 160 * height / 6.0f);
data->y += 1.0f / 64.0f;
return;
}
data->A = 0;
data->alpha = 0;
if (height <= 16.0f) data->y += 1.0f / 64.0f;
else if (height <= 32.0f) data->y += 1.0f / 16.0f;
else if (height <= 96.0f) data->y += 1.0f / 8.0f;
@ -144,7 +145,7 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str
topY = y + Blocks.MaxBB[block].y;
if (topY >= posY + 0.01f) continue;
cur->Block = block; cur->y = topY;
cur->block = block; cur->y = topY;
EntityShadow_CalcAlpha(posY, cur);
i++; cur++;
@ -154,7 +155,7 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str
}
if (i < 4) {
cur->Block = Env.EdgeBlock; cur->y = 0.0f;
cur->block = Env.EdgeBlock; cur->y = 0.0f;
EntityShadow_CalcAlpha(posY, cur);
i++; cur++;
}
@ -188,16 +189,16 @@ static void EntityShadow_Draw(struct Entity* e) {
x1 = Math_Floor(pos.x - shadow_radius); z1 = Math_Floor(pos.z - shadow_radius);
x2 = Math_Floor(pos.x + shadow_radius); z2 = Math_Floor(pos.z + shadow_radius);
if (EntityShadow_GetBlocks(e, x1, y, z1, data) && data[0].A > 0) {
if (EntityShadow_GetBlocks(e, x1, y, z1, data) && data[0].alpha > 0) {
EntityShadow_DrawCircle(&ptr, e, data, (float)x1, (float)z1);
}
if (x1 != x2 && EntityShadow_GetBlocks(e, x2, y, z1, data) && data[0].A > 0) {
if (x1 != x2 && EntityShadow_GetBlocks(e, x2, y, z1, data) && data[0].alpha > 0) {
EntityShadow_DrawCircle(&ptr, e, data, (float)x2, (float)z1);
}
if (z1 != z2 && EntityShadow_GetBlocks(e, x1, y, z2, data) && data[0].A > 0) {
if (z1 != z2 && EntityShadow_GetBlocks(e, x1, y, z2, data) && data[0].alpha > 0) {
EntityShadow_DrawCircle(&ptr, e, data, (float)x1, (float)z2);
}
if (x1 != x2 && z1 != z2 && EntityShadow_GetBlocks(e, x2, y, z2, data) && data[0].A > 0) {
if (x1 != x2 && z1 != z2 && EntityShadow_GetBlocks(e, x2, y, z2, data) && data[0].alpha > 0) {
EntityShadow_DrawCircle(&ptr, e, data, (float)x2, (float)z2);
}
}
@ -262,6 +263,7 @@ void EntityShadows_Render(void) {
if (Entities.ShadowsMode == SHADOW_MODE_CIRCLE_ALL) {
for (i = 0; i < ENTITIES_MAX_COUNT; i++)
{
e = Entities.List[i];
if (!e || !e->ShouldRender || e == &Entities.CurPlayer->Base) continue;
EntityShadow_Draw(e);
}

View File

@ -132,7 +132,8 @@ enum CC_ERRORS {
HTTP_ERR_RELATIVE = 0xCCDED069UL, /* Unsupported relative URL format */
HTTP_ERR_INVALID_BODY= 0xCCDED06AUL, /* HTTP message doesn't have Content-Length or use Chunked transfer encoding */
HTTP_ERR_CHUNK_SIZE = 0xCCDED06BUL, /* HTTP message chunk has negative size/length */
HTTP_ERR_TRUNCATED = 0xCCDED06CUL, /* HTTP respone header was truncated due to being too long */
HTTP_ERR_TRUNCATED = 0xCCDED06CUL, /* HTTP response header was truncated due to being too long */
HTTP_ERR_NO_RESPONSE = 0xCCDED06DUL, /* First attempt to read response returned 0 bytes */
SSL_ERR_CONTEXT_DEAD = 0xCCDED070UL, /* Server shutdown the SSL context and it must be recreated */
PNG_ERR_16BITSAMPLES = 0xCCDED071UL, /* Image uses 16 bit samples, which is unimplemented */

View File

@ -4,6 +4,8 @@
/* For abs(x) function */
#include <stdlib.h>
#define PI 3.141592653589793238462643383279502884197169399
/* Sega saturn is missing these intrinsics */
#ifdef CC_BUILD_SATURN
#include <stdint.h>
@ -80,8 +82,8 @@ float Math_ClampAngle(float degrees) {
}
float Math_LerpAngle(float leftAngle, float rightAngle, float t) {
/* We have to cheat a bit for angles here */
/* Consider 350* --> 0*, we only want to travel 10* */
/* Need to potentially adjust a bit when interpolating some angles */
/* Consider 350* --> 0*, we only want to interpolate across the 10* */
/* But without adjusting for this case, we would interpolate back the whole 350* degrees */
cc_bool invertLeft = leftAngle > 270.0f && rightAngle < 90.0f;
cc_bool invertRight = rightAngle > 270.0f && leftAngle < 90.0f;
@ -147,8 +149,6 @@ float Random_Float(RNGState* seed) {
/*########################################################################################################################*
*--------------------------------------------------Transcendental functions-----------------------------------------------*
*#########################################################################################################################*/
static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769;
#ifdef CC_BUILD_DREAMCAST
#include <math.h>
@ -156,12 +156,10 @@ static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769;
/* TODO: Properly investigate this issue */
/* double make_dreamcast_build_compile(void) { fabs(4); } */
double Math_Sin(double x) { return sin(x); }
double Math_Cos(double x) { return cos(x); }
double Math_Sin(double x) { return sinf(x); }
double Math_Cos(double x) { return cosf(x); }
double Math_Exp2(double x) { return exp2(x); }
double Math_Log2(double x) { return log2(x); }
double Math_Atan2(double x, double y) { return atan2(y, x); }
#else
/***** Caleb's Math functions *****/
@ -187,7 +185,7 @@ double Math_Atan2(double x, double y) { return atan2(y, x); }
/* from the mathematical functions anyways */
/* Global constants */
#define PI 3.141592653589793238462643383279502884197169399
static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769;
#define DIV_2_PI (1.0 / (2.0 * PI))
static const cc_uint64 _DBL_NAN = 0x7FF8000000000000ULL;
@ -296,149 +294,6 @@ double Math_Cos(double x) {
return SinStage3(x_div_pi_shifted - Floord(x_div_pi_shifted));
}
/**************
* Math_Atan2 *
**************/
/* Calculates the 5th degree polynomial ARCTN 4903 listed in the book's
* appendix.
*
* Associated math function: arctan(x)
* Allowed input range: [0, tan(pi/32)]
* Precision: 16.52
*/
static double AtanStage1(double x) {
const double A[] = {
.99999999999969557,
-.3333333333318,
.1999999997276,
-.14285702288,
.11108719478,
-.8870580341e-1,
};
double P = A[5];
double x_2 = x * x;
int i;
for (i = 4; i >= 0; i--) {
P *= x_2;
P += A[i];
}
P *= x;
return P;
}
/* This function finds out in which partition the non-negative real number x
* resides out of 8 partitions, which are precomputed. It then uses the
* following law:
*
* t = x_i^{-1} - (x_i^{-2} + 1)/(x_i^{-1} + x)
* arctan(x) = arctan(x_i) + arctan(t)
*
* where x_i = tan((2i - 2)*pi/32) and i is the partition number. The value of t
* is guaranteed to be between [-tan(pi/32), tan(pi/32)].
*
* Associated math function: arctan(x)
* Allowed input range: [0, infinity]
*/
static double AtanStage2(double x) {
const double X_i[] = {
0.0,
0.0984914033571642477671304050090839155018329620361328125,
0.3033466836073424044428747947677038609981536865234375,
0.53451113595079158269385288804187439382076263427734375,
0.82067879082866024287312711749109439551830291748046875,
1.218503525587976366040265929768793284893035888671875,
1.8708684117893887854933154812897555530071258544921875,
3.29655820893832096629694206058047711849212646484375,
(float)(1e+300 * 1e+300) /* Infinity */
};
const double div_x_i[] = {
0,
0,
5.02733949212584807497705696732737123966217041015625,
2.41421356237309492343001693370752036571502685546875,
1.496605762665489169904731170390732586383819580078125,
1.0000000000000002220446049250313080847263336181640625,
0.66817863791929898997778991542872972786426544189453125,
0.414213562373095089963470627481001429259777069091796875,
0.1989123673796580893391450217677629552781581878662109375,
};
const double div_x_i_2_plus_1[] = {
0,
0,
26.2741423690881816810360760428011417388916015625,
6.8284271247461898468600338674150407314300537109375,
3.23982880884355051165357508580200374126434326171875,
2.000000000000000444089209850062616169452667236328125,
1.446462692171689656817079594475217163562774658203125,
1.1715728752538099310953612075536511838436126708984375,
1.0395661298965801488947136022034101188182830810546875,
};
int L = 0;
int R = 8;
double t;
while (R - L > 1) {
int m = (L + R) / 2;
if (X_i[m] <= x)
L = m;
else if (X_i[m] > x)
R = m;
}
if (R <= 1)
return AtanStage1(x);
t = div_x_i[R] - div_x_i_2_plus_1[R] / (div_x_i[R] + x);
if (t >= 0)
return (2 * R - 2) * PI / 32.0 + AtanStage1(t);
return (2 * R - 2) * PI / 32.0 - AtanStage1(-t);
}
/* Uses the property arctan(x) = -arctan(-x).
*
* Associated math function: arctan(x)
* Allowed input range: anything
*/
static double Atan(double x) {
if (x == DBL_NAN)
return DBL_NAN;
if (x == NEG_INF)
return -PI / 2.0;
if (x == POS_INF)
return PI / 2.0;
if (x >= 0)
return AtanStage2(x);
return -AtanStage2(-x);
}
/* Implements the function atan2 using Atan.
*
* Associated math function: atan2(y, x)
* Allowed input range: anything
*/
double Math_Atan2(double x, double y) {
if (x > 0)
return Atan(y / x);
if (x < 0) {
if (y >= 0)
return Atan(y / x) + PI;
return Atan(y / x) - PI;
}
/* x = 0 case */
if (y > 0) return PI / 2.0;
if (y < 0) return -PI / 2.0;
return DBL_NAN;
}
/************
* Math_Exp *
************/
@ -576,7 +431,7 @@ double Math_Log2(double x) {
if (x == POS_INF)
return POS_INF;
if (x == NEG_INF || x == DBL_NAN || x <= 0.0)
if (x == DBL_NAN || x <= 0.0)
return DBL_NAN;
doi.d = x;
@ -588,5 +443,26 @@ double Math_Log2(double x) {
return exponent + Log2Stage1(doi.d);
}
#endif
// Approximation of atan2f using the Remez algorithm
// https://math.stackexchange.com/a/1105038
float Math_Atan2f(float x, float y) {
if (x == 0) {
if (y > 0) return PI / 2.0f;
if (y < 0) return -PI / 2.0f;
return 0; /* Should probably be NaN */
}
float ax = Math_AbsF(x);
float ay = Math_AbsF(y);
float a = (ax < ay) ? (ax / ay) : (ay / ax);
float s = a * a;
float r = ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a;
if (ay > ax) r = 1.57079637f - r;
if (x < 0) r = 3.14159274f - r;
if (y < 0) r = -r;
return r;
}

View File

@ -31,7 +31,9 @@ CC_API double Math_Sin(double x);
CC_API double Math_Cos(double x);
float Math_SinF(float x);
float Math_CosF(float x);
double Math_Atan2(double x, double y);
/* Computes atan2(y, x), intended primarily for angle calculation*/
/* Note that accuracy is only up to around 4 decimal places */
float Math_Atan2f(float x, float y);
/* Computes log2(x). Can also be used to approximate log_y(x). */
/* e.g. for log3(x), use: log2(x)/log2(3) */

View File

@ -640,7 +640,7 @@ static void DrawSplitscreen(float delta, float t, int i, int x, int y, int w, in
Entities.CurPlayer = &LocalPlayer_Instances[i];
LocalPlayer_SetInterpPosition(Entities.CurPlayer, t);
Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, t);
Camera.CurrentPos = Camera.Active->GetPosition(t);
Game_DrawFrame(delta, t);
}
@ -684,7 +684,7 @@ static CC_INLINE void Game_RenderFrame(double delta) {
t = (float)(entTask.accumulator / entTask.interval);
LocalPlayer_SetInterpPosition(Entities.CurPlayer, t);
Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, t);
Camera.CurrentPos = Camera.Active->GetPosition(t);
/* NOTE: EnvRenderer_UpdateFog also also sets clear color */
EnvRenderer_UpdateFog();
AudioBackend_Tick();

View File

@ -439,7 +439,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
if (enabled) {
C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
} else {
@ -447,7 +447,7 @@ void Gfx_SetAlphaBlending(cc_bool enabled) {
}
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
C3D_AlphaTest(enabled, GPU_GREATER, 0x7F);
}

View File

@ -691,7 +691,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
static ID3D11SamplerState* ps_samplers[2];
static ID3D11PixelShader* ps_shaders[12];
static ID3D11Buffer* ps_cBuffer;
static cc_bool ps_alphaTesting, ps_mipmaps;
static cc_bool ps_mipmaps;
static float ps_fogEnd, ps_fogDensity;
static PackedCol ps_fogColor;
static int ps_fogMode;
@ -725,7 +725,7 @@ static void PS_CreateShaders(void) {
static int PS_CalcShaderIndex(void) {
int idx = gfx_format == VERTEX_FORMAT_COLOURED ? 0 : 1;
if (ps_alphaTesting) idx += 2;
if (gfx_alphaTest) idx += 2;
if (gfx_fogEnabled) {
// uncomment when it works
@ -822,8 +822,7 @@ static void PS_Free(void) {
PS_FreeConstants();
}
void Gfx_SetAlphaTest(cc_bool enabled) {
ps_alphaTesting = enabled;
static void SetAlphaTest(cc_bool enabled) {
PS_UpdateShader();
}
// unnecessary? check if any performance is gained, probably irrelevant
@ -887,10 +886,10 @@ void Gfx_DisableMipmaps(void) {
static ID3D11RenderTargetView* backbuffer;
static ID3D11Texture2D* depthbuffer;
static ID3D11DepthStencilView* depthbufferView;
static ID3D11BlendState* om_blendStates[4];
static ID3D11BlendState* om_blendStates[16 * 2];
static ID3D11DepthStencilState* om_depthStates[4];
static float gfx_clearColor[4];
static cc_bool gfx_alphaBlending, gfx_colorEnabled = true;
static cc_bool gfx_channels[4] = { true, true, true, true };
static cc_bool gfx_depthTest, gfx_depthWrite;
static void OM_Clear(GfxBuffers buffers) {
@ -972,8 +971,14 @@ static void OM_CreateBlendStates(void) {
for (int i = 0; i < Array_Elems(om_blendStates); i++)
{
desc.RenderTarget[0].RenderTargetWriteMask = (i & 1) ? D3D11_COLOR_WRITE_ENABLE_ALL : 0;
desc.RenderTarget[0].BlendEnable = (i & 2) != 0;
int mask = 0;
if (i & 0x01) mask |= D3D11_COLOR_WRITE_ENABLE_RED;
if (i & 0x02) mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
if (i & 0x04) mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
if (i & 0x08) mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
desc.RenderTarget[0].RenderTargetWriteMask = mask;
desc.RenderTarget[0].BlendEnable = (i & 0x10) != 0;
hr = ID3D11Device_CreateBlendState(device, &desc, &om_blendStates[i]);
if (hr) Logger_Abort2(hr, "Failed to create blend state");
@ -981,7 +986,8 @@ static void OM_CreateBlendStates(void) {
}
static void OM_UpdateBlendState(void) {
ID3D11BlendState* blendState = om_blendStates[gfx_colorEnabled | (gfx_alphaBlending << 1)];
int idx = (gfx_channels[0]) | (gfx_channels[1] << 1) | (gfx_channels[2] << 2) | (gfx_channels[3] << 3) | (gfx_alphaBlend << 4);
ID3D11BlendState* blendState = om_blendStates[idx];
ID3D11DeviceContext_OMSetBlendState(context, blendState, NULL, 0xffffffff);
}
@ -1030,15 +1036,16 @@ void Gfx_SetDepthWrite(cc_bool enabled) {
OM_UpdateDepthState();
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
gfx_alphaBlending = enabled;
static void SetAlphaBlend(cc_bool enabled) {
OM_UpdateBlendState();
}
static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
gfx_colorEnabled = r;
gfx_channels[0] = r;
gfx_channels[1] = g;
gfx_channels[2] = b;
gfx_channels[3] = a;
OM_UpdateBlendState();
// TODO all channels
}
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {

View File

@ -394,7 +394,7 @@ void Gfx_DisableMipmaps(void) {
*-----------------------------------------------------State management----------------------------------------------------*
*#########################################################################################################################*/
static D3DFOGMODE gfx_fogMode = D3DFOG_NONE;
static cc_bool gfx_alphaTesting, gfx_alphaBlending;
static cc_bool gfx_alphaBlending;
static cc_bool gfx_depthTesting, gfx_depthWriting;
static PackedCol gfx_clearColor, gfx_fogColor;
static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f;
@ -455,18 +455,12 @@ void Gfx_SetFogMode(FogFunc func) {
IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, mode);
}
void Gfx_SetAlphaTest(cc_bool enabled) {
if (gfx_alphaTesting == enabled) return;
gfx_alphaTesting = enabled;
static void SetAlphaTest(cc_bool enabled) {
if (Gfx.LostContext) return;
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, enabled);
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
if (gfx_alphaBlending == enabled) return;
gfx_alphaBlending = enabled;
static void SetAlphaBlend(cc_bool enabled) {
if (Gfx.LostContext) return;
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, enabled);
}
@ -529,7 +523,7 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
static void D3D9_RestoreRenderStates(void) {
union IntAndFloat raw;
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, gfx_alphaTesting);
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, gfx_alphaTest);
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, gfx_alphaBlending);
IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, gfx_fogEnabled);

View File

@ -5,6 +5,7 @@
#include "Logger.h"
#include "Window.h"
#include "../third_party/gldc/gldc.h"
#include "../third_party/gldc/src/draw.c"
#include <malloc.h>
#include <kos.h>
#include <dc/matrix.h>
@ -30,6 +31,7 @@ static void InitGLState(void) {
void Gfx_Create(void) {
if (!Gfx.Created) glKosInit();
Gfx_SetViewport(0, 0, Game.Width, Game.Height);
InitGLState();
@ -59,7 +61,7 @@ void Gfx_Free(void) {
*#########################################################################################################################*/
static PackedCol gfx_clearColor;
void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); }
void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); }
static void SetAlphaBlend(cc_bool enabled) { gl_Toggle(GL_BLEND); }
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
void Gfx_ClearColor(PackedCol color) {
@ -79,7 +81,7 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
void Gfx_SetDepthWrite(cc_bool enabled) { glDepthMask(enabled); }
void Gfx_SetDepthTest(cc_bool enabled) { gl_Toggle(GL_DEPTH_TEST); }
void Gfx_SetAlphaTest(cc_bool enabled) { gl_Toggle(GL_ALPHA_TEST); }
static void SetAlphaTest(cc_bool enabled) { gl_Toggle(GL_ALPHA_TEST); }
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
// don't need a fake second pass in this case
@ -352,7 +354,7 @@ static FogFunc gfx_fogMode = -1;
void Gfx_SetFog(cc_bool enabled) {
gfx_fogEnabled = enabled;
if (enabled) { glEnable(GL_FOG); } else { glDisable(GL_FOG); }
gl_Toggle(GL_FOG);
}
void Gfx_SetFogCol(PackedCol color) {
@ -465,15 +467,35 @@ cc_bool Gfx_WarnIfNecessary(void) {
*----------------------------------------------------------Drawing--------------------------------------------------------*
*#########################################################################################################################*/
#define VB_PTR gfx_vertices
static const void* VERTEX_PTR;
extern void apply_poly_header(PolyHeader* header, PolyList* activePolyList);
static void SetupVertices(int startVertex) {
if (gfx_format == VERTEX_FORMAT_TEXTURED) {
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
gldcVertexPointer(SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
} else {
cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED;
gldcVertexPointer(SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset));
extern Vertex* DrawColouredQuads(const void* src, Vertex* dst, int numQuads);
extern Vertex* DrawTexturedQuads(const void* src, Vertex* dst, int numQuads);
void DrawQuads(int count) {
if (!count) return;
PolyList* output = _glActivePolyList();
AlignedVectorHeader* hdr = &output->vector.hdr;
uint32_t header_required = (hdr->size == 0) || STATE_DIRTY;
// Reserve room for the vertices and header
Vertex* beg = aligned_vector_reserve(&output->vector, hdr->size + (header_required) + count);
if (header_required) {
apply_poly_header((PolyHeader*)beg, output);
STATE_DIRTY = GL_FALSE;
beg++;
hdr->size += 1;
}
Vertex* end;
if (TEXTURES_ENABLED) {
end = DrawTexturedQuads(VERTEX_PTR, beg, count >> 2);
} else {
end = DrawColouredQuads(VERTEX_PTR, beg, count >> 2);
}
hdr->size += (end - beg);
}
void Gfx_SetVertexFormat(VertexFormat fmt) {
@ -489,29 +511,33 @@ void Gfx_SetVertexFormat(VertexFormat fmt) {
}
void Gfx_DrawVb_Lines(int verticesCount) {
SetupVertices(0);
//SetupVertices(0);
//glDrawArrays(GL_LINES, 0, verticesCount);
}
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
SetupVertices(startVertex);
glDrawArrays(GL_QUADS, 0, verticesCount);
if (gfx_format == VERTEX_FORMAT_TEXTURED) {
VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED;
} else {
VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_COLOURED;
}
DrawQuads(verticesCount);
}
void Gfx_DrawVb_IndexedTris(int verticesCount) {
SetupVertices(0);
VERTEX_PTR = gfx_vertices;
if (textureOffset) ShiftTextureCoords(verticesCount);
glDrawArrays(GL_QUADS, 0, verticesCount);
DrawQuads(verticesCount);
if (textureOffset) UnshiftTextureCoords(verticesCount);
}
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
if (renderingDisabled) return;
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
gldcVertexPointer(SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
glDrawArrays(GL_QUADS, 0, verticesCount);
VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED;
DrawQuads(verticesCount);
}
@ -550,6 +576,7 @@ void Gfx_ClearBuffers(GfxBuffers buffers) {
}
void Gfx_EndFrame(void) {
pvr_wait_ready();
glKosSwapBuffers();
if (gfx_minFrameMs) LimitFPS();
}
@ -558,6 +585,11 @@ void Gfx_OnWindowResize(void) {
Gfx_SetViewport(0, 0, Game.Width, Game.Height);
}
extern float VP_COL_HWIDTH, VP_TEX_HWIDTH;
extern float VP_COL_HHEIGHT, VP_TEX_HHEIGHT;
extern float VP_COL_X_PLUS_HWIDTH, VP_TEX_X_PLUS_HWIDTH;
extern float VP_COL_Y_PLUS_HHEIGHT, VP_TEX_Y_PLUS_HHEIGHT;
void Gfx_SetViewport(int x, int y, int w, int h) {
if (x == 0 && y == 0 && w == Game.Width && h == Game.Height) {
glDisable(GL_SCISSOR_TEST);
@ -567,5 +599,11 @@ void Gfx_SetViewport(int x, int y, int w, int h) {
glViewport(x, y, w, h);
glScissor (x, y, w, h);
VP_COL_HWIDTH = VP_TEX_HWIDTH = w * 0.5f;
VP_COL_HHEIGHT = VP_TEX_HHEIGHT = h * -0.5f;
VP_COL_X_PLUS_HWIDTH = VP_TEX_X_PLUS_HWIDTH = x + w * 0.5f;
VP_COL_Y_PLUS_HHEIGHT = VP_TEX_Y_PLUS_HHEIGHT = y + h * 0.5f;
}
#endif

View File

@ -187,7 +187,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
GX_SetCullMode(enabled ? GX_CULL_FRONT : GX_CULL_NONE);
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
if (enabled) {
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
} else {
@ -409,7 +409,7 @@ void Gfx_SetFogEnd(float value) {
void Gfx_SetFogMode(FogFunc func) {
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
if (enabled) {
GX_SetAlphaCompare(GX_GREATER, 127, GX_AOP_AND, GX_ALWAYS, 0);
} else {
@ -560,7 +560,7 @@ 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_Color4u8(PackedCol_R(v->Col), PackedCol_G(v->Col), PackedCol_B(v->Col), PackedCol_A(v->Col));
GX_Color1u32(v->Col);
}
GX_End();
}
@ -572,7 +572,7 @@ 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_Color4u8(PackedCol_R(v->Col), PackedCol_G(v->Col), PackedCol_B(v->Col), PackedCol_A(v->Col));
GX_Color1u32(v->Col);
GX_TexCoord2f32(v->U, v->V);
}
GX_End();

View File

@ -534,7 +534,7 @@ void Gfx_SetFogMode(FogFunc func) {
gfx_fogMode = func;
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
if (enabled) { glEnable(GL_ALPHA_TEST); } else { glDisable(GL_ALPHA_TEST); }
}

View File

@ -202,7 +202,7 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
/* cached uniforms (cached for multiple programs */
static struct Matrix _view, _proj, _mvp;
static cc_bool gfx_alphaTest, gfx_texTransform;
static cc_bool gfx_texTransform;
static float _texX, _texY;
static PackedCol gfx_fogColor;
static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f;
@ -500,7 +500,7 @@ void Gfx_SetFogMode(FogFunc func) {
SwitchProgram();
}
void Gfx_SetAlphaTest(cc_bool enabled) { gfx_alphaTest = enabled; SwitchProgram(); }
static void SetAlphaTest(cc_bool enabled) { SwitchProgram(); }
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
cc_bool enabled = !depthOnly;

View File

@ -237,7 +237,7 @@ void Gfx_DisableMipmaps(void) { }
*-----------------------------------------------------State management----------------------------------------------------*
*#########################################################################################################################*/
void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); }
void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); }
static void SetAlphaBlend(cc_bool enabled) { gl_Toggle(GL_BLEND); }
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
@ -377,7 +377,7 @@ void Gfx_SetFogEnd(float value) {
void Gfx_SetFogMode(FogFunc func) {
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
if (enabled) { glEnable(GL_ALPHA_TEST); } else { glDisable(GL_ALPHA_TEST); }
}

View File

@ -176,7 +176,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
glPolyFmt(POLY_ALPHA(31) | (enabled ? POLY_CULL_BACK : POLY_CULL_NONE));
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
/*if (enabled) {
glEnable(GL_BLEND);
} else {
@ -376,7 +376,7 @@ void Gfx_SetFogEnd(float value) {
void Gfx_SetFogMode(FogFunc func) {
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
if (enabled) {
//glEnable(GL_ALPHA_TEST);
} else {

View File

@ -36,6 +36,9 @@ static RenderBuffer buffers[2];
static cc_uint8* next_packet;
static int active_buffer;
static RenderBuffer* buffer;
static cc_bool rendering2D;
static void* lastPoly;
static cc_bool cullingEnabled;
static void OnBufferUpdated(void) {
buffer = &buffers[active_buffer];
@ -100,7 +103,7 @@ void Gfx_FreeState(void) {
void Gfx_Create(void) {
Gfx.MaxTexWidth = 128;
Gfx.MaxTexHeight = 128;
Gfx.MaxTexHeight = 256;
Gfx.Created = true;
Gfx_RestoreState();
@ -126,30 +129,41 @@ void Gfx_Free(void) {
// VRAM can be divided into texture pages
// 32 texture pages total - each page is 64 x 256
// 10 texture pages are occupied by the doublebuffered display
// 22 texture packs are usable, and are then divided into
// - 4 pages for 256 wide textures, 8 for 128 wide, 10 for 64
#define TPAGE_START_HOR 5
#define TPAGES_PER_HALF 16
// 22 texture pages are usable for textures
// These 22 pages are then divided into:
// - 5 for 128+ wide horizontal, 6 otherwise
// - 11 pages for vertical textures
#define TPAGE_WIDTH 64
#define TPAGE_HEIGHT 256
#define MAX_TEX_PAGES 22
static cc_uint8 vram_used[(MAX_TEX_PAGES * TPAGE_HEIGHT) / 8];
#define TPAGES_PER_HALF 16
// Horizontally oriented textures (first group of 16)
#define TPAGE_START_HOR 5
#define MAX_HOR_TEX_PAGES 11
#define MAX_HOR_TEX_LINES (MAX_HOR_TEX_PAGES * TPAGE_HEIGHT)
// Horizontally oriented textures (second group of 16)
#define TPAGE_START_VER (16 + 5)
#define MAX_VER_TEX_PAGES 11
#define MAX_VER_TEX_LINES (MAX_VER_TEX_PAGES * TPAGE_WIDTH)
static cc_uint8 vram_used[(MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES) / 8];
#define VRAM_SetUsed(line) (vram_used[(line) / 8] |= (1 << ((line) % 8)))
#define VRAM_UnUsed(line) (vram_used[(line) / 8] &= ~(1 << ((line) % 8)))
#define VRAM_IsUsed(line) (vram_used[(line) / 8] & (1 << ((line) % 8)))
static void VRAM_GetBlockRange(int width, int* beg, int* end) {
if (width >= 256) {
*beg = 0;
*end = 4 * TPAGE_HEIGHT;
#define VRAM_BoundingAxis(width, height) height > width ? width : height
static void VRAM_GetBlockRange(int width, int height, int* beg, int* end) {
if (height > width) {
*beg = MAX_HOR_TEX_LINES;
*end = MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES;
} else if (width >= 128) {
*beg = 4 * TPAGE_HEIGHT;
*end = 12 * TPAGE_HEIGHT;
*beg = 0;
*end = 5 * TPAGE_HEIGHT;
} else {
*beg = 12 * TPAGE_HEIGHT;
*end = 22 * TPAGE_HEIGHT;
*beg = 5 * TPAGE_HEIGHT;
*end = MAX_HOR_TEX_LINES;
}
}
@ -163,7 +177,7 @@ static cc_bool VRAM_IsRangeFree(int beg, int end) {
static int VRAM_FindFreeBlock(int width, int height) {
int beg, end;
VRAM_GetBlockRange(width, &beg, &end);
VRAM_GetBlockRange(width, height, &beg, &end);
// TODO kinda inefficient
for (int i = beg; i < end - height; i++)
@ -175,13 +189,41 @@ static int VRAM_FindFreeBlock(int width, int height) {
return -1;
}
static void VRAM_AllocBlock(int line, int width, int height) {
int lines = VRAM_BoundingAxis(width, height);
for (int i = line; i < line + lines; i++)
{
VRAM_SetUsed(i);
}
}
static void VRAM_FreeBlock(int line, int width, int height) {
int lines = VRAM_BoundingAxis(width, height);
for (int i = line; i < line + lines; i++)
{
VRAM_UnUsed(i);
}
}
static int VRAM_CalcPage(int line) {
if (line < MAX_HOR_TEX_LINES) {
return TPAGE_START_HOR + (line / TPAGE_HEIGHT);
} else {
line -= MAX_HOR_TEX_LINES;
return TPAGE_START_VER + (line / TPAGE_WIDTH);
}
}
#define TEXTURES_MAX_COUNT 64
typedef struct GPUTexture {
cc_uint16 width, height;
cc_uint8 width_mask, height_mask;
cc_uint16 line, tpage;
cc_uint8 xOffset, yOffset;
} GPUTexture;
static GPUTexture textures[TEXTURES_MAX_COUNT];
static GPUTexture* active_tex;
static GPUTexture* curTex;
#define BGRA8_to_PS1(src) \
((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | ((src[3] & 0x80) << 8)
@ -205,28 +247,30 @@ static void* AllocTextureAt(int i, struct Bitmap* bmp, int rowWidth) {
int line = VRAM_FindFreeBlock(bmp->width, bmp->height);
if (line == -1) { Mem_Free(tmp); return NULL; }
tex->width = bmp->width;
tex->height = bmp->height;
tex->width = bmp->width; tex->width_mask = bmp->width - 1;
tex->height = bmp->height; tex->height_mask = bmp->height - 1;
tex->line = line;
int page = TPAGE_START_HOR + (line / TPAGE_HEIGHT);
// In bottom half of VRAM? Need to offset horizontally again
if (page >= TPAGES_PER_HALF) page += TPAGE_START_HOR;
int page = VRAM_CalcPage(line);
int pageX = (page % TPAGES_PER_HALF);
int pageY = (page / TPAGES_PER_HALF);
for (int i = tex->line; i < tex->line + tex->height; i++)
{
VRAM_SetUsed(i);
}
tex->tpage = (2 << 7) | (pageY << 4) | pageX;
VRAM_AllocBlock(line, bmp->width, bmp->height);
if (bmp->height > bmp->width) {
tex->xOffset = line % TPAGE_WIDTH;
tex->yOffset = 0;
} else {
tex->xOffset = 0;
tex->yOffset = line % TPAGE_HEIGHT;
}
Platform_Log3("%i x %i = %i", &bmp->width, &bmp->height, &line);
Platform_Log3(" at %i (%i, %i)", &page, &pageX, &pageY);
RECT rect;
rect.x = pageX * TPAGE_WIDTH;
rect.y = pageY * TPAGE_HEIGHT + (line % TPAGE_HEIGHT);
rect.x = pageX * TPAGE_WIDTH + tex->xOffset;
rect.y = pageY * TPAGE_HEIGHT + tex->yOffset;
rect.w = bmp->width;
rect.h = bmp->height;
@ -251,7 +295,7 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8
void Gfx_BindTexture(GfxResourceID texId) {
if (!texId) texId = white_square;
active_tex = (GPUTexture*)texId;
curTex = (GPUTexture*)texId;
}
void Gfx_DeleteTexture(GfxResourceID* texId) {
@ -259,10 +303,7 @@ void Gfx_DeleteTexture(GfxResourceID* texId) {
if (!data) return;
GPUTexture* tex = (GPUTexture*)data;
for (int i = tex->line; i < tex->line + tex->height; i++)
{
VRAM_UnUsed(i);
}
VRAM_FreeBlock(tex->line, tex->width, tex->height);
tex->width = 0; tex->height = 0;
*texId = NULL;
}
@ -285,13 +326,13 @@ void Gfx_SetFogEnd(float value) { }
void Gfx_SetFogMode(FogFunc func) { }
void Gfx_SetFaceCulling(cc_bool enabled) {
// TODO
cullingEnabled = enabled;
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
}
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
@ -530,8 +571,77 @@ static void Transform(Vec3* result, struct VertexTextured* a, const struct Matri
}
cc_bool VERTEX_LOGGING;
static void DrawColouredQuads(int verticesCount, int startVertex) {
static void DrawColouredQuads2D(int verticesCount, int startVertex) {
return;
for (int i = 0; i < verticesCount; i += 4)
{
struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i;
POLY_F4* poly = new_primitive(sizeof(POLY_F4));
setPolyF4(poly);
poly->x0 = v[1].x; poly->y0 = v[1].y;
poly->x1 = v[0].x; poly->y1 = v[0].y;
poly->x2 = v[2].x; poly->y2 = v[2].y;
poly->x3 = v[3].x; poly->y3 = v[3].y;
poly->r0 = PackedCol_R(v->Col);
poly->g0 = PackedCol_G(v->Col);
poly->b0 = PackedCol_B(v->Col);
if (lastPoly) {
setaddr(poly, getaddr(lastPoly)); setaddr(lastPoly, poly);
} else {
addPrim(&buffer->ot[0], poly);
}
lastPoly = poly;
}
}
static void DrawTexturedQuads2D(int verticesCount, int startVertex) {
int uOffset = curTex->xOffset, vOffset = curTex->yOffset;
for (int i = 0; i < verticesCount; i += 4)
{
struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i;
POLY_FT4* poly = new_primitive(sizeof(POLY_FT4));
setPolyFT4(poly);
poly->tpage = curTex->tpage;
poly->clut = 0;
// TODO & instead of %
poly->x0 = v[1].x; poly->y0 = v[1].y;
poly->x1 = v[0].x; poly->y1 = v[0].y;
poly->x2 = v[2].x; poly->y2 = v[2].y;
poly->x3 = v[3].x; poly->y3 = v[3].y;
poly->u0 = ((int)(v[1].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset;
poly->v0 = ((int)(v[1].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u1 = ((int)(v[0].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset;
poly->v1 = ((int)(v[0].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u2 = ((int)(v[2].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset;
poly->v2 = ((int)(v[2].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u3 = ((int)(v[3].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset;
poly->v3 = ((int)(v[3].V * curTex->height) & curTex->height_mask) + vOffset;
// https://problemkaputt.de/psxspx-gpu-rendering-attributes.htm
// "For untextured graphics, 8bit RGB values of FFh are brightest. However, for texture blending, 8bit values of 80h are brightest"
poly->r0 = PackedCol_R(v->Col) >> 1;
poly->g0 = PackedCol_G(v->Col) >> 1;
poly->b0 = PackedCol_B(v->Col) >> 1;
if (lastPoly) {
setaddr(poly, getaddr(lastPoly)); setaddr(lastPoly, poly);
} else {
addPrim(&buffer->ot[0], poly);
}
lastPoly = poly;
}
}
static void DrawColouredQuads3D(int verticesCount, int startVertex) {
for (int i = 0; i < verticesCount; i += 4)
{
struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i;
@ -567,8 +677,8 @@ static void DrawColouredQuads(int verticesCount, int startVertex) {
}
}
static void DrawTexturedQuads(int verticesCount, int startVertex) {
int pageOffset = active_tex->line % TPAGE_HEIGHT;
static void DrawTexturedQuads3D(int verticesCount, int startVertex) {
int uOffset = curTex->xOffset, vOffset = curTex->yOffset;
for (int i = 0; i < verticesCount; i += 4)
{
@ -576,7 +686,7 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) {
POLY_FT4* poly = new_primitive(sizeof(POLY_FT4));
setPolyFT4(poly);
poly->tpage = active_tex->tpage;
poly->tpage = curTex->tpage;
poly->clut = 0;
Vec3 coords[4];
@ -586,12 +696,28 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) {
Transform(&coords[3], &v[3], &mvp);
// TODO & instead of %
poly->x0 = coords[1].x; poly->y0 = coords[1].y; poly->u0 = (int)(v[1].U * active_tex->width) % active_tex->width; poly->v0 = ((int)(v[1].V * active_tex->height) % active_tex->height) + pageOffset;
poly->x1 = coords[0].x; poly->y1 = coords[0].y; poly->u1 = (int)(v[0].U * active_tex->width) % active_tex->width; poly->v1 = ((int)(v[0].V * active_tex->height) % active_tex->height) + pageOffset;
poly->x2 = coords[2].x; poly->y2 = coords[2].y; poly->u2 = (int)(v[2].U * active_tex->width) % active_tex->width; poly->v2 = ((int)(v[2].V * active_tex->height) % active_tex->height) + pageOffset;
poly->x3 = coords[3].x; poly->y3 = coords[3].y; poly->u3 = (int)(v[3].U * active_tex->width) % active_tex->width; poly->v3 = ((int)(v[3].V * active_tex->height) % active_tex->height) + pageOffset;
poly->x0 = coords[1].x; poly->y0 = coords[1].y;
poly->x1 = coords[0].x; poly->y1 = coords[0].y;
poly->x2 = coords[2].x; poly->y2 = coords[2].y;
poly->x3 = coords[3].x; poly->y3 = coords[3].y;
//int P = active_tex->height, page = poly->tpage & 0xFF, ll = active_tex->line % TPAGE_HEIGHT;
if (cullingEnabled) {
// https://gamedev.stackexchange.com/questions/203694/how-to-make-backface-culling-work-correctly-in-both-orthographic-and-perspective
int signA = (poly->x0 - poly->x1) * (poly->y2 - poly->y1);
int signB = (poly->x2 - poly->x1) * (poly->y0 - poly->y1);
if (signA > signB) continue;
}
poly->u0 = ((int)(v[1].U * curTex->width) & curTex->width_mask) + uOffset;
poly->v0 = ((int)(v[1].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u1 = ((int)(v[0].U * curTex->width) & curTex->width_mask) + uOffset;
poly->v1 = ((int)(v[0].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u2 = ((int)(v[2].U * curTex->width) & curTex->width_mask) + uOffset;
poly->v2 = ((int)(v[2].V * curTex->height) & curTex->height_mask) + vOffset;
poly->u3 = ((int)(v[3].U * curTex->width) & curTex->width_mask) + uOffset;
poly->v3 = ((int)(v[3].V * curTex->height) & curTex->height_mask) + vOffset;
//int P = curTex->height, page = poly->tpage & 0xFF, ll = curTex->yOffset;
//Platform_Log4("XYZ: %f3 x %i, %i, %i", &v[0].V, &P, &page, &ll);
int p = (coords[0].z + coords[1].z + coords[2].z + coords[3].z) / 4;
if (p < 0 || p >= OT_LENGTH) continue;
@ -600,9 +726,9 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) {
//if (VERTEX_LOGGING) Platform_Log3("IN: %i, %i, %i", &X, &Y, &Z);
X = poly->x1; Y = poly->y1, Z = coords[0].z;
poly->r0 = PackedCol_R(v->Col);
poly->g0 = PackedCol_G(v->Col);
poly->b0 = PackedCol_B(v->Col);
poly->r0 = PackedCol_R(v->Col) >> 1;
poly->g0 = PackedCol_G(v->Col) >> 1;
poly->b0 = PackedCol_B(v->Col) >> 1;
//if (VERTEX_LOGGING) Platform_Log4("OUT: %i, %i, %i (%i)", &X, &Y, &Z, &p);
// TODO: 2D shouldn't use AddPrim, draws in the wrong way
@ -678,24 +804,29 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) {
}
}*/
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
if (gfx_format == VERTEX_FORMAT_TEXTURED) {
DrawTexturedQuads(verticesCount, startVertex);
static void DrawQuads(int verticesCount, int startVertex) {
if (rendering2D && gfx_format == VERTEX_FORMAT_TEXTURED) {
DrawTexturedQuads2D(verticesCount, startVertex);
} else if (rendering2D) {
DrawColouredQuads2D(verticesCount, startVertex);
} else if (gfx_format == VERTEX_FORMAT_TEXTURED) {
DrawTexturedQuads3D(verticesCount, startVertex);
} else {
DrawColouredQuads(verticesCount, startVertex);
DrawColouredQuads3D(verticesCount, startVertex);
}
}
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
DrawQuads(verticesCount, startVertex);
}
void Gfx_DrawVb_IndexedTris(int verticesCount) {
if (gfx_format == VERTEX_FORMAT_TEXTURED) {
DrawTexturedQuads(verticesCount, 0);
} else {
DrawColouredQuads(verticesCount, 0);
}
DrawQuads(verticesCount, 0);
}
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
DrawTexturedQuads(verticesCount, startVertex);
DrawTexturedQuads3D(verticesCount, startVertex);
}
@ -711,6 +842,7 @@ cc_bool Gfx_WarnIfNecessary(void) {
}
void Gfx_BeginFrame(void) {
lastPoly = NULL;
}
void Gfx_EndFrame(void) {
@ -735,4 +867,14 @@ void Gfx_GetApiInfo(cc_string* info) {
}
cc_bool Gfx_TryRestoreContext(void) { return true; }
void Gfx_Begin2D(int width, int height) {
rendering2D = true;
Gfx_SetAlphaBlending(true);
}
void Gfx_End2D(void) {
rendering2D = false;
Gfx_SetAlphaBlending(false);
}
#endif

View File

@ -243,8 +243,6 @@ void Gfx_DisableMipmaps(void) { }
*------------------------------------------------------State management---------------------------------------------------*
*#########################################################################################################################*/
static int clearR, clearG, clearB;
static cc_bool gfx_alphaBlend;
static cc_bool gfx_alphaTest;
static cc_bool gfx_depthTest;
static cc_bool stateDirty;
@ -274,13 +272,11 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
gfx_alphaTest = enabled;
static void SetAlphaTest(cc_bool enabled) {
stateDirty = true;
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
gfx_alphaBlend = enabled;
static void SetAlphaBlend(cc_bool enabled) {
// TODO update primitive state
}

View File

@ -286,7 +286,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
rsxSetCullFaceEnable(context, enabled);
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
rsxSetBlendEnable(context, enabled);
}
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
@ -316,7 +316,7 @@ void Gfx_SetDepthTest(cc_bool enabled) {
UpdateDepthState();
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
rsxSetAlphaTestEnable(context, enabled);
}

View File

@ -163,7 +163,7 @@ void Gfx_BindTexture(GfxResourceID texId) {
*#########################################################################################################################*/
static PackedCol gfx_clearColor;
void Gfx_SetFaceCulling(cc_bool enabled) { GU_Toggle(GU_CULL_FACE); }
void Gfx_SetAlphaBlending(cc_bool enabled) { GU_Toggle(GU_BLEND); }
static void SetAlphaBlend(cc_bool enabled) { GU_Toggle(GU_BLEND); }
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
void Gfx_ClearColor(PackedCol color) {
@ -377,7 +377,7 @@ void Gfx_SetFogMode(FogFunc func) {
/* TODO: Implemen fake exp/exp2 fog */
}
void Gfx_SetAlphaTest(cc_bool enabled) { GU_Toggle(GU_ALPHA_TEST); }
static void SetAlphaTest(cc_bool enabled) { GU_Toggle(GU_ALPHA_TEST); }
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
cc_bool enabled = !depthOnly;

View File

@ -8,7 +8,6 @@
// TODO track last frame used on
static cc_bool gfx_depthOnly;
static cc_bool gfx_alphaTesting, gfx_alphaBlending;
static int frontBufferIndex, backBufferIndex;
// Inspired from
// https://github.com/xerpi/gxmfun/blob/master/source/main.c
@ -242,11 +241,11 @@ static void FP_SwitchActive(void) {
// [normal rendering, blend rendering, no rendering]
if (gfx_depthOnly) {
index += 2;
} else if (gfx_alphaBlending) {
} else if (gfx_alphaBlend) {
index += 1;
}
if (gfx_alphaTesting) index += 2 * 3;
if (gfx_alphaTest) index += 2 * 3;
FragmentProgram* FP = &FP_list[index];
if (FP == FP_Active) return;
@ -964,13 +963,11 @@ void Gfx_SetFogMode(FogFunc func) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
gfx_alphaTesting = enabled;
static void SetAlphaTest(cc_bool enabled) {
FP_SwitchActive();
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
gfx_alphaBlending = enabled;
static void SetAlphaBlend(cc_bool enabled) {
FP_SwitchActive();
}

View File

@ -143,10 +143,10 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
}
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }

View File

@ -10,9 +10,6 @@ static struct Bitmap fb_bmp;
static float vp_hwidth, vp_hheight;
static int sc_maxX, sc_maxY;
static cc_bool alphaBlending;
static cc_bool alphaTest;
static PackedCol* colorBuffer;
static PackedCol clearColor;
static cc_bool colWrite = true;
@ -115,12 +112,12 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
faceCulling = enabled;
}
void Gfx_SetAlphaTest(cc_bool enabled) {
alphaTest = enabled;
static void SetAlphaTest(cc_bool enabled) {
/* Uses value from Gfx_SetAlphaTest */
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
alphaBlending = enabled;
static void SetAlphaBlend(cc_bool enabled) {
/* Uses value from Gfx_SetAlphaBlending */
}
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
@ -391,7 +388,7 @@ static void DrawTriangle(Vector4 frag1, Vector4 frag2, Vector4 frag3,
int B = PackedCol_B(fragColor);
int A = PackedCol_A(fragColor);
if (alphaBlending) {
if (gfx_alphaBlend) {
PackedCol dst = colorBuffer[index];
int dstR = BitmapCol_R(dst);
int dstG = BitmapCol_G(dst);
@ -401,7 +398,7 @@ static void DrawTriangle(Vector4 frag1, Vector4 frag2, Vector4 frag3,
G = (G * A) / 255 + (dstG * (255 - A)) / 255;
B = (B * A) / 255 + (dstB * (255 - A)) / 255;
}
if (alphaTest && A < 0x80) continue;
if (gfx_alphaTest && A < 0x80) continue;
if (depthWrite) depthBuffer[index] = z;
colorBuffer[index] = BitmapCol_Make(R, G, B, 0xFF);

View File

@ -31,7 +31,6 @@ static GfxResourceID white_square;
static WHBGfxShaderGroup* group;
static void InitGfx(void) {
WHBGfxInit();
GX2InitSampler(&sampler, GX2_TEX_CLAMP_MODE_WRAP, GX2_TEX_XY_FILTER_MODE_POINT);
WHBGfxLoadGFDShaderGroup(&colorShader, 0, coloured_gsh);
@ -86,7 +85,9 @@ static void Gfx_RestoreState(void) {
static GX2Texture* pendingTex;
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
GX2Texture* tex = Mem_AllocCleared(1, sizeof(GX2Texture), "GX2 texture");
GX2Texture* tex = Mem_TryAllocCleared(1, sizeof(GX2Texture));
if (!tex) return NULL;
// TODO handle out of memory better
int width = bmp->width, height = bmp->height;
tex->surface.width = width;
@ -99,8 +100,9 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8
tex->compMap = GX2_COMP_MAP(GX2_SQ_SEL_R, GX2_SQ_SEL_G, GX2_SQ_SEL_B, GX2_SQ_SEL_A);
GX2CalcSurfaceSizeAndAlignment(&tex->surface);
GX2InitTextureRegs(tex);
tex->surface.image = MEMAllocFromDefaultHeapEx(tex->surface.imageSize, tex->surface.alignment);
// TODO check result
if (!tex->surface.image) { Mem_Free(tex); return NULL; }
CopyTextureData(tex->surface.image, tex->surface.pitch << 2, bmp, rowWidth << 2);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, tex->surface.image, tex->surface.imageSize);
@ -175,11 +177,11 @@ void Gfx_SetFogMode(FogFunc func) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
GX2SetAlphaTest(enabled, GX2_COMPARE_FUNC_GEQUAL, 0.5f);
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
GX2SetBlendControl(GX2_RENDER_TARGET_0,
GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD,
true,
@ -431,12 +433,18 @@ void Gfx_ClearBuffers(GfxBuffers buffers) {
}
}
static int drc_ticks;
void Gfx_EndFrame(void) {
GX2ColorBuffer* buf;
buf = WHBGfxGetTVColourBuffer();
GX2CopyColorBufferToScanBuffer(buf, GX2_SCAN_TARGET_TV);
GX2ContextState* state = WHBGfxGetDRCContextState();
GX2SetContextState(state);
drc_ticks = (drc_ticks + 1) % 200;
buf = WHBGfxGetDRCColourBuffer();
GX2ClearColor(buf, drc_ticks / 200.0f, drc_ticks / 200.0f, drc_ticks / 200.0f, 1.0f);
GX2CopyColorBufferToScanBuffer(buf, GX2_SCAN_TARGET_DRC);
GX2SwapScanBuffers();
@ -459,7 +467,10 @@ void Gfx_OnWindowResize(void) {
}
void Gfx_SetViewport(int x, int y, int w, int h) { }
void Gfx_SetViewport(int x, int y, int w, int h) {
GX2SetViewport(x, y, w, h, 0.0f, 1.0f);
GX2SetScissor( x, y, w, h);
}
void Gfx_3DS_SetRenderScreen1(enum Screen3DS screen) {
GX2ContextState* tv_state = WHBGfxGetTVContextState();

View File

@ -299,13 +299,13 @@ void Gfx_SetFaceCulling(cc_bool enabled) {
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
uint32_t* p = pb_begin();
p = pb_push1(p, NV097_SET_BLEND_ENABLE, enabled);
pb_end(p);
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
uint32_t* p = pb_begin();
p = pb_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled);
pb_end(p);
@ -396,7 +396,6 @@ void Gfx_EndFrame(void) {
*----------------------------------------------------------Buffers--------------------------------------------------------*
*#########################################################################################################################*/
static cc_uint8* gfx_vertices;
static cc_uint16* gfx_indices;
static void* AllocBuffer(int count, int elemSize) {
return MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 16, PAGE_WRITECOMBINE | PAGE_READWRITE);
@ -410,16 +409,12 @@ static void FreeBuffer(GfxResourceID* buffer) {
GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) {
void* ib = AllocBuffer(count, sizeof(cc_uint16));
if (!ib) Logger_Abort("Failed to allocate memory for index buffer");
fillFunc(ib, count, obj);
return ib;
return (void*)1;
}
void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; }
void Gfx_BindIb(GfxResourceID ib) { }
void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); }
void Gfx_DeleteIb(GfxResourceID* ib) { }
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
@ -476,6 +471,18 @@ 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));
pb_end(p);
}
void Gfx_SetFogDensity(float value) {
@ -536,8 +543,8 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f
void Gfx_OnWindowResize(void) { }
static struct Vec4 vp_offset = { 320, -240, 8388608, 1 };
static struct Vec4 vp_scale = { 320, 240, 8388608, 1 };
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) {
@ -655,10 +662,10 @@ 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
// NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so must be <= 256
while (count > 0)
{
int batch_count = min(count, 64); // TODO increase?
int batch_count = min(count, 256);
p = pb_push1(p, 0x40000000 | NV097_DRAW_ARRAYS,
MASK(NV097_DRAW_ARRAYS_COUNT, (batch_count-1)) |
@ -676,9 +683,7 @@ void Gfx_DrawVb_Lines(int verticesCount) {
DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount);
}
#define MAX_BATCH 120
static void DrawIndexedVertices(int verticesCount, int startVertex) {
// TODO switch to indexed rendering
DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount);
}

View File

@ -82,7 +82,7 @@ static void Gfx_FreeState(void) {
static void Gfx_RestoreState(void) {
InitDefaultResources();
Gfx_SetFaceCulling(false);
Gfx_SetAlphaBlending(false);
SetAlphaBlend(false);
Xe_SetAlphaFunc(xe, XE_CMP_GREATER);
Xe_SetAlphaRef(xe, 0.5f);
@ -155,11 +155,11 @@ void Gfx_SetFogMode(FogFunc func) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
static void SetAlphaTest(cc_bool enabled) {
Xe_SetAlphaTestEnable(xe, enabled);
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
static void SetAlphaBlend(cc_bool enabled) {
if (enabled) {
Xe_SetBlendControl(xe,
XE_BLEND_SRCALPHA, XE_BLENDOP_ADD, XE_BLEND_INVSRCALPHA,

View File

@ -249,7 +249,6 @@ void Gui_Remove(struct Screen* s) {
void Gui_Add(struct Screen* s, int priority) {
struct Screen* existing;
int i;
Gui_RemoveCore(s);
existing = Gui_GetScreen(priority);

View File

@ -45,7 +45,7 @@ CC_VAR extern struct _GuiData {
float RawHotbarScale, RawChatScale, RawInventoryScale, RawCrosshairScale;
GfxResourceID GuiTex, GuiClassicTex, IconsTex, TouchTex;
int DefaultLines;
int __unused;
int _unused;
float RawTouchScale;
/* The highest priority screen that has grabbed input. */
struct Screen* InputGrab;

View File

@ -43,7 +43,6 @@ static void HeldBlockRenderer_RenderModel(void) {
SetHeldModel(model);
Vec3_Set(held_entity.ModelScale, 1.0f,1.0f,1.0f);
Gfx_SetAlphaTest(true);
Model_RenderArm(model, &held_entity);
Gfx_SetAlphaTest(false);
} else {

View File

@ -41,6 +41,14 @@ static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) {
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");
@ -58,11 +66,11 @@ static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) {
if (String_CaselessEqualsConst(&name, "ETag")) {
String_CopyToRawArray(req->etag, &value);
} else if (String_CaselessEqualsConst(&name, "Content-Length")) {
Convert_ParseInt(&value, &req->contentLength);
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 */
Convert_ParseInt(&value, &req->contentLength);
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")) {
@ -496,13 +504,15 @@ static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct H
static cc_result HttpConnection_Read(struct HttpConnection* conn, cc_uint8* data, cc_uint32 count, cc_uint32* read) {
if (conn->sslCtx)
return SSL_Read(conn->sslCtx, data, count, read);
return Socket_Read(conn->socket, data, count, read);
}
static cc_result HttpConnection_Write(struct HttpConnection* conn, const cc_uint8* data, cc_uint32 count, cc_uint32* wrote) {
static cc_result HttpConnection_Write(struct HttpConnection* conn, const cc_uint8* data, cc_uint32 count) {
if (conn->sslCtx)
return SSL_Write(conn->sslCtx, data, count, wrote);
return Socket_Write(conn->socket, data, count, wrote);
return SSL_WriteAll(conn->sslCtx, data, count);
return Socket_WriteAll(conn->socket, data, count);
}
@ -556,6 +566,7 @@ static cc_result ConnectionPool_Open(struct HttpConnection** conn, const struct
*--------------------------------------------------------HttpClient-------------------------------------------------------*
*#########################################################################################################################*/
enum HTTP_RESPONSE_STATE {
HTTP_RESPONSE_STATE_INITIAL,
HTTP_RESPONSE_STATE_HEADER,
HTTP_RESPONSE_STATE_DATA,
HTTP_RESPONSE_STATE_CHUNK_HEADER,
@ -581,7 +592,7 @@ struct HttpClientState {
};
static void HttpClientState_Reset(struct HttpClientState* state) {
state->state = HTTP_RESPONSE_STATE_HEADER;
state->state = HTTP_RESPONSE_STATE_INITIAL;
state->chunked = 0;
state->dataLeft = 0;
state->autoClose = false;
@ -621,15 +632,13 @@ static void HttpClient_Serialise(struct HttpClientState* state) {
static cc_result HttpClient_SendRequest(struct HttpClientState* state) {
char inputBuffer[16384];
cc_string inputMsg;
cc_uint32 wrote;
String_InitArray(inputMsg, inputBuffer);
state->req->meta = &inputMsg;
state->req->progress = HTTP_PROGRESS_FETCHING_DATA;
HttpClient_Serialise(state);
/* TODO check that wrote is >= inputMsg.length */
return HttpConnection_Write(state->conn, (cc_uint8*)inputBuffer, inputMsg.length, &wrote);
return HttpConnection_Write(state->conn, (cc_uint8*)inputBuffer, inputMsg.length);
}
@ -705,6 +714,9 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
while (offset < total) {
switch (state->state) {
case HTTP_RESPONSE_STATE_INITIAL:
state->state = HTTP_RESPONSE_STATE_HEADER;
break;
case HTTP_RESPONSE_STATE_HEADER:
{
@ -833,9 +845,12 @@ static cc_result HttpClient_ParseResponse(struct HttpClientState* state) {
{
dst = state->dataLeft > INPUT_BUFFER_LEN ? (req->data + req->size) : buffer;
res = HttpConnection_Read(state->conn, dst, INPUT_BUFFER_LEN, &total);
if (res) return res;
if (total == 0) return ERR_END_OF_STREAM;
if (total == 0) {
Platform_Log1("Http read unexpectedly returned 0 in state %i", &state->state);
return state->state == HTTP_RESPONSE_STATE_INITIAL ? HTTP_ERR_NO_RESPONSE : ERR_END_OF_STREAM;
}
if (dst != buffer) {
/* When there is more than INPUT_BUFFER_LEN bytes of unread data/content, */
@ -912,6 +927,11 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) {
res = HttpBackend_PerformRequest(&state);
retried = true;
}
if (res == HTTP_ERR_NO_RESPONSE && !retried) {
Platform_LogConst("Resetting connection due to empty response..");
res = HttpBackend_PerformRequest(&state);
retried = true;
}
if (res || !HttpClient_IsRedirect(req)) break;
if (redirects >= 20) return HTTP_ERR_REDIRECTS;
@ -1278,7 +1298,7 @@ static void PerformRequest(struct HttpRequest* req, cc_string* url) {
end = Stopwatch_Measure();
elapsed = Stopwatch_ElapsedMS(beg, end);
Platform_Log4("HTTP: result %i (http %i) in %i ms (%i bytes)",
Platform_Log4("HTTP: result %e (http %i) in %i ms (%i bytes)",
&req->result, &req->statusCode, &elapsed, &req->size);
Http_FinishRequest(req);

View File

@ -216,7 +216,8 @@ static const char* const storageNames[INPUT_COUNT] = {
"Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9",
"KeypadDivide", "KeypadMultiply", "KeypadSubtract",
"KeypadAdd", "KeypadDecimal", "KeypadEnter",
"XButton1", "XButton2", "LeftMouse", "RightMouse", "MiddleMouse",
"XButton1", "XButton2", "XButton3", "XButton4", "XButton5", "XButton6",
"LeftMouse", "RightMouse", "MiddleMouse",
Pad_Names
};
@ -239,7 +240,8 @@ const char* const Input_DisplayNames[INPUT_COUNT] = {
"NUMPAD5", "NUMPAD6", "NUMPAD7", "NUMPAD8", "NUMPAD9",
"DIVIDE", "MULTIPLY", "SUBTRACT",
"ADD", "DECIMAL", "NUMPADENTER",
"XBUTTON1", "XBUTTON2", "LMOUSE", "RMOUSE", "MMOUSE",
"XBUTTON1", "XBUTTON2", "XBUTTON3", "XBUTTON4", "XBUTTON5", "XBUTTON6",
"LMOUSE", "RMOUSE", "MMOUSE",
Pad_Names
};
@ -291,6 +293,15 @@ void Input_Clear(void) {
ClearTouches();
}
int Input_CalcDelta(int key, int horDelta, int verDelta) {
if (Input_IsLeftButton(key) || key == CCKEY_KP4) return -horDelta;
if (Input_IsRightButton(key) || key == CCKEY_KP6) return +horDelta;
if (Input_IsUpButton(key) || key == CCKEY_KP8) return -verDelta;
if (Input_IsDownButton(key) || key == CCKEY_KP2) return +verDelta;
return 0;
}
/*########################################################################################################################*
*----------------------------------------------------------Mouse----------------------------------------------------------*
@ -418,38 +429,49 @@ static void KeyBind_Init(void) {
*---------------------------------------------------------Gamepad---------------------------------------------------------*
*#########################################################################################################################*/
#define GAMEPAD_BEG_BTN CCPAD_A
#define GAMEPAD_BTN_COUNT (INPUT_COUNT - GAMEPAD_BEG_BTN)
int Gamepad_AxisBehaviour[2] = { AXIS_BEHAVIOUR_MOVEMENT, AXIS_BEHAVIOUR_CAMERA };
int Gamepad_AxisSensitivity[2] = { AXIS_SENSI_NORMAL, AXIS_SENSI_NORMAL };
static const float axis_sensiFactor[] = { 0.25f, 0.5f, 1.0f, 2.0f, 4.0f };
struct GamepadState {
float axisX[2], axisY[2];
/*cc_bool pressed[INPUT_COUNT - GAMEPAD_BEG_BTN];*/
float holdtime[INPUT_COUNT - GAMEPAD_BEG_BTN];
cc_bool pressed[GAMEPAD_BTN_COUNT];
float holdtime[GAMEPAD_BTN_COUNT];
};
static struct GamepadState gamepads[INPUT_MAX_GAMEPADS];
static void Gamepad_Update(struct GamepadState* pad, float delta) {
int btn;
for (btn = GAMEPAD_BEG_BTN; btn < INPUT_COUNT; btn++)
for (btn = 0; btn < GAMEPAD_BTN_COUNT; btn++)
{
if (!Input.Pressed[btn]) continue;
pad->holdtime[btn - GAMEPAD_BEG_BTN] += delta;
if (pad->holdtime[btn - GAMEPAD_BEG_BTN] < 1.0f) continue;
if (!pad->pressed[btn]) continue;
pad->holdtime[btn] += delta;
if (pad->holdtime[btn] < 1.0f) continue;
/* Held for over a second, trigger a fake press */
pad->holdtime[btn - GAMEPAD_BEG_BTN] = 0;
Input_SetPressed(btn);
pad->holdtime[btn] = 0;
Input_SetPressed(btn + GAMEPAD_BEG_BTN);
}
}
void Gamepad_SetButton(int port, int btn, int pressed) {
struct GamepadState* pad = &gamepads[port];
/* Reset hold tracking time */
if (pressed && !Input.Pressed[btn]) pad->holdtime[btn - GAMEPAD_BEG_BTN] = 0;
int i;
btn -= GAMEPAD_BEG_BTN;
Input_SetNonRepeatable(btn, pressed);
/* Reset hold tracking time */
if (pressed && !pad->pressed[btn]) pad->holdtime[btn] = 0;
pad->pressed[btn] = pressed != 0;;
/* Set pressed if button pressed on any gamepad, to avoid constant flip flopping */
/* between pressed and non-pressed when multiple controllers are plugged in */
for (i = 0; i < INPUT_MAX_GAMEPADS; i++)
pressed |= gamepads[i].pressed[btn];
Input_SetNonRepeatable(btn + GAMEPAD_BEG_BTN, pressed);
}
void Gamepad_SetAxis(int port, int axis, float x, float y, float delta) {
@ -480,7 +502,7 @@ static void PlayerInputPad(int port, int axis, struct LocalPlayer* p, float* xMo
y = gamepads[port].axisY[axis];
if (x != 0 || y != 0) {
angle = Math_Atan2(x, y);
angle = Math_Atan2f(x, y);
*xMoving = Math_CosF(angle);
*zMoving = Math_SinF(angle);
}

View File

@ -43,7 +43,8 @@ enum InputButtons {
CCKEY_KP_PLUS, CCKEY_KP_DECIMAL, CCKEY_KP_ENTER,
/* NOTE: RMOUSE must be before MMOUSE for PlayerClick compatibility */
CCMOUSE_X1, CCMOUSE_X2, CCMOUSE_L, CCMOUSE_R, CCMOUSE_M,
CCMOUSE_X1, CCMOUSE_X2, CCMOUSE_X3, CCMOUSE_X4, CCMOUSE_X5, CCMOUSE_X6,
CCMOUSE_L, CCMOUSE_R, CCMOUSE_M,
CCPAD_A, CCPAD_B, CCPAD_X, CCPAD_Y, CCPAD_L, CCPAD_R, CCPAD_Z,
CCPAD_LEFT, CCPAD_RIGHT, CCPAD_UP, CCPAD_DOWN,
@ -106,6 +107,7 @@ void Input_Clear(void);
#else
#define Input_IsActionPressed() Input_IsCtrlPressed()
#endif
int Input_CalcDelta(int btn, int horDelta, int verDelta);
#ifdef CC_BUILD_TOUCH

View File

@ -334,6 +334,7 @@ static void OnPointerDown(void* obj, int idx) {
struct LScreen* s = Launcher_Active;
struct LWidget* over;
struct LWidget* prev;
if (Window_Main.SoftKeyboardFocus) return;
if (!s) return;
over = GetWidgetAt(s, idx);
@ -347,6 +348,7 @@ static void OnPointerUp(void* obj, int idx) {
struct LScreen* s = Launcher_Active;
struct LWidget* over;
struct LWidget* prev;
if (Window_Main.SoftKeyboardFocus) return;
if (!s) return;
over = GetWidgetAt(s, idx);
@ -367,6 +369,7 @@ static void OnPointerMove(void* obj, int idx) {
struct LWidget* over;
struct LWidget* prev;
cc_bool overSame;
if (Window_Main.SoftKeyboardFocus) return;
if (!s) return;
over = GetWidgetAt(s, idx);

View File

@ -380,14 +380,9 @@ static void ColoursScreen_MouseWheel(struct LScreen* s_, float delta) {
}
static void ColoursScreen_KeyDown(struct LScreen* s, int key, cc_bool was) {
if (Input_IsLeftButton(key)) {
ColoursScreen_AdjustSelected(s, -1);
} else if (Input_IsRightButton(key)) {
ColoursScreen_AdjustSelected(s, +1);
} else if (Input_IsUpButton(key)) {
ColoursScreen_AdjustSelected(s, +10);
} else if (Input_IsDownButton(key)) {
ColoursScreen_AdjustSelected(s, -10);
int delta = Input_CalcDelta(key, 1, 10);
if (delta) {
ColoursScreen_AdjustSelected(s, delta);
} else {
LScreen_KeyDown(s, key, was);
}
@ -886,6 +881,12 @@ static void MainScreen_ApplyUpdateLabel(struct MainScreen* s) {
}
}
#ifdef CC_BUILD_CONSOLE
static void MainScreen_ExitApp(void* w) {
Window_Main.Exists = false;
}
#endif
static void MainScreen_Activated(struct LScreen* s_) {
struct MainScreen* s = (struct MainScreen*)s_;
@ -909,8 +910,6 @@ static void MainScreen_Activated(struct LScreen* s_) {
SwitchToSplitScreen, main_btnSplit);
#endif
LLabel_Add(s, &s->lblUpdate, "&eChecking..",
Updater_Supported ? main_lblUpdate_N : main_lblUpdate_H);
if (Process_OpenSupported) {
LButton_Add(s, &s->btnRegister, 100, 35, "Register",
MainScreen_Register, main_btnRegister);
@ -918,10 +917,19 @@ static void MainScreen_Activated(struct LScreen* s_) {
LButton_Add(s, &s->btnOptions, 100, 35, "Options",
SwitchToSettings, main_btnOptions);
#ifdef CC_BUILD_CONSOLE
LLabel_Add(s, &s->lblUpdate, "&eChecking..", main_lblUpdate_N);
LButton_Add(s, &s->btnUpdates, 100, 35, "Exit",
MainScreen_ExitApp, main_btnUpdates);
#else
LLabel_Add(s, &s->lblUpdate, "&eChecking..",
Updater_Supported ? main_lblUpdate_N : main_lblUpdate_H);
if (Updater_Supported) {
LButton_Add(s, &s->btnUpdates, 100, 35, "Updates",
SwitchToUpdates, main_btnUpdates);
}
#endif
s->btnResume.OnHover = MainScreen_ResumeHover;
s->btnResume.OnUnhover = MainScreen_ResumeUnhover;

View File

@ -65,8 +65,7 @@ void Launcher_DisplayHttpError(struct HttpRequest* req, const char* action, cc_s
if (res) {
/* Non HTTP error - this is not good */
Http_LogError(action, req);
String_Format2(dst, res >= 0x80000000 ? "&cError %h when %c" : "&cError %i when %c",
&res, action);
String_Format2(dst, "&cError %e when %c", &res, action);
} else if (status != 200) {
String_Format2(dst, "&c%i error when %c", &status, action);
} else {
@ -272,8 +271,9 @@ void Launcher_Run(void) {
#endif
for (;;) {
Window_ProcessEvents(10 / 1000.0);
Window_ProcessGamepads(10 / 1000.0);
Window_ProcessEvents(10 / 1000.0f);
Window_ProcessGamepads(10 / 1000.0f);
Gamepad_Tick(10 / 1000.0f);
if (!Window_Main.Exists || Launcher_ShouldExit) break;
Launcher_Active->Tick(Launcher_Active);

View File

@ -7,6 +7,7 @@
#include "Logger.h"
#include "Event.h"
#include "Game.h"
#include "Options.h"
struct _Lighting Lighting;
#define Lighting_Pack(x, z) ((x) + World.Width * (z))
@ -66,6 +67,12 @@ static PackedCol ClassicLighting_Color(int x, int y, int z) {
return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol;
}
static PackedCol SmoothLighting_Color(int x, int y, int z) {
if (!World_Contains(x, y, z)) return Env.SunCol;
if (Blocks.FullBright[World_GetBlock(x, y, z)]) return Env.SunCol;
return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol;
}
static PackedCol ClassicLighting_Color_XSide(int x, int y, int z) {
if (!World_Contains(x, y, z)) return Env.SunXSide;
return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunXSide : Env.ShadowXSide;
@ -375,10 +382,13 @@ static void ClassicLighting_AllocState(void) {
}
static void ClassicLighting_SetActive(void) {
cc_bool smoothLighting = false;
if (!Game_ClassicMode) smoothLighting = Options_GetBool(OPT_SMOOTH_LIGHTING, false);
Lighting.OnBlockChanged = ClassicLighting_OnBlockChanged;
Lighting.Refresh = ClassicLighting_Refresh;
Lighting.IsLit = ClassicLighting_IsLit;
Lighting.Color = ClassicLighting_Color;
Lighting.Color = smoothLighting ? SmoothLighting_Color : ClassicLighting_Color;
Lighting.Color_XSide = ClassicLighting_Color_XSide;
Lighting.IsLit_Fast = ClassicLighting_IsLit_Fast;
@ -398,6 +408,10 @@ static void ClassicLighting_SetActive(void) {
*---------------------------------------------------Lighting component----------------------------------------------------*
*#########################################################################################################################*/
void Lighting_ApplyActive() {
ClassicLighting_SetActive();
}
static void OnInit(void) { ClassicLighting_SetActive(); }
static void OnReset(void) { Lighting.FreeState(); }
static void OnNewMapLoaded(void) { Lighting.AllocState(); }

View File

@ -49,4 +49,6 @@ CC_VAR extern struct _Lighting {
PackedCol (*Color_XSide_Fast)(int x, int y, int z);
PackedCol (*Color_ZSide_Fast)(int x, int y, int z);
} Lighting;
void Lighting_ApplyActive(void);
#endif

View File

@ -126,14 +126,12 @@ static void AppendErrorDesc(cc_string* msg, cc_result res, Logger_DescribeError
}
void Logger_FormatWarn(cc_string* msg, cc_result res, const char* action, Logger_DescribeError describeErr) {
String_Format2(msg, res < 20000 ? "Error %i when %c" : "Error %h when %c",
&res, action);
String_Format2(msg, "Error %e when %c", &res, action);
AppendErrorDesc(msg, res, describeErr);
}
void Logger_FormatWarn2(cc_string* msg, cc_result res, const char* action, const cc_string* path, Logger_DescribeError describeErr) {
String_Format3(msg, res < 20000 ? "Error %i when %c '%s'" : "Error %h when %c '%s'",
&res, action, path);
String_Format3(msg, "Error %e when %c '%s'", &res, action, path);
AppendErrorDesc(msg, res, describeErr);
}
@ -508,7 +506,7 @@ static void PrintRegisters(cc_string* str, void* ctx) {
#define REG_GET_PC() &r->Pc
Dump_ARM32()
#elif defined _M_ARM64
#define REG_GNUM(num) &r->x[num]
#define REG_GNUM(num) &r->X[num]
#define REG_GET_FP() &r->Fp
#define REG_GET_LR() &r->Lr
#define REG_GET_SP() &r->Sp

View File

@ -33,6 +33,7 @@
#include "Utils.h"
#include "Errors.h"
#include "SystemFonts.h"
#include "Lighting.h"
/* Describes a menu option button */
struct MenuOptionDesc {
@ -514,7 +515,7 @@ static void PauseScreen_CheckHacksAllowed(void* screen) {
struct PauseScreen* s = (struct PauseScreen*)screen;
if (Gui.ClassicMenu) return;
Widget_SetDisabled(&s->btns[4],
Widget_SetDisabled(&s->btns[1],
!Entities.CurPlayer->Hacks.CanAnyHacks); /* select texture pack */
s->dirty = true;
}
@ -541,11 +542,11 @@ static void PauseScreen_Init(void* screen) {
struct PauseScreen* s = (struct PauseScreen*)screen;
static const struct SimpleButtonDesc descs[] = {
{ -160, -50, "Options...", Menu_SwitchOptions },
{ -160, 0, "Change texture pack...", Menu_SwitchTexPacks },
{ -160, 50, "Hotkeys...", Menu_SwitchHotkeys },
{ 160, -50, "Generate new level...", Menu_SwitchGenLevel },
{ 160, 0, "Load level...", Menu_SwitchLoadLevel },
{ 160, 50, "Save level...", Menu_SwitchSaveLevel },
{ -160, 0, "Change texture pack...", Menu_SwitchTexPacks },
{ -160, 50, "Hotkeys...", Menu_SwitchHotkeys }
{ 160, 50, "Save level...", Menu_SwitchSaveLevel }
};
s->widgets = pause_widgets;
s->numWidgets = 0;
@ -559,8 +560,8 @@ static void PauseScreen_Init(void* screen) {
s->maxVertices = Screen_CalcDefaultMaxVertices(s);
if (Server.IsSinglePlayer) return;
s->btns[1].flags = WIDGET_FLAG_DISABLED;
s->btns[2].flags = WIDGET_FLAG_DISABLED;
s->btns[3].flags = WIDGET_FLAG_DISABLED;
s->btns[5].flags = WIDGET_FLAG_DISABLED;
}
static void PauseScreen_Free(void* screen) {
@ -1655,8 +1656,18 @@ static void FontListScreen_LoadEntries(struct ListScreen* s) {
ListScreen_Select(s, SysFonts_UNSAFE_GetDefault());
}
static void FontListScreen_RegisterCallback(const cc_string* path) {
Chat_Add1("Loaded font from %s", path);
}
static void FontListScreen_UploadCallback(const cc_string* path) {
SysFonts_Register(path);
cc_result res = SysFonts_Register(path, FontListScreen_RegisterCallback);
if (res) {
Logger_SimpleWarn2(res, "loading font from", path);
} else {
SysFonts_SaveCache();
}
}
static void FontListScreen_ActionFunc(void* s, void* w) {
@ -2862,6 +2873,7 @@ static void GraphicsOptionsScreen_SetViewDist(const cc_string* v) { Game_UserSet
static void GraphicsOptionsScreen_GetSmooth(cc_string* v) { Menu_GetBool(v, Builder_SmoothLighting); }
static void GraphicsOptionsScreen_SetSmooth(const cc_string* v) {
Builder_SmoothLighting = Menu_SetBool(v, OPT_SMOOTH_LIGHTING);
Lighting_ApplyActive();
Builder_ApplyActive();
MapRenderer_Refresh();
}

View File

@ -818,6 +818,7 @@ static void CustomModel_DrawArm(struct Entity* e) {
struct CustomModel* cm = (struct CustomModel*)Models.Active;
int i;
if (!cm->numArmParts) return;
Gfx_SetAlphaTest(true);
Models.uScale = 1.0f / cm->uScale;
Models.vScale = 1.0f / cm->vScale;
@ -952,6 +953,7 @@ static void HumanModel_DrawCore(struct Entity* e, struct ModelSet* model, cc_boo
static void HumanModel_DrawArmCore(struct Entity* e, struct ModelSet* model) {
struct ModelLimbs* set;
int type, num;
Gfx_SetAlphaTest(true);
type = Models.skinType;
set = &model->limbs[type & 0x3];
@ -1854,6 +1856,7 @@ static void SkeletonModel_Draw(struct Entity* e) {
}
static void SkeletonModel_DrawArm(struct Entity* e) {
Gfx_SetAlphaTest(true);
Model_LockVB(e, MODEL_BOX_VERTICES);
Model_DrawArmPart(&skeleton_rightArm);

View File

@ -201,7 +201,7 @@ void Options_SetSecure(const char* opt, const cc_string* src) {
String_InitArray(enc, encData);
res = Platform_Encrypt(src->buffer, src->length, &enc);
if (res) { Platform_Log2("Error %h encrypting option %c", &res, opt); return; }
if (res) { Platform_Log2("Error %e encrypting option %c", &res, opt); return; }
/* base64 encode the data, as user might edit options.txt with a text editor */
if (enc.length > 1500) Logger_Abort("too large to base64");
@ -223,5 +223,5 @@ void Options_GetSecure(const char* opt, cc_string* dst) {
dataLen = Convert_FromBase64(raw.buffer, raw.length, data);
res = Platform_Decrypt(data, dataLen, dst);
if (res) Platform_Log2("Error %h decrypting option %c", &res, opt);
if (res) Platform_Log2("Error %e decrypting option %c", &res, opt);
}

View File

@ -270,6 +270,8 @@ cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* m
cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified);
/* Attempts to close the given socket */
void Socket_Close(cc_socket s);
/* Attempts to write all data to the given socket, returning ERR_END_OF_STREAM if it could not */
cc_result Socket_WriteAll(cc_socket socket, const cc_uint8* data, cc_uint32 count);
#ifdef CC_BUILD_MOBILE
void Platform_ShareScreenshot(const cc_string* filename);

View File

@ -260,9 +260,6 @@ void Platform_Init(void) {
DisableFpuExceptions();
Platform_ReadonlyFilesystem = true;
// TODO: Redesign Drawer2D to better handle this
Options_SetBool(OPT_USE_CHAT_FONT, true);
dfs_init(DFS_DEFAULT_LOCATION);
timer_init();
rtc_init();

View File

@ -18,6 +18,7 @@
#include <unistd.h>
#include <sys/time.h>
#include <nds/bios.h>
#include <nds/cothread.h>
#include <nds/interrupts.h>
#include <nds/timers.h>
#include <nds/debug.h>
@ -66,17 +67,18 @@ cc_uint64 Stopwatch_Measure(void) {
static void LogNocash(const char* msg, int len) {
// Can only be up to 120 bytes total
char buffer[120];
len = min(len, 119);
len = min(len, 118);
Mem_Copy(buffer, msg, len);
buffer[len] = '\n';
nocashWrite(buffer, len + 1);
buffer[len + 0] = '\n';
buffer[len + 1] = '\0';
nocashWrite(buffer, len + 2);
}
extern void consolePrintString(const char* ptr, int len);
void Platform_Log(const char* msg, int len) {
LogNocash(msg, len);
if (!keyboardOpen) consolePrintString(msg, len);
consolePrintString(msg, len);
}
TimeMS DateTime_CurrentUTC(void) {
@ -110,14 +112,15 @@ static void GetNativePath(char* str, const cc_string* path) {
Mem_Copy(str, root_path.buffer, root_path.length);
str += root_path.length;
String_EncodeUtf8(str, path);
Platform_Log1("Open %c", str - root_path.length);
}
cc_result Directory_Create(const cc_string* path) {
if (!fat_available) return ENOSYS;
if (!fat_available) return 0;
char str[NATIVE_STR_LEN];
GetNativePath(str, path);
Platform_Log1("mkdir %c", str);
return mkdir(str, 0) == -1 ? errno : 0;
}
@ -127,6 +130,8 @@ int File_Exists(const cc_string* path) {
char str[NATIVE_STR_LEN];
struct stat sb;
GetNativePath(str, path);
Platform_Log1("Check %c", str);
return stat(str, &sb) == 0 && S_ISREG(sb.st_mode);
}
@ -137,6 +142,8 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall
static cc_result File_Do(cc_file* file, const cc_string* path, int mode) {
char str[NATIVE_STR_LEN];
GetNativePath(str, path);
Platform_Log1("Open %c", str);
*file = open(str, mode, 0);
return *file == -1 ? errno : 0;
}
@ -186,24 +193,36 @@ cc_result File_Length(cc_file file, cc_uint32* len) {
*len = st.st_size; return 0;
}
static int LoadFatFilesystem(void* arg) {
fat_available = fatInitDefault();
return 0;
}
static void InitFilesystem(void) {
// I don't know why I have to call this function, but if I don't,
// then when running in DSi mode AND an SD card is readable,
// fatInitDefault gets stuck somewhere (in disk_initialize it seems)
if (isDSiMode()) {
const DISC_INTERFACE* sd_io = get_io_dsisd();
if (sd_io) sd_io->startup();
cothread_t thread = cothread_create(LoadFatFilesystem, NULL, 0, 0);
// If running with DSi mode in melonDS and the internal SD card is enabled, then
// fatInitDefault gets stuck in sdmmc_ReadSectors - because the fifoWaitValue32Async will never return
// (You can tell when this happens - "MMC: unknown CMD 17 00000000" is logged to console)
// However, since it does yield to cothreads, workaround this by running fatInitDefault on another thread
// and then giving up if it takes too long.. not the most elegant solution, but it does work
if (thread == -1) {
LoadFatFilesystem(NULL);
} else {
for (int i = 0; i < 100; i++)
{
cothread_yield();
if (cothread_has_joined(thread)) break;
swiDelay(2000);
}
}
fat_available = fatInitDefault();
Platform_ReadonlyFilesystem = !fat_available;
if (!fat_available) return;
char* dir = fatGetDefaultCwd();
if (dir && dir[0]) {
if (dir) {
root_path.buffer = dir;
root_path.length = String_Length(dir);
}
Platform_ReadonlyFilesystem = !fat_available;
}
@ -406,9 +425,6 @@ void Platform_Init(void) {
InitNetworking();
cpuStartTiming(1);
// TODO: Redesign Drawer2D to better handle this
Options_Load();
Options_SetBool(OPT_USE_CHAT_FONT, true);
}
void Platform_Free(void) { }

View File

@ -227,8 +227,6 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
void Platform_Init(void) {
ResetGraph(0);
Stopwatch_Init();
Options_SetBool(OPT_USE_CHAT_FONT, true);
}
void Platform_Free(void) { }

View File

@ -497,7 +497,7 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
*--------------------------------------------------------Font/Text--------------------------------------------------------*
*#########################################################################################################################*/
static void FontDirCallback(const cc_string* path, void* obj) {
SysFonts_Register(path);
SysFonts_Register(path, NULL);
}
void Platform_LoadSysFonts(void) {

View File

@ -213,8 +213,6 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
*#########################################################################################################################*/
void Platform_Init(void) {
Stopwatch_Init();
Options_SetBool(OPT_USE_CHAT_FONT, true);
}
void Platform_Free(void) { }

View File

@ -500,9 +500,6 @@ static void CreateRootDirectory(void) {
}
void Platform_Init(void) {
// TODO: Redesign Drawer2D to better handle this
//Options_SetBool(OPT_USE_CHAT_FONT, true);
CreateRootDirectory();
socketInitializeDefault();
}

View File

@ -360,7 +360,7 @@ static void FontDirCallback(const cc_string* path, void* obj) {
static const cc_string fonExt = String_FromConst(".fon");
/* Completely skip windows .FON files */
if (String_CaselessEnds(path, &fonExt)) return;
SysFonts_Register(path);
SysFonts_Register(path, NULL);
}
void Platform_LoadSysFonts(void) {
@ -839,7 +839,7 @@ cc_bool DynamicLib_DescribeError(cc_string* dst) {
dynamicErr = 0; /* Reset error (match posix behaviour) */
Platform_DescribeError(res, dst);
String_Format1(dst, " (error %i)", &res);
String_Format1(dst, " (error %e)", &res);
/* Plugin may have been compiled to load symbols from ClassiCube.exe, */
/* but the user might have renamed it to something else */

View File

@ -111,7 +111,7 @@ cc_result Directory_Create(const cc_string* path) {
}
int File_Exists(const cc_string* path) {
if (!hdd_mounted) return ERR_NOT_SUPPORTED;
if (!hdd_mounted) return 0;
char str[NATIVE_STR_LEN];
DWORD attribs;
@ -164,7 +164,7 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall
} while (FindNextFileA(find, &eA));
res = GetLastError(); /* return code from FindNextFile */
FindClose(find);
NtClose(find);
return res == ERROR_NO_MORE_FILES ? 0 : res;
}
@ -203,7 +203,8 @@ cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32*
}
cc_result File_Close(cc_file file) {
return CloseHandle(file) ? 0 : GetLastError();
NTSTATUS status = NtClose(file);
return NT_SUCCESS(status) ? 0 : status;
}
cc_result File_Seek(cc_file file, int offset, int seekType) {
@ -225,7 +226,15 @@ cc_result File_Length(cc_file file, cc_uint32* len) {
/*########################################################################################################################*
*--------------------------------------------------------Threading--------------------------------------------------------*
*#############################################################################################################p############*/
*##########################################################################################################################*/
static void WaitForSignal(HANDLE handle, LARGE_INTEGER* duration) {
for (;;)
{
NTSTATUS status = NtWaitForSingleObjectEx((HANDLE)handle, UserMode, FALSE, duration);
if (status != STATUS_ALERTED) break;
}
}
void Thread_Sleep(cc_uint32 milliseconds) { Sleep(milliseconds); }
static DWORD WINAPI ExecThread(void* param) {
Thread_StartFunc func = (Thread_StartFunc)param;
@ -243,13 +252,12 @@ void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char*
}
void Thread_Detach(void* handle) {
if (!CloseHandle((HANDLE)handle)) {
Logger_Abort2(GetLastError(), "Freeing thread handle");
}
NTSTATUS status = NtClose((HANDLE)handle);
if (!NT_SUCCESS(status)) Logger_Abort2(status, "Freeing thread handle");
}
void Thread_Join(void* handle) {
WaitForSingleObject((HANDLE)handle, INFINITE);
WaitForSignal((HANDLE)handle, NULL);
Thread_Detach(handle);
}
@ -263,30 +271,41 @@ void Mutex_Free(void* handle) {
RtlDeleteCriticalSection((CRITICAL_SECTION*)handle);
Mem_Free(handle);
}
void Mutex_Lock(void* handle) { RtlEnterCriticalSection((CRITICAL_SECTION*)handle); }
void Mutex_Unlock(void* handle) { RtlLeaveCriticalSection((CRITICAL_SECTION*)handle); }
void Mutex_Lock(void* handle) {
RtlEnterCriticalSection((CRITICAL_SECTION*)handle);
}
void Mutex_Unlock(void* handle) {
RtlLeaveCriticalSection((CRITICAL_SECTION*)handle);
}
void* Waitable_Create(void) {
void* handle = CreateEventA(NULL, false, false, NULL);
if (!handle) {
Logger_Abort2(GetLastError(), "Creating waitable");
}
HANDLE handle;
NTSTATUS status = NtCreateEvent(&handle, NULL, SynchronizationEvent, false);
if (!NT_SUCCESS(status)) Logger_Abort2(status, "Creating waitable");
return handle;
}
void Waitable_Free(void* handle) {
if (!CloseHandle((HANDLE)handle)) {
Logger_Abort2(GetLastError(), "Freeing waitable");
}
NTSTATUS status = NtClose((HANDLE)handle);
if (!NT_SUCCESS(status)) Logger_Abort2(status, "Freeing waitable");
}
void Waitable_Signal(void* handle) {
NtSetEvent((HANDLE)handle, NULL);
}
void Waitable_Signal(void* handle) { NtSetEvent((HANDLE)handle, NULL); }
void Waitable_Wait(void* handle) {
WaitForSingleObject((HANDLE)handle, INFINITE);
WaitForSignal((HANDLE)handle, NULL);
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
WaitForSingleObject((HANDLE)handle, milliseconds);
LARGE_INTEGER duration;
duration.QuadPart = ((LONGLONG)milliseconds) * -10000; // negative for relative timeout
WaitForSignal((HANDLE)handle, &duration);
}
@ -408,7 +427,9 @@ static void InitHDD(void) {
void Platform_Init(void) {
InitHDD();
Stopwatch_Init();
#ifndef CC_BUILD_CXBX
nxNetInit(NULL);
#endif
}
void Platform_Free(void) {

View File

@ -358,7 +358,7 @@ static void DisconnectInvalidMap(cc_result res) {
cc_string tmp; char tmpBuffer[STRING_SIZE];
String_InitArray(tmp, tmpBuffer);
String_Format1(&tmp, "Server sent corrupted map data (error %h)", &res);
String_Format1(&tmp, "Server sent corrupted map data (error %e)", &res);
Game_Disconnect(&title, &tmp); return;
}

View File

@ -105,21 +105,6 @@ static SECURITY_STATUS SSL_CreateHandle(struct SSLContext* ctx) {
&cred, NULL, NULL, &ctx->handle, NULL);
}
static cc_result SSL_SendRaw(cc_socket socket, const cc_uint8* data, cc_uint32 count) {
cc_uint32 sent;
cc_result res;
while (count)
{
if ((res = Socket_Write(socket, data, count, &sent))) return res;
if (!sent) return ERR_END_OF_STREAM;
data += sent;
count -= sent;
}
return 0;
}
static cc_result SSL_RecvRaw(struct SSLContext* ctx) {
cc_uint32 read;
cc_result res;
@ -160,7 +145,7 @@ static SECURITY_STATUS SSL_Connect(struct SSLContext* ctx, const char* hostname)
/* Send initial handshake to the server (if there is one) */
if (out_buffers[0].pvBuffer) {
res = SSL_SendRaw(ctx->socket, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer);
res = Socket_WriteAll(ctx->socket, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer);
FP_FreeContextBuffer(out_buffers[0].pvBuffer);
}
return res;
@ -221,7 +206,7 @@ static SECURITY_STATUS SSL_Negotiate(struct SSLContext* ctx) {
/* Need to send data to the server */
if (sec == SEC_I_CONTINUE_NEEDED) {
res = SSL_SendRaw(ctx->socket, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer);
res = Socket_WriteAll(ctx->socket, out_buffers[0].pvBuffer, out_buffers[0].cbBuffer);
FP_FreeContextBuffer(out_buffers[0].pvBuffer); /* TODO always free? */
if (res) return res;
@ -392,13 +377,12 @@ static cc_result SSL_WriteChunk(struct SSLContext* s, const cc_uint8* data, cc_u
/* NOTE: Okay to write in one go, since all three buffers will be contiguous */
/* (as TLS record header size will always be the same size) */
total = buffers[0].cbBuffer + buffers[1].cbBuffer + buffers[2].cbBuffer;
return SSL_SendRaw(s->socket, buffer, total);
return Socket_WriteAll(s->socket, buffer, total);
}
cc_result SSL_Write(void* ctx, const cc_uint8* data, cc_uint32 count, cc_uint32* wrote) {
cc_result SSL_WriteAll(void* ctx, const cc_uint8* data, cc_uint32 count) {
struct SSLContext* s = ctx;
cc_result res;
*wrote = 0;
/* TODO: Don't loop here? move to HTTPConnection instead?? */
while (count)
@ -406,7 +390,6 @@ cc_result SSL_Write(void* ctx, const cc_uint8* data, cc_uint32 count, cc_uint32*
int len = min(count, s->sizes.cbMaximumMessage);
if ((res = SSL_WriteChunk(s, data, len))) return res;
*wrote += len;
data += len;
count -= len;
}
@ -558,7 +541,7 @@ cc_result SSL_Read(void* ctx_, cc_uint8* data, cc_uint32 count, cc_uint32* read)
return 0;
}
cc_result SSL_Write(void* ctx_, const cc_uint8* data, cc_uint32 count, cc_uint32* wrote) {
cc_result SSL_WriteAll(void* ctx_, const cc_uint8* data, cc_uint32 count) {
SSLContext* ctx = (SSLContext*)ctx_;
// TODO: just br_sslio_write ??
int res = br_sslio_write_all(&ctx->ioc, data, count);
@ -569,7 +552,6 @@ cc_result SSL_Write(void* ctx_, const cc_uint8* data, cc_uint32 count, cc_uint32
}
br_sslio_flush(&ctx->ioc);
*wrote = res;
return 0;
}
@ -592,7 +574,7 @@ cc_result SSL_Read(void* ctx, cc_uint8* data, cc_uint32 count, cc_uint32* read)
return ERR_NOT_SUPPORTED;
}
cc_result SSL_Write(void* ctx, const cc_uint8* data, cc_uint32 count, cc_uint32* wrote) {
cc_result SSL_WriteAll(void* ctx, const cc_uint8* data, cc_uint32 count) {
return ERR_NOT_SUPPORTED;
}

View File

@ -11,6 +11,6 @@ cc_bool SSLBackend_DescribeError(cc_result res, cc_string* dst);
cc_result SSL_Init(cc_socket socket, const cc_string* host, void** ctx);
cc_result SSL_Read(void* ctx, cc_uint8* data, cc_uint32 count, cc_uint32* read);
cc_result SSL_Write(void* ctx, const cc_uint8* data, cc_uint32 count, cc_uint32* wrote);
cc_result SSL_WriteAll(void* ctx, const cc_uint8* data, cc_uint32 count);
cc_result SSL_Free(void* ctx);
#endif

Some files were not shown because too many files have changed in this diff Show More