From e6644af3012b62395db9807b9b3865ff42b12e1b Mon Sep 17 00:00:00 2001 From: Shinovon Date: Thu, 24 Jul 2025 07:40:02 +0500 Subject: [PATCH 001/115] Fix performance drop when rendering translucent on PowerVR MBX --- misc/opengl/GLCommon.h | 2 ++ src/Graphics_GL1.c | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/misc/opengl/GLCommon.h b/misc/opengl/GLCommon.h index 9c8b6f0ee..207c7328d 100644 --- a/misc/opengl/GLCommon.h +++ b/misc/opengl/GLCommon.h @@ -42,6 +42,8 @@ typedef cc_uintptr GLpointer; #define GL_TRIANGLES 0x0004 #define GL_QUADS 0x0007 +#define GL_ZERO 0 +#define GL_ONE 1 #define GL_BLEND 0x0BE2 #define GL_SRC_ALPHA 0x0302 #define GL_ONE_MINUS_SRC_ALPHA 0x0303 diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 02a21331c..4f027d8e1 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -25,6 +25,8 @@ #include "../misc/opengl/GL1Funcs.h" #if defined CC_BUILD_SYMBIAN #include "../misc/opengl/GL2Funcs.h" + +static cc_bool mbx; #endif #if CC_BUILD_MAXSTACK <= (64 * 1024) @@ -84,7 +86,9 @@ void Gfx_Create(void) { #ifdef CC_BUILD_GL11_FALLBACK GLContext_GetAll(coreFuncs, Array_Elems(coreFuncs)); #endif +#ifndef CC_BUILD_GLES customMipmapsLevels = true; +#endif Gfx.BackendType = CC_GFX_BACKEND_GL1; GL_InitCommon(); @@ -335,6 +339,17 @@ static void SetAlphaTest(cc_bool enabled) { void Gfx_DepthOnlyRendering(cc_bool depthOnly) { cc_bool enabled = !depthOnly; +#ifdef CC_BUILD_SYMBIAN + if (mbx) { + if (depthOnly) { + _glBlendFunc(GL_ZERO, GL_ONE); + Gfx_SetAlphaBlending(true); + } else { + _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + return; + } +#endif SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); @@ -422,6 +437,18 @@ cc_bool Gfx_WarnIfNecessary(void) { Gfx.Limitations |= GFX_LIMIT_VERTEX_ONLY_FOG; return true; } +#if defined CC_BUILD_SYMBIAN + if (String_ContainsConst(&renderer, "SGX")) { + } else if (String_ContainsConst(&renderer, "MBX")) { + Gfx.Limitations |= GFX_LIMIT_VERTEX_ONLY_FOG; + mbx = true; + } else if (!String_ContainsConst(&renderer, "HW")) { + Chat_AddRaw("&cSoftware rendering is being used, performance will greatly suffer."); + + Gfx.Limitations |= GFX_LIMIT_MINIMAL; + return true; + } +#endif return false; } From aa11859bdabb3e4465e5ca83b33f56a89285b48e Mon Sep 17 00:00:00 2001 From: Shinovon Date: Thu, 24 Jul 2025 12:54:13 +0500 Subject: [PATCH 002/115] Symbian: rewrite main loop --- src/Window_Symbian.cpp | 60 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/Window_Symbian.cpp b/src/Window_Symbian.cpp index f9f7609fc..15d32668c 100644 --- a/src/Window_Symbian.cpp +++ b/src/Window_Symbian.cpp @@ -485,35 +485,41 @@ void CCAppUi::HandleCommandL(TInt aCommand) { // CCContainer implementation TInt CCContainer::LoopCallBack(TAny*) { - if (!WindowInfo.Exists) { - Window_RequestClose(); - container->iAppUi->Exit(); - return EFalse; - } - - // launcher -> game -> launcher -> ... loop - launcher: - if (!gameRunning) { - if (Launcher_Tick()) { - return ETrue; + cc_bool run = false; + for (;;) { + if (!WindowInfo.Exists) { + Window_RequestClose(); + container->iAppUi->Exit(); + return EFalse; } - Launcher_Finish(); - - // run game - gameRunning = true; - Game_Setup(); - container->RestartTimerL(100); + + if (run) { + run = false; + ProcessProgramArgs(0, 0); + Game_Setup(); + gameRunning = true; + container->RestartTimerL(100); + } + + if (!gameRunning) { + if (Launcher_Tick()) break; + Launcher_Finish(); + run = true; + continue; + } + + if (!Game_Running) { + gameRunning = false; + Game_Free(); +// Launcher_Setup(); +// container->RestartTimerL(10000); + WindowInfo.Exists = false; + continue; + } + + Game_RenderFrame(); + break; } - - if (!Game_Running) { - // return to launcher - gameRunning = false; - Game_Free(); - Launcher_Setup(); - container->RestartTimerL(10000); - goto launcher; - } - Game_RenderFrame(); return ETrue; } From 9b1af5d3af11e50472d9a82baa245280f6045bfd Mon Sep 17 00:00:00 2001 From: Shinovon Date: Sat, 26 Jul 2025 02:40:44 +0500 Subject: [PATCH 003/115] Try to achieve better performance on MBX by disabling things --- src/Core.h | 1 + src/Graphics_GL1.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Core.h b/src/Core.h index 3dc3cea14..abe4086b3 100644 --- a/src/Core.h +++ b/src/Core.h @@ -616,6 +616,7 @@ typedef cc_uint8 cc_bool; #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #else #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define CC_DISABLE_ANIMATIONS #endif #endif #endif diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 4f027d8e1..88c1fca10 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -440,7 +440,7 @@ cc_bool Gfx_WarnIfNecessary(void) { #if defined CC_BUILD_SYMBIAN if (String_ContainsConst(&renderer, "SGX")) { } else if (String_ContainsConst(&renderer, "MBX")) { - Gfx.Limitations |= GFX_LIMIT_VERTEX_ONLY_FOG; + Gfx.Limitations |= GFX_LIMIT_MINIMAL; mbx = true; } else if (!String_ContainsConst(&renderer, "HW")) { Chat_AddRaw("&cSoftware rendering is being used, performance will greatly suffer."); From 7c94970b8d80a40aa7e304fb77f76a4c76be0e1e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 26 Jul 2025 21:37:23 +1000 Subject: [PATCH 004/115] Move Wii U to new makefile --- misc/3ds/Makefile | 2 +- misc/n64/Makefile | 16 ++- misc/wiiu/Makefile | 233 +++++++++++++-------------------- misc/wiiu/icon.png | Bin 0 -> 3971 bytes src/Http_Worker.c | 122 ----------------- src/{ => wiiu}/Audio_WiiU.c | 8 +- src/{ => wiiu}/Graphics_WiiU.c | 10 +- src/{ => wiiu}/Platform_WiiU.c | 28 ++-- src/{ => wiiu}/Window_WiiU.c | 30 ++--- 9 files changed, 137 insertions(+), 312 deletions(-) create mode 100644 misc/wiiu/icon.png rename src/{ => wiiu}/Audio_WiiU.c (94%) rename src/{ => wiiu}/Graphics_WiiU.c (96%) rename src/{ => wiiu}/Platform_WiiU.c (95%) rename src/{ => wiiu}/Window_WiiU.c (95%) diff --git a/misc/3ds/Makefile b/misc/3ds/Makefile index 902b47195..717530b0f 100644 --- a/misc/3ds/Makefile +++ b/misc/3ds/Makefile @@ -121,7 +121,7 @@ $(BUILD_DIR)/%.shbin: misc/3ds/%.v.pica $(PICASSO) $< -o $@ $(BUILD_DIR)/%.shbin.o: $(BUILD_DIR)/%.shbin - $(BIN2S) $< | $(ARM_AS) -o $@ + $(BIN2S) $< | $(ARM_CC) -x assembler-with-cpp -c - -o $@ #--------------------------------------------------------------------------------- diff --git a/misc/n64/Makefile b/misc/n64/Makefile index c243c55fd..341bc1163 100644 --- a/misc/n64/Makefile +++ b/misc/n64/Makefile @@ -4,16 +4,24 @@ N64_ROM_TITLE = "ClassiCube" N64_ROM_RTC = true TARGET = ClassiCube-n64 N64_MKDFS_ROOT = "misc/n64/files" +SRC_DIRS = CFILES := $(notdir $(wildcard src/*.c)) OFILES := $(CFILES:.c=.o) rsp_gpu.o OBJS := $(addprefix $(BUILD_DIR)/,$(OFILES)) CFLAGS := -Wno-error=missing-braces -Wno-error=strict-aliasing -Wno-error=incompatible-pointer-types -default: $(TARGET).z64 + +default: $(BUILD_DIR) $(TARGET).z64 + +clean: + rm -rf $(BUILD_DIR) $(TARGET).z64 + +$(BUILD_DIR): + mkdir -p $@ + $(BUILD_DIR)/%.o: src/%.c - @mkdir -p $(dir $@) @echo " [CC] $<" $(CC) -c $(CFLAGS) -o $@ $< @@ -26,8 +34,4 @@ $(BUILD_DIR)/filesystem.dfs: misc/n64/files/default.zip $(BUILD_DIR)/ClassiCube-n64.elf: $(OBJS) -clean: - rm -rf $(BUILD_DIR) $(TARGET).z64 -.PHONY: clean - -include $(wildcard $(BUILD_DIR)/*.d) diff --git a/misc/wiiu/Makefile b/misc/wiiu/Makefile index 5e8424dea..9ec2f0cf9 100644 --- a/misc/wiiu/Makefile +++ b/misc/wiiu/Makefile @@ -1,170 +1,123 @@ -#------------------------------------------------------------------------------- -.SUFFIXES: -#------------------------------------------------------------------------------- - ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro) endif -TOPDIR ?= $(CURDIR) +.SUFFIXES: -#------------------------------------------------------------------------------- -# APP_NAME sets the long name of the application -# APP_SHORTNAME sets the short name of the application -# APP_AUTHOR sets the author of the application -#------------------------------------------------------------------------------- -APP_NAME := ClassiCube -APP_SHORTNAME := ClassiCube -APP_AUTHOR := ClassiCube team -include $(DEVKITPRO)/wut/share/wut_rules +#--------------------------------------------------------------------------------- +# Configurable options +#--------------------------------------------------------------------------------- +# Name of the final output +TARGET = ClassiCube-wiiu +# List of directories containing source code +SOURCE_DIRS = src src/wiiu third_party/bearssl +# Directory where object files are placed +BUILD_DIR = build/wiiu +# Directory where shader files are +SHADERS = misc/wiiu -#------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -# CONTENT is the path to the bundled folder that will be mounted as /vol/content/ -# ICON is the game icon, leave blank to use default rule -# TV_SPLASH is the image displayed during bootup on the TV, leave blank to use default rule -# DRC_SPLASH is the image displayed during bootup on the DRC, leave blank to use default rule -#------------------------------------------------------------------------------- -TARGET := ClassiCube-wiiu -BUILD := build-wiiu -SOURCES := src third_party/bearssl -SHADERS := misc/wiiu -DATA := data -INCLUDES := -CONTENT := -ICON := -TV_SPLASH := -DRC_SPLASH := +WUHB_OPTIONS = \ + --name "ClassiCube" \ + --short-name "ClassiCube" \ + --author "ClassiCube team" \ + --icon=misc/wiiu/icon.png -#------------------------------------------------------------------------------- -# options for code generation -#------------------------------------------------------------------------------- -CFLAGS := -g -Wall -O2 -ffunction-sections -fno-math-errno \ - $(MACHDEP) +#WUHB_OPTIONS += --tv-image=misc/wiiu/tv_splash.png +#WUHB_OPTIONS += --drc-image=misc/wiiu/drc_splash.png -CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -CXXFLAGS := $(CFLAGS) +#--------------------------------------------------------------------------------- +# Compilable files +#--------------------------------------------------------------------------------- +S_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) - -LIBS := -lwut -lm - -#------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level -# containing include and lib -#------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUT_ROOT) - -#------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(SHADERS),$(notdir $(wildcard $(dir)/*.gsh))) - -export LD := $(CC) +BINFILES := $(foreach dir,$(SHADERS),$(wildcard $(dir)/*.gsh)) +OBJS += $(addprefix $(BUILD_DIR)/, $(notdir $(BINFILES:%.gsh=%.gsh.o))) export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(OBJS:%.o=%.d) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -ifneq (,$(strip $(CONTENT))) - export APP_CONTENT := $(TOPDIR)/$(CONTENT) -endif +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +MACHDEP = -DESPRESSO -mcpu=750 -meabi -mhard-float +CFLAGS = -g -Wall -O2 -ffunction-sections -fno-math-errno $(MACHDEP) \ + -I $(DEVKITPRO)/wut/include \ + -D__WIIU__ -D__WUT__ -ifneq (,$(strip $(ICON))) - export APP_ICON := $(TOPDIR)/$(ICON) -else ifneq (,$(wildcard $(TOPDIR)/$(TARGET).png)) - export APP_ICON := $(TOPDIR)/$(TARGET).png -else ifneq (,$(wildcard $(TOPDIR)/icon.png)) - export APP_ICON := $(TOPDIR)/icon.png -endif +LDFLAGS = -g $(MACHDEP) -specs=$(DEVKITPRO)/wut/share/wut.specs \ + -L $(DEVKITPRO)/wut/lib +# Additional libraries to link against +LIBS = -lwut -lm -ifneq (,$(strip $(TV_SPLASH))) - export APP_TV_SPLASH := $(TOPDIR)/$(TV_SPLASH) -else ifneq (,$(wildcard $(TOPDIR)/tv-splash.png)) - export APP_TV_SPLASH := $(TOPDIR)/tv-splash.png -else ifneq (,$(wildcard $(TOPDIR)/splash.png)) - export APP_TV_SPLASH := $(TOPDIR)/splash.png -endif -ifneq (,$(strip $(DRC_SPLASH))) - export APP_DRC_SPLASH := $(TOPDIR)/$(DRC_SPLASH) -else ifneq (,$(wildcard $(TOPDIR)/drc-splash.png)) - export APP_DRC_SPLASH := $(TOPDIR)/drc-splash.png -else ifneq (,$(wildcard $(TOPDIR)/splash.png)) - export APP_DRC_SPLASH := $(TOPDIR)/splash.png -endif +#--------------------------------------------------------------------------------- +# Compiler tools +#--------------------------------------------------------------------------------- +PREFIX := $(DEVKITPRO)/devkitPPC/bin/powerpc-eabi- +PPC_AS := $(PREFIX)as +PPC_CC := $(PREFIX)gcc +PPC_CXX := $(PREFIX)g++ -.PHONY: $(BUILD) clean all +ELF2RPL := $(DEVKITPRO)/tools/bin/elf2rpl +WUHBTOOL := $(DEVKITPRO)/tools/bin/wuhbtool +BIN2S := $(DEVKITPRO)/tools/bin/bin2s -#------------------------------------------------------------------------------- -all: $(BUILD) -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/misc/wiiu/Makefile +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).wuhb -#------------------------------------------------------------------------------- clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).wuhb $(TARGET).rpx $(TARGET).elf + rm $(TARGET).wuhb $(TARGET).rpx $(TARGET).elf $(OBJS) -#------------------------------------------------------------------------------- -else -.PHONY: all +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) -DEPENDS := $(OFILES:.o=.d) -#------------------------------------------------------------------------------- -# main targets -#------------------------------------------------------------------------------- -all : $(OUTPUT).wuhb +#--------------------------------------------------------------------------------- +# Executable generation +#--------------------------------------------------------------------------------- +$(TARGET).elf: $(OBJS) + $(PPC_CC) $(LDFLAGS) $^ -o $@ $(LIBS) + +$(TARGET).rpx: $(TARGET).elf + $(ELF2RPL) $< $@ + +$(TARGET).wuhb: $(TARGET).rpx + $(WUHBTOOL) $< $@ $(WUHB_OPTIONS) -$(OUTPUT).wuhb : $(OUTPUT).rpx -$(OUTPUT).rpx : $(OUTPUT).elf -$(OUTPUT).elf : $(OFILES) -# you need a rule like this for each extension you use as binary data -#------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) -#------------------------------------------------------------------------------- -%.gsh.o %_gsh.h : ../misc/wiiu/%.gsh -#------------------------------------------------------------------------------- - echo $(notdir $<) - $(bin2o) +#--------------------------------------------------------------------------------- +# Object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/%.c + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ --include $(DEPENDS) +$(BUILD_DIR)/%.o: src/wiiu/%.S + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ -#------------------------------------------------------------------------------- -endif -#------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/wiiu/%.c + $(PPC_CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: third_party/bearssl/%.c + $(PPC_CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.gsh.o : misc/wiiu/%.gsh + $(BIN2S) $< | $(PPC_CC) -x assembler-with-cpp -c - -o $@ + + +#--------------------------------------------------------------------------------- +# Dependency tracking +#--------------------------------------------------------------------------------- +$(DEPFILES): + +include $(wildcard $(DEPFILES)) diff --git a/misc/wiiu/icon.png b/misc/wiiu/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7679104138cd403c885bbdfa60f29f0d11c1bef9 GIT binary patch literal 3971 zcmW+(2|QHo+djr%Y#BoKEn9XO@fSv83CS`jyWtHZONg2fW1C{gTe4;eMPWk7o_%W) zVidv*3E9Sr?0lzhe$Slqn>o+(oO`+M>$;yrYs;&gY(i`R0C1X_8lk~E{_hvY3|_nR zJ;>kN!3!~Om*RfUTJRM zI|cgR^cG#VKaj@$6wMZr#zLMv=L*s{Ft}az%QVqWMkkYmqRebd+50|V0ztcdTB-&}XsKfumO>Q?>kwF9#c~<8Bda47j_340LEa6u&Dpc~;mK{K1Ro zz~|l`!m!g&wq&}`lm>9>Z!I36ZQ!@J6;IFKpRQA9>*=czI`Mx2(7En52NtvR(8H4h zhhW!Xqjut{eFMjby94umsRMMnS~+}GpaZ2QsLxM)T3xMccpRW`+@lTUZ)D7Q$Y!5qIm4H#O(03EuTnK3_p>guYiYkS~`*!!u z2YYuF1bpzTV$O-ZtVgJniFd9KoIt5@Pj}>vkeo=jgE>FI1w78IZ(HtE3_juBYv=tT zNSjZA#}WiQAb*nSY@EBBCOxows6 zK^5aOWAW%wmizoXC|f4txtTs;nRp_<(rt5Uix~kqrDC2u9Lg$Eu9?Rw)1hQokTB6V zMW~$3k#QLNIUmqf!+ymuxn0wtHm;c&*1^X5T1zG7pStlkn9YC|+TUfO>Yd8UkiDF7 z`Z+!DNy!zM`?rhl4T%>434Wr7zdy(5=;+?|s8#UtR~b_Mdyj5f5H*fVzkQ?a^hsZ; z`24u?b;hGTw+eA<4y1-goR$7Q)Uwoet1DnT*a?;@rq>B(U`sEHK$_j?TV1Wtn^Y!9 zz;LI>yH8D}>FdoKQUyb{(HR5J&OGY6^sz@9Bqw_ ztd1F)vwi#qX&%pMeEtjwR-e-F;wmOgFiy~|gCB293&1fs1N>cB@k)X+K*W6b|5*Yx zB?nI5Ay|0IrIuJ_AkBBo&Yj&EkoC~)Qv42~CfjpXV%YI#5&CYt#!v_YIBGw9=v)qs zg~y`b#&>lY-nuCGGvt4lxrQx<1wOuh&D7f3x&*r6Y{i{o5*!qSUs&*3U0n@Yu2cr% zUS|JxRXKNXZ~#vZbZ^Kw4H#uDZF|?^Y%Q!W4M)=+XD7DZ@)IdT2CBX|veT z<@l*JLf`xq2{?XeF|Mny(Q^=ie|}!+V93J1$=Swc_n3K z$vn&Q1I=U=hOuom({=im!1ZngvjQZd~;n8;{x)<7q(_s0*B zGKvCaXCXw;&(F`n-Tms-t1O_M)J>fBE?P7LYU%7O4BD#V{;^{JL60Z*)YMcCvXXEC z^8New_M@Yg5-+$UbU9S$^5x47_tu1pMzDr1j4L530vw)Ltm%DL(V-EpED3yTtKMKQ zGDV5(;O5plGb6^#!V;FEz+YQ2Z&(N?5D1~{ngv65MUMd=2D@_m7Tjj%Ftq>VL_Z%H z{iLu^a_=~*YdwOW#46(TQ&|1lrr6(!6%`fKrKNuQVFuaD!qQUesp%5iyDx@AvMJwI zG(YdLu(0&sy4bW)%&f)moa|LmS-I7uCvDa_HpUCSePm>$@GvU;{^E~7t!D$TJiNBZ zWOB(WPsrK!@p1mJ?n*w#40RB-G@1uA?#lIDHL06m?7@Y!d(Cf=#YVf}_5hID7Z;?> zQTdJNqT=&uiA9^eo#U2cFZc!%6BC5;+33SHt!ed7J1gI~VbC}41{b$XU!y^zDpTm` z>3q0WH$aVKf+vTUxu|G}T7A7%=hOqPl{WJ{sc@S=JdQFdwkh+wdGqGx(f(Z!OSyg+ z6fC4sB&0F-oqlz@F|hdd1-}jN$mC?w`1p;-MW)A%s6zby{)6j7V@dK!4G*?TZo3u0 zW3#gbm6Vhm0FVmj`uaXtSS*s4;$@QrN7?|jhj>mtlN`2DS5<}o z^XFcJi^{L48Y&p2k`vHLe}Dg=HKJHU1CUYI)7O?lzgf zj%_$Nr0ij#`^DK~{vx@ZOw5fRgVFi98l`UjoH0D=%8 zJI`n!0k>9OzG1nII7?t}Uk*jvcOzZ^Vt3UaEY>l8$a*q00WhblU9KueO z2MUHtb96{{3jN+SEln6$Ed&njsB)ALIdfj*jBtpmW&-|2dS<$uXU<&wX7Rq$9*8k82;+2BNN;F` z4Ek@gwQuaUp{KwYF*7qaj9(7oa;rl_cx;S4H&)}MV<_m9ajF$|Pt9XO1-KHXgA zbN-g&ukh9B+9R*Ob1$h<znrGp=#hh~3{m)U%)kRi|79OkHX1I zRlT2G$f)&Yk zuI!)%T_s-(dIkif>`y3VHN}A%^XB$SIYr^GzJ2@{n7B|l?u4}A<>p}KPBa>xm>9Tq z1eW~7gyVXQdK%!68dcEO-VWHuB+MP2?9Hb(G0XF^?X6U{Su3Q6?v#t|N6w6Sa-m=) zrKQ<^9ITR`8B5$64!D3*-Qze=iNS6|40I#WDE5NYJ8Fc2tDvBi?ch20>HcEDKcS(#L?SV#!1>Nn z3Bxu-0I zs@htkh!s{5;fJxmJe8-e<;2rRu8O~1XYmgR@CXdF+;+J9XJ|8HLxEX=SxK{%A* zFZ9bS#-+erGHcq}3MQxf-zQth#!)DgoY7X#J+M$RrXC}S+`^yF10R{`?uc`vuq*pp zYM^B1Xn1sB;PrQAZ?syL1H6-ylVEo@JTvnoBO@d2x`bnfmFJ7;>FG4x-UnEbO(dhh z@ornramiCY<|Oz@+OLlYbyT&3kwQ93C(rx$V+q(}BPrYpsVP_yIEH8+TiEc@g0w+O zk~Tw6n~yKeNB3@ij#zKX=Mzg?y+_k2RO~<%{KKaFC4ohxZ0AKK6n-gb3t}^p$&fF~|p{aAToC+?z*o6X35DITv$#0UQ`M0X=sG*!><)OU2F#2tjozU!vHu6NNp|G` literal 0 HcmV?d00001 diff --git a/src/Http_Worker.c b/src/Http_Worker.c index c3f6ec549..d74509228 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -737,128 +737,6 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) { static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { return SSLBackend_DescribeError(res, dst); } -#elif defined CC_BUILD_ANDROID -/*########################################################################################################################* -*-----------------------------------------------------Android backend-----------------------------------------------------* -*#########################################################################################################################*/ -struct HttpRequest* java_req; -static jmethodID JAVA_httpInit, JAVA_httpSetHeader, JAVA_httpPerform, JAVA_httpSetData; -static jmethodID JAVA_httpDescribeError; - -static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { - char buffer[NATIVE_STR_LEN]; - cc_string err; - JNIEnv* env; - jvalue args[1]; - jobject obj; - - JavaGetCurrentEnv(env); - args[0].i = res; - obj = JavaSCall_Obj(env, JAVA_httpDescribeError, args); - if (!obj) return false; - - err = JavaGetString(env, obj, buffer); - String_AppendString(dst, &err); - (*env)->DeleteLocalRef(env, obj); - return true; -} - -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) { - JNIEnv* env; - jvalue args[2]; - - JavaGetCurrentEnv(env); - args[0].l = JavaMakeConst(env, key); - args[1].l = JavaMakeString(env, value); - - JavaSCall_Void(env, JAVA_httpSetHeader, args); - (*env)->DeleteLocalRef(env, args[0].l); - (*env)->DeleteLocalRef(env, args[1].l); -} - -/* Processes a HTTP header downloaded from the server */ -static void JNICALL java_HttpParseHeader(JNIEnv* env, jobject o, jstring header) { - char buffer[NATIVE_STR_LEN]; - cc_string line = JavaGetString(env, header, buffer); - Http_ParseHeader(java_req, &line); -} - -/* Processes a chunk of data downloaded from the web server */ -static void JNICALL java_HttpAppendData(JNIEnv* env, jobject o, jbyteArray arr, jint len) { - struct HttpRequest* req = java_req; - int ok = Http_BufferExpand(req, len); - if (!ok) Process_Abort("Out of memory for HTTP request"); - - (*env)->GetByteArrayRegion(env, arr, 0, len, (jbyte*)(&req->data[req->size])); - Http_BufferExpanded(req, len); -} - -static const JNINativeMethod methods[] = { - { "httpParseHeader", "(Ljava/lang/String;)V", java_HttpParseHeader }, - { "httpAppendData", "([BI)V", java_HttpAppendData } -}; -static void CacheMethodRefs(JNIEnv* env) { - JAVA_httpInit = JavaGetSMethod(env, "httpInit", "(Ljava/lang/String;Ljava/lang/String;)I"); - JAVA_httpSetHeader = JavaGetSMethod(env, "httpSetHeader", "(Ljava/lang/String;Ljava/lang/String;)V"); - JAVA_httpPerform = JavaGetSMethod(env, "httpPerform", "()I"); - JAVA_httpSetData = JavaGetSMethod(env, "httpSetData", "([B)I"); - - JAVA_httpDescribeError = JavaGetSMethod(env, "httpDescribeError", "(I)Ljava/lang/String;"); -} - -static void HttpBackend_Init(void) { - JNIEnv* env; - JavaGetCurrentEnv(env); - JavaRegisterNatives(env, methods); - CacheMethodRefs(env); -} - -static cc_result Http_InitReq(JNIEnv* env, struct HttpRequest* req, cc_string* url) { - static const char* verbs[3] = { "GET", "HEAD", "POST" }; - jvalue args[2]; - jint res; - - args[0].l = JavaMakeString(env, url); - args[1].l = JavaMakeConst(env, verbs[req->requestType]); - - res = JavaSCall_Int(env, JAVA_httpInit, args); - (*env)->DeleteLocalRef(env, args[0].l); - (*env)->DeleteLocalRef(env, args[1].l); - return res; -} - -static cc_result Http_SetData(JNIEnv* env, struct HttpRequest* req) { - jvalue args[1]; - jint res; - - args[0].l = JavaMakeBytes(env, req->data, req->size); - res = JavaSCall_Int(env, JAVA_httpSetData, args); - (*env)->DeleteLocalRef(env, args[0].l); - return res; -} - -static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) { - JNIEnv* env; - jint res; - - JavaGetCurrentEnv(env); - if ((res = Http_InitReq(env, req, url))) return res; - java_req = req; - - Http_SetRequestHeaders(req); - Http_AddHeader(req, "User-Agent", Http_GetUserAgent_UNSAFE()); - - if (req->data) { - if ((res = Http_SetData(env, req))) return res; - HttpRequest_Free(req); - } - - req->_capacity = 0; - req->progress = HTTP_PROGRESS_FETCHING_DATA; - res = JavaSCall_Int(env, JAVA_httpPerform, NULL); - req->progress = 100; - return res; -} #elif !defined CC_BUILD_NETWORKING /*########################################################################################################################* *------------------------------------------------------Null backend-------------------------------------------------------* diff --git a/src/Audio_WiiU.c b/src/wiiu/Audio_WiiU.c similarity index 94% rename from src/Audio_WiiU.c rename to src/wiiu/Audio_WiiU.c index f3e38a1e2..7bff38766 100644 --- a/src/Audio_WiiU.c +++ b/src/wiiu/Audio_WiiU.c @@ -1,12 +1,9 @@ -#include "Core.h" - -#if defined CC_BUILD_WIIU #include -static cc_bool ax_inited; struct AudioContext { int count; }; -#include "_AudioBase.h" +#include "../_AudioBase.h" +static cc_bool ax_inited; cc_bool AudioBackend_Init(void) { if (ax_inited) return true; @@ -114,5 +111,4 @@ cc_result SoundContext_PollBusy(struct AudioContext* ctx, cc_bool* isBusy) { cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { return false; } -#endif diff --git a/src/Graphics_WiiU.c b/src/wiiu/Graphics_WiiU.c similarity index 96% rename from src/Graphics_WiiU.c rename to src/wiiu/Graphics_WiiU.c index fec7b881f..4f0da4e01 100644 --- a/src/Graphics_WiiU.c +++ b/src/wiiu/Graphics_WiiU.c @@ -1,8 +1,7 @@ -#include "Core.h" -#ifdef CC_BUILD_WIIU -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Window.h" +#include "../_GraphicsBase.h" +#include "../Errors.h" +#include "../Window.h" + #include #include #include @@ -591,4 +590,3 @@ void Gfx_3DS_SetRenderScreen1(enum Screen3DS screen) { GX2SetContextState(screen == TOP_SCREEN ? tv_state : drc_state); } -#endif diff --git a/src/Platform_WiiU.c b/src/wiiu/Platform_WiiU.c similarity index 95% rename from src/Platform_WiiU.c rename to src/wiiu/Platform_WiiU.c index 8230d940d..15d8193a3 100644 --- a/src/Platform_WiiU.c +++ b/src/wiiu/Platform_WiiU.c @@ -1,17 +1,15 @@ -#include "Core.h" -#if defined CC_BUILD_WIIU - #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" -#include "Audio.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" +#include "../Audio.h" + #include #include #include @@ -40,7 +38,8 @@ #include #include #include -#include "_PlatformConsole.h" + +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const cc_result ReturnCode_FileNotFound = ENOENT; @@ -476,4 +475,3 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } -#endif diff --git a/src/Window_WiiU.c b/src/wiiu/Window_WiiU.c similarity index 95% rename from src/Window_WiiU.c rename to src/wiiu/Window_WiiU.c index 99e807336..cfee1b5ee 100644 --- a/src/Window_WiiU.c +++ b/src/wiiu/Window_WiiU.c @@ -1,18 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_WIIU -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Graphics.h" -#include "Launcher.h" -#include "LBackend.h" -#include "VirtualKeyboard.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Graphics.h" +#include "../Launcher.h" +#include "../LBackend.h" +#include "../VirtualKeyboard.h" + #include #include #include @@ -488,4 +487,3 @@ void OnscreenKeyboard_SetText(const cc_string* text) { void OnscreenKeyboard_Close(void) { VirtualKeyboard_Close(); } -#endif From b0ed2e02de95e46722a598bbae227ea51aca969e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 28 Jul 2025 07:53:53 +1000 Subject: [PATCH 005/115] Linux: Use versioned libcrypto .so as default Also fix overallocating memory for 4bpp PS2 textures --- misc/n64/rsp_gpu.S | 3 +++ src/Certs.c | 2 +- src/ps2/Graphics_PS2.c | 18 +++++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/misc/n64/rsp_gpu.S b/misc/n64/rsp_gpu.S index 569918b80..1f9f2e1b0 100644 --- a/misc/n64/rsp_gpu.S +++ b/misc/n64/rsp_gpu.S @@ -294,14 +294,17 @@ GL_TnL: ssv vcspos_i.W, SCREEN_VTX_W+0, vtx2 ssv vcspos_f.W, SCREEN_VTX_W+2, vtx2 + // Perspective division vmudl v___, vcspos_f, vinvw_f.wwwwWWWW vmadm v___, vcspos_i, vinvw_f.wwwwWWWW vmadn vscreenpos_f, vcspos_f, vinvw_i.wwwwWWWW vmadh vscreenpos_i, vcspos_i, vinvw_i.wwwwWWWW + // Clip against guard planes vch v___, vguard_i, vguard_i.wwwwWWWW vcl v___, vguard_f, vguard_f.wwwwWWWW + // Viewport transform vmudn v___, vscreenpos_f, vviewscale vmadh v___, vscreenpos_i, vviewscale vmadh vscreenpos_i, vviewoff, K1 diff --git a/src/Certs.c b/src/Certs.c index 561dc6858..a9ab018f0 100644 --- a/src/Certs.c +++ b/src/Certs.c @@ -89,7 +89,7 @@ static int (*_X509_STORE_CTX_init)(X509_STORE_CTX* ctx, X509_STORE* store, #if defined CC_BUILD_WIN static const cc_string cryptoLib = String_FromConst("libcrypto.dll"); -#elif defined CC_BUILD_HAIKU +#elif defined CC_BUILD_HAIKU || defined CC_BUILD_LINUX static const cc_string cryptoLib = String_FromConst("libcrypto.so.3"); static const cc_string cryptoAlt = String_FromConst("libcrypto.so"); #else diff --git a/src/ps2/Graphics_PS2.c b/src/ps2/Graphics_PS2.c index aeb5ef898..2a6e8df33 100644 --- a/src/ps2/Graphics_PS2.c +++ b/src/ps2/Graphics_PS2.c @@ -434,15 +434,14 @@ static void ConvertTexture_Palette(cc_uint8* dst, struct Bitmap* bmp, int rowWid static int Log2Dimension(int len) { return Math_ilog2(Math_NextPowOf2(len)); } -GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; - struct GPUTexture* tex = (struct GPUTexture*)memalign(16, 32 + size); - +static void GPUTexture_Init(struct GPUTexture* tex, struct Bitmap* bmp) { tex->width = bmp->width; tex->height = bmp->height; tex->log2_w = Log2Dimension(bmp->width); tex->log2_h = Log2Dimension(bmp->height); +} +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { BitmapCol palette[MAX_PAL_4BPP_ENTRIES] QWORD_ALIGNED; int pal_count = 0; int pal_index = -1; @@ -460,6 +459,10 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, //Platform_Log4("%i, c%i (%i x %i)", &pal_index, &pal_count, &bmp->width, &bmp->height); if (pal_index >= 0) { + struct GPUTexture* tex = memalign(16, 32 + bmp->width * bmp->height); + if (!tex) return 0; + GPUTexture_Init(tex, bmp); + tex->format = GS_PSM_4; tex->pal_index = pal_index; ConvertTexture_Palette((cc_uint8*)tex->pixels, bmp, rowWidth, palette, pal_count); @@ -490,7 +493,12 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, UploadToVRAM(tex, TEXMEM_4BPP_TO_VRAM(base)); return realloc(tex, sizeof(struct GPUTexture)); } + return tex; } else { + struct GPUTexture* tex = memalign(16, 32 + bmp->width * bmp->height * 4); + if (!tex) return 0; + GPUTexture_Init(tex, bmp); + tex->format = GS_PSM_32; CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, @@ -500,8 +508,8 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, // TODO fix properly. alignup instead //int blocks = SIZE_TO_BLOCKS(size, TEXMEM_BLOCK_SIZE); size = blocks / (2048 / 64); //Platform_Log4("32BPP: b %i / p %i (%i X %i)", &size, &blocks, &bmp->width, &bmp->height); + return tex; } - return tex; } static void UpdateTextureBuffer(int context, struct GPUTexture* tex, unsigned buf_addr) { From 21c092bd8084b16b2c7b3713000abe136217cf84 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 30 Jul 2025 19:55:42 +1000 Subject: [PATCH 006/115] Make primary UI button smaller on small displays --- src/Graphics_GL1.c | 4 ++++ src/Menus.c | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 88c1fca10..01b3e6e7e 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -341,6 +341,10 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) { cc_bool enabled = !depthOnly; #ifdef CC_BUILD_SYMBIAN if (mbx) { + /* On PowerVR MBX cards, glColorMask appears to be unimplemented in hardware */ + /* and thus any usage of it significantly hurts performance. */ + /* So instead, draw with blending of 'new_RGB = current_RGB' - that way */ + /* depth buffer is updated while the colour buffer remain unchanged. */ if (depthOnly) { _glBlendFunc(GL_ZERO, GL_ONE); Gfx_SetAlphaBlending(true); diff --git a/src/Menus.c b/src/Menus.c index b867470d0..6f6b1f728 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -196,6 +196,11 @@ static int Menu_PadAxis(void* screen, struct PadAxisUpdate* upd) { } } +static void AddPrimaryButton(void* screen, struct ButtonWidget* btn, Widget_LeftClick click) { + int width = Game_ClassicMode ? 400 : (Window_Main.Width < 300 ? 200 : 400); + ButtonWidget_Add(screen, btn, width, click); +} + /*########################################################################################################################* *------------------------------------------------------Menu utilities-----------------------------------------------------* @@ -508,7 +513,7 @@ static void PauseScreenBase_ContextRecreated(struct PauseScreen* s, struct FontD static void PauseScreenBase_AddWidgets(struct PauseScreen* s, int width) { TextWidget_Add(s, &s->title); Menu_AddButtons(s, s->btns, width, s->descs, s->descsCount); - ButtonWidget_Add(s, &s->back, 400, PauseScreenBase_Game); + AddPrimaryButton(s, &s->back, PauseScreenBase_Game); } @@ -741,7 +746,7 @@ static void OptionsGroupScreen_Init(void* screen) { Menu_AddButtons(s, s->btns, 300, optsGroup_btns, 8); TextWidget_Add(s, &s->desc); - ButtonWidget_Add(s, &s->done, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->done, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1016,7 +1021,7 @@ static void EditHotkeyScreen_Init(void* screen) { } else { text = String_Empty; } TextInputWidget_Add(s, &s->input, 500, &text, &desc); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchHotkeys); + AddPrimaryButton(s, &s->cancel, Menu_SwitchHotkeys); s->input.onscreenPlaceholder = "Hotkey text"; s->maxVertices = Screen_CalcDefaultMaxVertices(s); @@ -1227,7 +1232,7 @@ static void GenLevelScreen_Init(void* screen) { TextWidget_Add(s, &s->title); ButtonWidget_Add(s, &s->flatgrass, 200, GenLevelScreen_Flatgrass); ButtonWidget_Add(s, &s->vanilla, 200, GenLevelScreen_Notchy); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1307,7 +1312,7 @@ static void ClassicGenScreen_Init(void* screen) { ButtonWidget_Add(s, &s->btns[0], 400, ClassicGenScreen_Small); ButtonWidget_Add(s, &s->btns[1], 400, ClassicGenScreen_Medium); ButtonWidget_Add(s, &s->btns[2], 400, ClassicGenScreen_Huge); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -1544,7 +1549,7 @@ static void SaveLevelScreen_Init(void* screen) { ButtonWidget_Add(s, &s->save, 400, SaveLevelScreen_Save); ButtonWidget_Add(s, &s->file, 400, SaveLevelScreen_File); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); TextInputWidget_Add(s, &s->input, 400, &World.Name, &desc); Menu_SelectWidget((struct Screen*)s, 3); /* s->input */ @@ -1927,7 +1932,7 @@ static void BindsSourceScreen_Init(void* screen) { ButtonWidget_Add(s, &s->btns[0], 300, BindsSourceScreen_ModeNormal); ButtonWidget_Add(s, &s->btns[1], 300, BindsSourceScreen_ModeGamepad); - ButtonWidget_Add(s, &s->cancel, 400, Menu_SwitchPause); + AddPrimaryButton(s, &s->cancel, Menu_SwitchPause); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -2108,7 +2113,7 @@ static void KeyBindsScreen_Init(void* screen) { TextWidget_Add(s, &s->title); TextWidget_Add(s, &s->msg); - ButtonWidget_Add(s, &s->back, 400, Gui.ClassicMenu ? Menu_SwitchClassicOptions : Menu_SwitchOptions); + AddPrimaryButton(s, &s->back, Gui.ClassicMenu ? Menu_SwitchClassicOptions : Menu_SwitchOptions); if (s->leftPage || s->rightPage) { ButtonWidget_Add(s, &s->left, 40, s->leftPage); From fae6c725ec5a29b5c07195caea0f2763b3943f96 Mon Sep 17 00:00:00 2001 From: Sean Baggaley Date: Wed, 30 Jul 2025 21:38:05 +0100 Subject: [PATCH 007/115] SDL: Set GL attributes before creating the window This is required as on some platforms the attributes are needed at window creation time. For example, EGL uses some attributes like bit depths as part of the surface (which SDL creates alongside the window), and not the context. --- src/Window_SDL2.c | 11 +++++++++-- src/Window_SDL3.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Window_SDL2.c b/src/Window_SDL2.c index 9f8d101c9..4c0b5dcbb 100644 --- a/src/Window_SDL2.c +++ b/src/Window_SDL2.c @@ -38,6 +38,8 @@ typedef struct _WINDATA { #endif +static void SetGLAttributes(); + static void RefreshWindowBounds(void) { SDL_GetWindowSize(win_handle, &Window_Main.Width, &Window_Main.Height); } @@ -99,7 +101,10 @@ static void DoCreateWindow(int width, int height, int flags) { void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } #if CC_GFX_BACKEND_IS_GL() -void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +void Window_Create3D(int width, int height) { + SetGLAttributes(); + DoCreateWindow(width, height, SDL_WINDOW_OPENGL); +} #else void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } #endif @@ -537,7 +542,7 @@ void Gamepads_Process(float delta) { #if CC_GFX_BACKEND_IS_GL() static SDL_GLContext win_ctx; -void GLContext_Create(void) { +void SetGLAttributes(void) { struct GraphicsMode mode; InitGraphicsMode(&mode); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode.R); @@ -553,7 +558,9 @@ void GLContext_Create(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif +} +void GLContext_Create(void) { win_ctx = SDL_GL_CreateContext(win_handle); if (!win_ctx) Window_SDLFail("creating OpenGL context"); } diff --git a/src/Window_SDL3.c b/src/Window_SDL3.c index 351c72610..0fd8edce9 100644 --- a/src/Window_SDL3.c +++ b/src/Window_SDL3.c @@ -11,6 +11,8 @@ static SDL_Window* win_handle; static Uint32 dlg_event; +static void SetGLAttributes(); + static void RefreshWindowBounds(void) { SDL_GetWindowSize(win_handle, &Window_Main.Width, &Window_Main.Height); } @@ -84,7 +86,10 @@ static void DoCreateWindow(int width, int height, int flags) { void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } #if CC_GFX_BACKEND_IS_GL() -void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +void Window_Create3D(int width, int height) { + SetGLAttributes(); + DoCreateWindow(width, height, SDL_WINDOW_OPENGL); +} #else void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } #endif @@ -567,7 +572,7 @@ void Gamepads_Process(float delta) { #if CC_GFX_BACKEND_IS_GL() static SDL_GLContext win_ctx; -void GLContext_Create(void) { +void SetGLAttributes(void) { struct GraphicsMode mode; InitGraphicsMode(&mode); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, mode.R); @@ -583,7 +588,9 @@ void GLContext_Create(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif +} +void GLContext_Create(void) { win_ctx = SDL_GL_CreateContext(win_handle); if (!win_ctx) Window_SDLFail("creating OpenGL context"); } From 7c326bb2a24ada5ab57662a1719669730e4fc9a8 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 1 Aug 2025 07:13:59 +1000 Subject: [PATCH 008/115] Fix TinyC compilation --- readme.md | 3 +-- third_party/bearssl/config.h | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index cecc55d86..e23955ec5 100644 --- a/readme.md +++ b/readme.md @@ -138,8 +138,7 @@ Setting up TCC: Compiling with TCC: 1. Navigate to the directory with ClassiCube's source code -2. In `ExtMath.c`, change `fabsf` to `fabs` and `sqrtf` to `sqrt` -3. Run `tcc.exe -o ClassiCube.exe src/*.c third_party/bearssl/*.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
+2. Run `tcc.exe -o ClassiCube.exe src/*.c third_party/bearssl/*.c -lwinmm -lgdi32 -luser32 -lcomdlg32 -lshell32`
(Note: You may need to specify the full path to `tcc.exe` instead of just `tcc.exe`) ## Compiling - Linux diff --git a/third_party/bearssl/config.h b/third_party/bearssl/config.h index ff6fabc40..3ef9dbf20 100644 --- a/third_party/bearssl/config.h +++ b/third_party/bearssl/config.h @@ -47,6 +47,11 @@ #define BR_USE_URANDOM 0 #define BR_USE_GETENTROPY 0 +/* intrin.h doesn't exist in older TinyC */ +#if defined __TINYC__ +#define BR_INT128 0 +#endif + /* * When BR_64 is enabled, 64-bit integer types are assumed to be * efficient (i.e. the architecture has 64-bit registers and can From ef1b8fe86df41dcda32a4db69bc4e7c18d0fba14 Mon Sep 17 00:00:00 2001 From: Shinovon Date: Mon, 4 Aug 2025 04:27:36 +0500 Subject: [PATCH 009/115] Symbian: Improve PIPS version checking --- misc/symbian/ClassiCube.pkg | 2 +- src/Platform_Symbian.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/symbian/ClassiCube.pkg b/misc/symbian/ClassiCube.pkg index d2c1e7201..8b3f46a25 100644 --- a/misc/symbian/ClassiCube.pkg +++ b/misc/symbian/ClassiCube.pkg @@ -10,7 +10,7 @@ :"ClassiCube" ; Check OpenC versions -IF( version(0x20009a80, <, 1, 5, 0) ) AND NOT (EXISTS("Z:\sys\bin\libc.dll") OR EXISTS("C:\sys\bin\libc.dll")) +IF version(0x20009a80, <, 1, 5, 0) AND NOT EXISTS("C:\sys\bin\libc.dll") "incompatible_openc.txt"-"", FT, FORCEABORT ENDIF diff --git a/src/Platform_Symbian.cpp b/src/Platform_Symbian.cpp index b43805e10..0648022fb 100644 --- a/src/Platform_Symbian.cpp +++ b/src/Platform_Symbian.cpp @@ -51,7 +51,7 @@ const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; const cc_result ReturnCode_SocketDropped = EPIPE; #define SUPPORTS_GETADDRINFO 1 -const char* Platform_AppNameSuffix = ""; +const char* Platform_AppNameSuffix = " Symbian"; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; cc_bool Platform_ReadonlyFilesystem; From d28bf267a1c4c9597e8589a2de719c46f09420b6 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 4 Aug 2025 20:57:32 +1000 Subject: [PATCH 010/115] Make linux/BSD workflows treat warnings as errors --- .github/workflows/build_freebsd.yml | 2 +- .github/workflows/build_linux.yml | 4 ++-- .github/workflows/build_netbsd.yml | 2 +- src/Entity.c | 6 +++--- src/Game.c | 2 +- src/LScreens.c | 6 +++--- src/Stream.c | 7 +++++-- src/Vectors.c | 2 +- src/saturn/Platform_Saturn.c | 1 - 9 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_freebsd.yml b/.github/workflows/build_freebsd.yml index 319808665..cd5ccaac4 100644 --- a/.github/workflows/build_freebsd.yml +++ b/.github/workflows/build_freebsd.yml @@ -43,7 +43,7 @@ jobs: env: LIBS: "-lm -lpthread -lX11 -lXi -lGL -lexecinfo" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" PLAT32_FLAGS: "-fno-pie -fcf-protection=none -I freebsd32/include -L freebsd32/lib" PLAT64_FLAGS: "-fno-pie -fcf-protection=none -I freebsd64/include -L freebsd64/lib" diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index e0ab9a074..272bea502 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -43,7 +43,7 @@ jobs: env: LIBS: "-lX11 -lXi -lpthread -lGL -lm -ldl" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" NIX32_FLAGS: "-no-pie -fno-pie -m32 -fcf-protection=none -L ./lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" @@ -107,7 +107,7 @@ jobs: env: LIBS: "-lX11 -lXi -lpthread -lGL -lm -ldl" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -fvisibility=hidden -rdynamic -Werror" NIX64_FLAGS: "-no-pie -fno-pie -m64 -fcf-protection=none -rdynamic -L ./lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" diff --git a/.github/workflows/build_netbsd.yml b/.github/workflows/build_netbsd.yml index 4d264f5cf..35e80d5c4 100644 --- a/.github/workflows/build_netbsd.yml +++ b/.github/workflows/build_netbsd.yml @@ -37,7 +37,7 @@ jobs: env: LIBS: "-lm -lpthread -lX11 -lXi -lGL -lexecinfo" SRCS: "src/*.c third_party/bearssl/*.c" - FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -Wl,-R/usr/X11R7/lib -fvisibility=hidden -rdynamic" + FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror -Wl,-R/usr/X11R7/lib -fvisibility=hidden -rdynamic -Werror" PLAT64_FLAGS: "-fno-pie -fcf-protection=none -I netbsd64/include -L netbsd64/lib -Wl,--unresolved-symbols=ignore-in-shared-libs" run: | LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" diff --git a/src/Entity.c b/src/Entity.c index 69b0a3ce7..b7125696f 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -66,15 +66,15 @@ void Entity_GetTransform(struct Entity* e, Vec3 pos, Vec3 scale, struct Matrix* struct Matrix tmp; Matrix_Scale(m, scale.x, scale.y, scale.z); - if (e->RotZ) { + if (e->RotZ != 0.0f) { Matrix_RotateZ( &tmp, -e->RotZ * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } - if (e->RotX) { + if (e->RotX != 0.0f) { Matrix_RotateX( &tmp, -e->RotX * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } - if (e->RotY) { + if (e->RotY != 0.0f) { Matrix_RotateY( &tmp, -e->RotY * MATH_DEG2RAD); Matrix_MulBy(m, &tmp); } diff --git a/src/Game.c b/src/Game.c index 4439fc26b..b51f4b613 100644 --- a/src/Game.c +++ b/src/Game.c @@ -840,7 +840,7 @@ void Game_RenderFrame(void) { if (Game_ScreenshotRequested) Game_TakeScreenshot(); Gfx_EndFrame(); - if (gfx_minFrameMs) LimitFPS(); + if (gfx_minFrameMs != 0.0f) LimitFPS(); } void Game_Free(void) { diff --git a/src/LScreens.c b/src/LScreens.c index d3dd37041..2862c2996 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -1084,9 +1084,9 @@ static void CheckResourcesScreen_Activated(struct LScreen* s_) { } static void CheckResourcesScreen_ResetArea(struct Context2D* ctx, int x, int y, int width, int height) { - int R = BitmapCol_R(Launcher_Theme.BackgroundColor) * 0.78f; /* 153 -> 120 */ - int G = BitmapCol_G(Launcher_Theme.BackgroundColor) * 0.70f; /* 127 -> 89 */ - int B = BitmapCol_B(Launcher_Theme.BackgroundColor) * 0.88f; /* 172 -> 151 */ + float R = BitmapCol_R(Launcher_Theme.BackgroundColor) * 0.78f; /* 153 -> 120 */ + float G = BitmapCol_G(Launcher_Theme.BackgroundColor) * 0.70f; /* 127 -> 89 */ + float B = BitmapCol_B(Launcher_Theme.BackgroundColor) * 0.88f; /* 172 -> 151 */ Gradient_Noise(ctx, BitmapColor_RGB(R, G, B), 4, x, y, width, height); } diff --git a/src/Stream.c b/src/Stream.c index b298cb17e..6ce8ef4bf 100644 --- a/src/Stream.c +++ b/src/Stream.c @@ -209,10 +209,13 @@ static cc_result Stream_PortionSkip(struct Stream* s, cc_uint32 count) { } static cc_result Stream_PortionPosition(struct Stream* s, cc_uint32* position) { - *position = s->meta.portion.length - s->meta.portion.left; return 0; + *position = s->meta.portion.length - s->meta.portion.left; + return 0; } + static cc_result Stream_PortionLength(struct Stream* s, cc_uint32* length) { - *length = s->meta.portion.length; return 0; + *length = s->meta.portion.length; + return 0; } void Stream_ReadonlyPortion(struct Stream* s, struct Stream* source, cc_uint32 len) { diff --git a/src/Vectors.c b/src/Vectors.c index c69baab71..142df1194 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -14,7 +14,7 @@ void Vec3_Normalise(Vec3* v) { float scale, lenSquared; lenSquared = v->x * v->x + v->y * v->y + v->z * v->z; /* handle zero vector */ - if (!lenSquared) return; + if (lenSquared == 0.0f) return; scale = 1.0f / Math_SqrtF(lenSquared); v->x = v->x * scale; diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 4c8cd4f33..627c65413 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -113,7 +113,6 @@ static void Stopwatch_Init(void) { cpu_frt_ovi_set(ovf_handler); cpu_frt_interrupt_priority_set(15); - cpu_frt_count_set(0); } From 38ef3678c690fd4921945949bd6839be9efe204f Mon Sep 17 00:00:00 2001 From: Derek <19647340+ddinan@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:52:11 +1000 Subject: [PATCH 011/115] Add PushStrength to EntityProperty --- src/Entity.c | 1 + src/Entity.h | 1 + src/EntityComponents.c | 2 +- src/Protocol.c | 6 +++++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Entity.c b/src/Entity.c index 69b0a3ce7..e9c0a649b 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -43,6 +43,7 @@ void Entity_Init(struct Entity* e) { e->Flags = ENTITY_FLAG_HAS_MODELVB; e->uScale = 1.0f; e->vScale = 1.0f; + e->PushStrength = 1.0f; e->_skinReqID = 0; e->SkinRaw[0] = '\0'; e->NameRaw[0] = '\0'; diff --git a/src/Entity.h b/src/Entity.h index 69988c798..3bff2100f 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -108,6 +108,7 @@ struct Entity { Vec3 Position; /* NOTE: Do NOT change order of yaw/pitch, this will break models in plugins */ float Pitch, Yaw, RotX, RotY, RotZ; + float PushStrength; Vec3 Velocity; struct Model* Model; diff --git a/src/EntityComponents.c b/src/EntityComponents.c index 034f6344e..cf071d8e6 100644 --- a/src/EntityComponents.c +++ b/src/EntityComponents.c @@ -1047,7 +1047,7 @@ void PhysicsComp_DoEntityPush(struct Entity* entity) { if (dist < 0.002f || dist > 1.0f) continue; /* TODO: range needs to be lower? */ Vec3_Normalise(&dir); - pushStrength = (1 - dist) / 32.0f; /* TODO: should be 24/25 */ + pushStrength = (entity->PushStrength - dist) / 32.0f; /* TODO: should be 24/25 */ /* entity.Velocity -= dir * pushStrength */ Vec3_Mul1By(&dir, pushStrength); Vec3_SubBy(&entity->Velocity, &dir); diff --git a/src/Protocol.c b/src/Protocol.c index 51d1b1495..910a8e755 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -80,7 +80,7 @@ static struct CpeExt bulkBlockUpdate_Ext = { "BulkBlockUpdate", 1 }, textColors_Ext = { "TextColors", 1 }, envMapAspect_Ext = { "EnvMapAspect", 2 }, - entityProperty_Ext = { "EntityProperty", 1 }, + entityProperty_Ext = { "EntityProperty", 2 }, extEntityPos_Ext = { "ExtEntityPositions", 1 }, twoWayPing_Ext = { "TwoWayPing", 1 }, invOrder_Ext = { "InventoryOrder", 1 }, @@ -1428,6 +1428,10 @@ static void CPE_SetEntityProperty(cc_uint8* data) { Entity_UpdateModelBounds(e); return; + case 6: + if (value < -1024.0f) value = -1024.0f; + if (value > 1024.0f) value = 1024.0f; + e->PushStrength = (float)value; return; default: return; } From 9d2b38d9722e7666d0b3ccccc2a8e3da09880d59 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 6 Aug 2025 19:02:14 +1000 Subject: [PATCH 012/115] Add dedicated min soft GPU backend Intended for slow FPU less systems like GBA/32x --- src/Core.h | 15 +- src/EnvRenderer.c | 2 + src/Graphics.h | 2 + src/Graphics_SoftGPU.c | 16 - src/Graphics_SoftMin.c | 1043 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1054 insertions(+), 24 deletions(-) create mode 100644 src/Graphics_SoftMin.c diff --git a/src/Core.h b/src/Core.h index abe4086b3..c6defa787 100644 --- a/src/Core.h +++ b/src/Core.h @@ -146,6 +146,7 @@ typedef cc_uint8 cc_bool; #define CC_GFX_BACKEND_D3D11 5 #define CC_GFX_BACKEND_VULKAN 6 #define CC_GFX_BACKEND_GL11 7 +#define CC_GFX_BACKEND_SOFTMIN 8 #define CC_SSL_BACKEND_NONE 1 #define CC_SSL_BACKEND_BEARSSL 2 @@ -490,20 +491,19 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOFPU #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI - #undef CC_BUILD_ADVLIGHTING - #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_EXTRA_MODELS - #define SOFTGPU_DISABLE_ZBUFFER #undef CC_VAR #define CC_VAR __attribute__((visibility("default"), section(".ewram"))) #undef CC_BIG_VAR #define CC_BIG_VAR __attribute__((section(".ewram"))) #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL - #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #elif defined PLAT_NDS #define CC_BUILD_NDS #define CC_BUILD_CONSOLE @@ -591,14 +591,13 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOFPU #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI - #undef CC_BUILD_ADVLIGHTING - #undef CC_BUILD_FILESYSTEM #define CC_DISABLE_EXTRA_MODELS - #define SOFTGPU_DISABLE_ZBUFFER - #define CC_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #elif defined __SYMBIAN32__ #define CC_BUILD_SYMBIAN diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index d88564504..df73d586c 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -704,6 +704,7 @@ static CC_NOINLINE void BuildMapSides(void) { struct VertexTextured* data; if (!World.Loaded) return; + /*if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return;*/ block = Env.SidesBlock; if (Blocks.Draw[block] == DRAW_GAS) return; @@ -756,6 +757,7 @@ static CC_NOINLINE void BuildMapEdges(void) { struct VertexTextured* data; if (!World.Loaded) return; + /*if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return;*/ block = Env.EdgeBlock; if (Blocks.Draw[block] == DRAW_GAS) return; diff --git a/src/Graphics.h b/src/Graphics.h index 509dc421b..81b763f26 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -103,6 +103,8 @@ CC_VAR extern struct _GfxData { #define GFX_LIMIT_MAX_VERTEX_SIZE 0x04 /* Whether the graphics backend is minimal (no fog, clouds, sky) */ #define GFX_LIMIT_MINIMAL 0x08 +/* Whether the graphics backend shouldn't have horizon/border drawn */ +#define GFX_LIMIT_WORLD_ONLY 0x10 extern const cc_string Gfx_LowPerfMessage; diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index 54c3cc413..9a591248f 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -39,14 +39,8 @@ void Gfx_FreeState(void) { } void Gfx_Create(void) { -#if defined CC_BUILD_32X || defined CC_BUILD_GBA - Gfx.MaxTexWidth = 16; - Gfx.MaxTexHeight = 16; -#else Gfx.MaxTexWidth = 4096; Gfx.MaxTexHeight = 4096; -#endif - Gfx.Created = true; Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; Gfx.Limitations = GFX_LIMIT_MINIMAL; @@ -166,10 +160,8 @@ static void ClearColorBuffer(void) { } static void ClearDepthBuffer(void) { -#ifndef SOFTGPU_DISABLE_ZBUFFER int i, size = fb_width * fb_height; for (i = 0; i < size; i++) depthBuffer[i] = 100000000.0f; -#endif } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -664,15 +656,11 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { float w = 1 / (ic0 * w0 + ic1 * w1 + ic2 * w2); float z = (ic0 * z0 + ic1 * z1 + ic2 * z2) * w; -#ifndef SOFTGPU_DISABLE_ZBUFFER if (depthTest && (z < 0 || z > depthBuffer[db_index])) continue; if (!colWrite) { if (depthWrite) depthBuffer[db_index] = z; continue; } -#else - if (!colWrite) continue; -#endif if (texturing) { float u = (ic0 * u0 + ic1 * u1 + ic2 * u2) * w; @@ -687,9 +675,7 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { } if (gfx_alphaTest && A < 0x80) continue; -#ifndef SOFTGPU_DISABLE_ZBUFFER if (depthWrite) depthBuffer[db_index] = z; -#endif int cb_index = y * cb_stride + x; if (!gfx_alphaBlend) { @@ -1084,10 +1070,8 @@ void Gfx_OnWindowResize(void) { colorBuffer = fb_bmp.scan0; cb_stride = fb_bmp.width; -#ifndef SOFTGPU_DISABLE_ZBUFFER depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); db_stride = fb_width; -#endif Gfx_SetViewport(0, 0, Game.Width, Game.Height); Gfx_SetScissor (0, 0, Game.Width, Game.Height); diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c new file mode 100644 index 000000000..a6888a812 --- /dev/null +++ b/src/Graphics_SoftMin.c @@ -0,0 +1,1043 @@ +#include "Core.h" +#if CC_GFX_BACKEND == CC_GFX_BACKEND_SOFTMIN +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" + +static cc_bool faceCulling; +static int fb_width, fb_height; +static struct Bitmap fb_bmp; +static float vp_hwidth, vp_hheight; +static int fb_maxX, fb_maxY; + +static BitmapCol* colorBuffer; +static BitmapCol clearColor; +static cc_bool colWrite = true; +static int cb_stride; + +static float* depthBuffer; +static int db_stride; + +static void* gfx_vertices; +static GfxResourceID white_square; + +void Gfx_RestoreState(void) { + InitDefaultResources(); + + // 1x1 dummy white texture + struct Bitmap bmp; + BitmapCol pixels[1] = { BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 1, 1, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + Gfx.MaxTexWidth = 16; + Gfx.MaxTexHeight = 16; + Gfx.Created = true; + Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; + Gfx.Limitations = GFX_LIMIT_MINIMAL | GFX_LIMIT_WORLD_ONLY; + + Gfx_RestoreState(); +} + +void Gfx_Free(void) { + Gfx_FreeState(); + Window_FreeFramebuffer(&fb_bmp); +} + + +typedef struct CCTexture { + int width, height; + BitmapCol pixels[]; +} CCTexture; + +static CCTexture* curTexture; +static BitmapCol* curTexPixels; +static int curTexWidth, curTexHeight; +static int texWidthMask, texHeightMask; + +void Gfx_BindTexture(GfxResourceID texId) { + if (!texId) texId = white_square; + CCTexture* tex = texId; + + curTexture = tex; + curTexPixels = tex->pixels; + curTexWidth = tex->width; + curTexHeight = tex->height; + + texWidthMask = (1 << Math_ilog2(tex->width)) - 1; + texHeightMask = (1 << Math_ilog2(tex->height)) - 1; +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { + GfxResourceID data = *texId; + if (data) Mem_Free(data); + *texId = NULL; +} + +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)Mem_Alloc(2 + bmp->width * bmp->height, 4, "Texture"); + + tex->width = bmp->width; + tex->height = bmp->height; + + CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, + bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, + bmp->width, bmp->height); + return tex; +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)texId; + BitmapCol* dst = (tex->pixels + x) + y * tex->width; + + CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, + part->scan0, rowWidth * BITMAPCOLOR_SIZE, + part->width, part->height); +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + faceCulling = enabled; +} + +static void SetAlphaTest(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaTest */ +} + +static void SetAlphaBlend(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaBlending */ +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +static void ClearColorBuffer(void) { + int i, x, y, size = fb_width * fb_height; + + if (cb_stride == fb_width) { + for (i = 0; i < size; i++) colorBuffer[i] = clearColor; + } else { + /* Slower partial buffer clear */ + for (y = 0; y < fb_height; y++) { + i = y * cb_stride; + for (x = 0; x < fb_width; x++) { + colorBuffer[i + x] = clearColor; + } + } + } +} + +void Gfx_ClearBuffers(GfxBuffers buffers) { + if (buffers & GFX_BUFFER_COLOR) ClearColorBuffer(); +} + +void Gfx_ClearColor(PackedCol color) { + int R = PackedCol_R(color); + int G = PackedCol_G(color); + int B = PackedCol_B(color); + int A = PackedCol_A(color); + + clearColor = BitmapCol_Make(R, G, B, A); +} + +void Gfx_SetDepthTest(cc_bool enabled) { +} + +void Gfx_SetDepthWrite(cc_bool enabled) { +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + colWrite = !depthOnly; +} + + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; +} + + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +static float texOffsetX, texOffsetY; +static struct Matrix _view, _proj, _mvp; + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) _view = *matrix; + if (type == MATRIX_PROJ) _proj = *matrix; + + Matrix_Mul(&_mvp, &_view, &_proj); +} + +void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { + _view = *view; + _proj = *proj; + + Matrix_Mul(mvp, view, proj); + _mvp = *mvp; +} + +void Gfx_EnableTextureOffset(float x, float y) { + texOffsetX = x; + texOffsetY = y; +} + +void Gfx_DisableTextureOffset(void) { + texOffsetX = 0; + texOffsetY = 0; +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ + /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.1f; + + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ +typedef struct Vector3 { float x, y, z; } Vector3; +typedef struct Vector2 { float x, y; } Vector2; +typedef struct Vertex_ { + float x, y, z, w; + float u, v; + PackedCol c; +} Vertex; + +static void TransformVertex2D(int index, Vertex* vertex) { + // TODO: avoid the multiply, just add down in DrawTriangles + char* ptr = (char*)gfx_vertices + index * gfx_stride; + Vector3* pos = (Vector3*)ptr; + vertex->x = pos->x; + vertex->y = pos->y; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v = (struct VertexColoured*)ptr; + vertex->u = 0.0f; + vertex->v = 0.0f; + vertex->c = v->Col; + } else { + struct VertexTextured* v = (struct VertexTextured*)ptr; + vertex->u = v->U; + vertex->v = v->V; + vertex->c = v->Col; + } +} + +static int TransformVertex3D(int index, Vertex* vertex) { + // TODO: avoid the multiply, just add down in DrawTriangles + char* ptr = (char*)gfx_vertices + index * gfx_stride; + Vector3* pos = (Vector3*)ptr; + + vertex->x = pos->x * _mvp.row1.x + pos->y * _mvp.row2.x + pos->z * _mvp.row3.x + _mvp.row4.x; + vertex->y = pos->x * _mvp.row1.y + pos->y * _mvp.row2.y + pos->z * _mvp.row3.y + _mvp.row4.y; + vertex->z = pos->x * _mvp.row1.z + pos->y * _mvp.row2.z + pos->z * _mvp.row3.z + _mvp.row4.z; + vertex->w = pos->x * _mvp.row1.w + pos->y * _mvp.row2.w + pos->z * _mvp.row3.w + _mvp.row4.w; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v = (struct VertexColoured*)ptr; + vertex->u = 0.0f; + vertex->v = 0.0f; + vertex->c = v->Col; + } else { + struct VertexTextured* v = (struct VertexTextured*)ptr; + vertex->u = (v->U + texOffsetX); + vertex->v = (v->V + texOffsetY); + vertex->c = v->Col; + } + return vertex->z >= 0.0f; +} + +static void ViewportVertex3D(Vertex* vertex) { + float invW = 1.0f / vertex->w; + + vertex->x = vp_hwidth * (1 + vertex->x * invW); + vertex->y = vp_hheight * (1 - vertex->y * invW); + vertex->z = vertex->z * invW; + vertex->w = invW; +} + +static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2) { + PackedCol vColor = V0->c; + int minX = (int)V0->x; + int minY = (int)V0->y; + int maxX = (int)V1->x; + int maxY = (int)V2->y; + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + int begTX = (int)(V0->u * curTexWidth); + int begTY = (int)(V0->v * curTexHeight); + int delTX = (int)(V1->u * curTexWidth) - begTX; + int delTY = (int)(V2->v * curTexHeight) - begTY; + + int width = maxX - minX, height = maxY - minY; + + int fast = delTX == width && delTY == height && + (begTX + delTX < curTexWidth ) && + (begTY + delTY < curTexHeight); + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int x, y; + for (y = minY; y <= maxY; y++) + { + int texY = fast ? (begTY + (y - minY)) : (((begTY + delTY * (y - minY) / height)) & texHeightMask); + for (x = minX; x <= maxX; x++) + { + int texX = fast ? (begTX + (x - minX)) : (((begTX + delTX * (x - minX) / width)) & texWidthMask); + int texIndex = texY * curTexWidth + texX; + + BitmapCol color = curTexPixels[texIndex]; + int R, G, B, A; + + A = BitmapCol_A(color); + if (gfx_alphaBlend && A == 0) continue; + int cb_index = y * cb_stride + x; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = BitmapCol_R(color); + G = BitmapCol_G(color); + B = BitmapCol_B(color); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + color = BitmapCol_Make(R, G, B, 0xFF); + } + + if (vColor != PACKEDCOL_WHITE) { + int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(color); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(vColor), g2 = BitmapCol_G(color); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(vColor), b2 = BitmapCol_B(color); + B = ( b1 * b2 ) >> 8; + + color = BitmapCol_Make(R, G, B, 0xFF); + } + + colorBuffer[cb_index] = color; + } + } +} + +#define edgeFunction(ax,ay, bx,by, cx,cy) (((bx) - (ax)) * ((cy) - (ay)) - ((by) - (ay)) * ((cx) - (ax))) + +static void DrawTriangle2D(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + float u0 = V0->u * curTexWidth, u1 = V1->u * curTexWidth, u2 = V2->u * curTexWidth; + float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight, v2 = V2->v * curTexHeight; + PackedCol color = V0->c; + + int area = edgeFunction(x0,y0, x1,y1, x2,y2); + float factor = 1.0f / area; + int x, y; + + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); + float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); + float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + float bc0 = bc0_start; + float bc1 = bc1_start; + float bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + float ic0 = bc0 * factor; + float ic1 = bc1 * factor; + float ic2 = bc2 * factor; + + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + int cb_index = y * cb_stride + x; + + int R, G, B, A; + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + float u = ic0 * u0 + ic1 * u1 + ic2 * u2; + float v = ic0 * v0 + ic1 * v1 + ic2 * v2; + int texX = ((int)u) & texWidthMask; + int texY = ((int)v) & texHeightMask; + int texIndex = texY * curTexWidth + texX; + + BitmapCol tColor = curTexPixels[texIndex]; + int a1 = PackedCol_A(color), a2 = BitmapCol_A(tColor); + A = ( a1 * a2 ) >> 8; + int r1 = PackedCol_R(color), r2 = BitmapCol_R(tColor); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(color), g2 = BitmapCol_G(tColor); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(color), b2 = BitmapCol_B(tColor); + B = ( b1 * b2 ) >> 8; + } else { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } + + if (gfx_alphaTest && A < 0x80) continue; + if (gfx_alphaBlend && A == 0) continue; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + } + + colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); + } + } +} + +#define MultiplyColors(vColor, tColor) \ + a1 = PackedCol_A(vColor); \ + a2 = BitmapCol_A(tColor); \ + A = ( a1 * a2 ) >> 8; \ +\ + r1 = PackedCol_R(vColor); \ + r2 = BitmapCol_R(tColor); \ + R = ( r1 * r2 ) >> 8; \ +\ + g1 = PackedCol_G(vColor); \ + g2 = BitmapCol_G(tColor); \ + G = ( g1 * g2 ) >> 8; \ +\ + b1 = PackedCol_B(vColor); \ + b2 = BitmapCol_B(tColor); \ + B = ( b1 * b2 ) >> 8; \ + +static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + int area = edgeFunction(x0,y0, x1,y1, x2,y2); + if (faceCulling) { + // https://gamedev.stackexchange.com/questions/203694/how-to-make-backface-culling-work-correctly-in-both-orthographic-and-perspective + if (area < 0) return; + } + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + // NOTE: W in frag variables below is actually 1/W + float factor = 1.0f / area; + float w0 = V0->w, w1 = V1->w, w2 = V2->w; + + // TODO proper clipping + if (w0 <= 0 || w1 <= 0 || w2 <= 0) { + return; + } + + float z0 = V0->z, z1 = V1->z, z2 = V2->z; + PackedCol color = V0->c; + + float u0 = V0->u * curTexWidth, u1 = V1->u * curTexWidth, u2 = V2->u * curTexWidth; + float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight, v2 = V2->v * curTexHeight; + + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); + float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); + float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; + + if (!texturing) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else { + /* Always use a single pixel */ + float rawY0 = v0; + float rawY1 = v1; + + float rawY = min(rawY0, rawY1); + int texY = (int)(rawY + 0.01f) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + texturing = false; + } + + if (!colWrite) return; + if (gfx_alphaTest && A < 0x80) return; + color = BitmapCol_Make(R, G, B, 0xFF); + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + float bc0 = bc0_start; + float bc1 = bc1_start; + float bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + float ic0 = bc0 * factor; + float ic1 = bc1 * factor; + float ic2 = bc2 * factor; + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = color; + continue; + } + + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + int finR = (R * A + dstR * (255 - A)) >> 8; + int finG = (G * A + dstG * (255 - A)) >> 8; + int finB = (B * A + dstB * (255 - A)) >> 8; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } +} + +#define V0_VIS (1 << 0) +#define V1_VIS (1 << 1) +#define V2_VIS (1 << 2) +#define V3_VIS (1 << 3) + +// https://github.com/behindthepixels/EDXRaster/blob/master/EDXRaster/Core/Clipper.h +static void ClipLine(Vertex* v1, Vertex* v2, Vertex* V) { + float t = Math_AbsF(v1->z / (v2->z - v1->z)); + float invt = 1.0f - t; + + V->x = invt * v1->x + t * v2->x; + V->y = invt * v1->y + t * v2->y; + //V->z = invt * v1->z + t * v2->z; + V->z = 0.0f; // clipped against near plane anyways (I.e Z/W = 0 --> Z = 0) + V->w = invt * v1->w + t * v2->w; + + V->u = invt * v1->u + t * v2->u; + V->v = invt * v1->v + t * v2->v; + V->c = v1->c; +} + +// https://casual-effects.com/research/McGuire2011Clipping/clip.glsl +static void DrawClipped(int mask, Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) { + Vertex tmp[2]; + Vertex* a = &tmp[0]; + Vertex* b = &tmp[1]; + + switch (mask) { + case V0_VIS: + { + // v0 + // / | + // / | + // .....A....B... + // / | + // v3--v2---v1 + ClipLine(v3, v0, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v0); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v0, a, b); + } + break; + case V1_VIS: + { + // v1 + // / | + // / | + // ....A.....B... + // / | + // v0--v3---v2 + ClipLine(v0, v1, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v1); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, b, v1); + } break; + case V2_VIS: + { + // v2 + // / | + // / | + // ....A.....B... + // / | + // v1--v0---v3 + ClipLine(v1, v2, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, b, v2); + } break; + case V3_VIS: + { + // v3 + // / | + // / | + // ....A.....B... + // / | + // v2--v1---v0 + ClipLine(v2, v3, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(b, v3, a); + } + break; + case V0_VIS | V1_VIS: + { + // v0-----------v1 + // \ | + // ...B.........A... + // \ | + // v3-----v2 + ClipLine(v1, v2, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, v0, a); + DrawTriangle3D(a, v0, b); + } break; + // case V0_VIS | V2_VIS: degenerate case that should never happen + case V0_VIS | V3_VIS: + { + // v3-----------v0 + // \ | + // ...B.........A... + // \ | + // v2-----v1 + ClipLine(v0, v1, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(a, v0, b); + DrawTriangle3D(b, v0, v3); + } break; + case V1_VIS | V2_VIS: + { + // v1-----------v2 + // \ | + // ...B.........A... + // \ | + // v0-----v3 + ClipLine(v2, v3, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, b, v2); + DrawTriangle3D(v2, b, a); + } break; + // case V1_VIS | V3_VIS: degenerate case that should never happen + case V2_VIS | V3_VIS: + { + // v2-----------v3 + // \ | + // ...B.........A... + // \ | + // v1-----v0 + ClipLine(v3, v0, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D( b, a, v2); + DrawTriangle3D(v2, a, v3); + } break; + case V0_VIS | V1_VIS | V2_VIS: + { + // --v1-- + // v0-- --v2 + // \ / + // ....B.....A... + // \ / + // v3 + // v1,v2,v0 v2,v0,A v0,A,B + ClipLine(v2, v3, a); + ClipLine(v3, v0, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v1, v0, v2); + DrawTriangle3D(v2, v0, a); + DrawTriangle3D(v0, b, a); + } break; + case V0_VIS | V1_VIS | V3_VIS: + { + // --v0-- + // v3-- --v1 + // \ / + // ....B.....A... + // \ / + // v2 + // v0,v1,v3 v1,v3,A v3,A,B + ClipLine(v1, v2, a); + ClipLine(v2, v3, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v1); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v0, v3, v1); + DrawTriangle3D(v1, v3, a); + DrawTriangle3D(v3, b, a); + } break; + case V0_VIS | V2_VIS | V3_VIS: + { + // --v3-- + // v2-- --v0 + // \ / + // ....B.....A... + // \ / + // v1 + // v3,v0,v2 v0,v2,A v2,A,B + ClipLine(v0, v1, a); + ClipLine(v1, v2, b); + + ViewportVertex3D(v0); + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v3, v2, v0); + DrawTriangle3D(v0, v2, a); + DrawTriangle3D(v2, b, a); + } break; + case V1_VIS | V2_VIS | V3_VIS: + { + // --v2-- + // v1-- --v3 + // \ / + // ....B.....A... + // \ / + // v0 + // v2,v3,v1 v3,v1,A v1,A,B + ClipLine(v3, v0, a); + ClipLine(v0, v1, b); + + ViewportVertex3D(v1); + ViewportVertex3D(v2); + ViewportVertex3D(v3); + ViewportVertex3D(a); + ViewportVertex3D(b); + + DrawTriangle3D(v2, v1, v3); + DrawTriangle3D(v3, v1, a); + DrawTriangle3D(v1, b, a); + } break; + } +} + +void DrawQuads(int startVertex, int verticesCount, DrawHints hints) { + Vertex vertices[4]; + int i, j = startVertex; + + if (gfx_rendering2D && (hints & (DRAW_HINT_SPRITE|DRAW_HINT_RECT))) { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + + DrawSprite2D(&vertices[0], &vertices[1], &vertices[2]); + } + } else if (gfx_rendering2D) { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + TransformVertex2D(j + 3, &vertices[3]); + + DrawTriangle2D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); + } + } else { + // 4 vertices = 1 quad = 2 triangles + for (i = 0; i < verticesCount / 4; i++, j += 4) + { + int clip = TransformVertex3D(j + 0, &vertices[0]) << 0 + | TransformVertex3D(j + 1, &vertices[1]) << 1 + | TransformVertex3D(j + 2, &vertices[2]) << 2 + | TransformVertex3D(j + 3, &vertices[3]) << 3; + + if (clip == 0) { + // Quad entirely clipped + } else if (clip == 0x0F) { + // Quad entirely visible + ViewportVertex3D(&vertices[0]); + ViewportVertex3D(&vertices[1]); + ViewportVertex3D(&vertices[2]); + ViewportVertex3D(&vertices[3]); + + DrawTriangle3D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle3D(&vertices[2], &vertices[0], &vertices[3]); + } else { + // Quad partially visible + DrawClipped(clip, &vertices[0], &vertices[1], &vertices[2], &vertices[3]); + } + } + } +} + +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { } /* TODO */ + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { + DrawQuads(startVertex, verticesCount, hints); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + DrawQuads(0, verticesCount, DRAW_HINT_NONE); +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawQuads(startVertex, verticesCount, DRAW_HINT_NONE); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +static BitmapCol* CB_GetRow(struct Bitmap* bmp, int y, void* ctx) { + return colorBuffer + cb_stride * y; +} + +cc_result Gfx_TakeScreenshot(struct Stream* output) { + struct Bitmap bmp; + Bitmap_Init(bmp, fb_width, fb_height, NULL); + return Png_Encode(&bmp, output, CB_GetRow, false, NULL); +} + +cc_bool Gfx_WarnIfNecessary(void) { return false; } +cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } + +void Gfx_BeginFrame(void) { } + +void Gfx_EndFrame(void) { + Rect2D r = { 0, 0, fb_width, fb_height }; + Window_DrawFramebuffer(r, &fb_bmp); +} + +void Gfx_SetVSync(cc_bool vsync) { + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + // TODO ?????? + //Window_FreeFramebuffer(&fb_bmp); + + fb_width = Game.Width; + fb_height = Game.Height; + + Window_AllocFramebuffer(&fb_bmp, Game.Width, Game.Height); + colorBuffer = fb_bmp.scan0; + cb_stride = fb_bmp.width; + + Gfx_SetViewport(0, 0, Game.Width, Game.Height); + Gfx_SetScissor (0, 0, Game.Width, Game.Height); +} + +void Gfx_SetViewport(int x, int y, int w, int h) { + vp_hwidth = w / 2.0f; + vp_hheight = h / 2.0f; +} + +void Gfx_SetScissor (int x, int y, int w, int h) { + /* TODO minX/Y */ + fb_maxX = x + w - 1; + fb_maxY = y + h - 1; +} + +void Gfx_GetApiInfo(cc_string* info) { + String_AppendConst(info, "-- Using software --\n"); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif From 529341fd7d3e6e609dbc38c4458a324deb65624c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 7 Aug 2025 07:25:39 +1000 Subject: [PATCH 013/115] Dreamcast: Use blind dialling, partially addresses #1409 --- Makefile | 12 ++++++------ src/dreamcast/Platform_Dreamcast.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index e48ba190a..b7bf9acd4 100644 --- a/Makefile +++ b/Makefile @@ -185,15 +185,15 @@ ifeq ($(PLAT),dos) endif -ifdef SDL2 +ifdef BUILD_SDL2 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 LIBS += -lSDL2 endif -ifdef SDL3 +ifdef BUILD_SDL3 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL3 LIBS += -lSDL3 endif -ifdef TERMINAL +ifdef BUILD_TERMINAL CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_TERMINAL -DCC_GFX_BACKEND=CC_GFX_BACKEND_SOFTGPU LIBS := $(subst mwindows,mconsole,$(LIBS)) endif @@ -246,11 +246,11 @@ dos: $(MAKE) $(TARGET) PLAT=dos # Default overrides sdl2: - $(MAKE) $(TARGET) SDL2=1 + $(MAKE) $(TARGET) BUILD_SDL2=1 sdl3: - $(MAKE) $(TARGET) SDL3=1 + $(MAKE) $(TARGET) BUILD_SDL3=1 terminal: - $(MAKE) $(TARGET) TERMINAL=1 + $(MAKE) $(TARGET) BUILD_TERMINAL=1 release: $(MAKE) $(TARGET) RELEASE=1 diff --git a/src/dreamcast/Platform_Dreamcast.c b/src/dreamcast/Platform_Dreamcast.c index f0ff07410..ffe86c437 100644 --- a/src/dreamcast/Platform_Dreamcast.c +++ b/src/dreamcast/Platform_Dreamcast.c @@ -692,7 +692,7 @@ static void InitModem(void) { ppp_init(); Platform_LogConst("Dialling modem.. (can take ~20 seconds)"); - err = ppp_modem_init("111111111111", 0, NULL); + err = ppp_modem_init("111111111111", 1, NULL); if (err) { Platform_Log1("Establishing link failed (%i)", &err); return; } From 2d32791f3528418077c86f1dee51126d0feaab60 Mon Sep 17 00:00:00 2001 From: Goodlyay Date: Thu, 7 Aug 2025 03:03:12 -0700 Subject: [PATCH 014/115] Fix wrong entity PushStrength field being used, make network value fixed-point decimal --- src/Entity.h | 4 +++- src/EntityComponents.c | 2 +- src/Protocol.c | 8 +++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Entity.h b/src/Entity.h index 3bff2100f..9248b924d 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -107,8 +107,8 @@ struct Entity { const struct EntityVTABLE* VTABLE; Vec3 Position; /* NOTE: Do NOT change order of yaw/pitch, this will break models in plugins */ + /* When adding a new field to structs that plugins can access, add them to the end to avoid breaking compatibility. */ float Pitch, Yaw, RotX, RotY, RotZ; - float PushStrength; Vec3 Velocity; struct Model* Model; @@ -134,6 +134,8 @@ struct Entity { /* Current state is linearly interpolated between prev and next */ struct EntityLocation prev, next; GfxResourceID ModelVB; + + float PushStrength; }; typedef cc_bool (*Entity_TouchesCondition)(BlockID block); diff --git a/src/EntityComponents.c b/src/EntityComponents.c index cf071d8e6..12e7b309c 100644 --- a/src/EntityComponents.c +++ b/src/EntityComponents.c @@ -1047,7 +1047,7 @@ void PhysicsComp_DoEntityPush(struct Entity* entity) { if (dist < 0.002f || dist > 1.0f) continue; /* TODO: range needs to be lower? */ Vec3_Normalise(&dir); - pushStrength = (entity->PushStrength - dist) / 32.0f; /* TODO: should be 24/25 */ + pushStrength = (other->PushStrength - dist) / 32.0f; /* TODO: should be 24/25 */ /* entity.Velocity -= dir * pushStrength */ Vec3_Mul1By(&dir, pushStrength); Vec3_SubBy(&entity->Velocity, &dir); diff --git a/src/Protocol.c b/src/Protocol.c index 910a8e755..0d1e73810 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -1429,9 +1429,11 @@ static void CPE_SetEntityProperty(cc_uint8* data) { Entity_UpdateModelBounds(e); return; case 6: - if (value < -1024.0f) value = -1024.0f; - if (value > 1024.0f) value = 1024.0f; - e->PushStrength = (float)value; return; + scale = value / 1000.0f; + if (scale < -1024.0f) scale = -1024.0f; + if (scale > 1024.0f) scale = 1024.0f; + e->PushStrength = scale; + return; default: return; } From c91641b5cdac65d4c2959d998e596214a279f424 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 9 Aug 2025 21:09:10 +1000 Subject: [PATCH 015/115] Tidy up timer code a little bit --- src/Platform_NDS.c | 39 ++++++++++++++++++++++++++++++++---- src/Window_Terminal.c | 6 +++--- src/gba/Platform_GBA.c | 5 +++-- src/saturn/Platform_Saturn.c | 15 +++++++++----- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index a9a10dffd..6a3f86bdd 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -56,8 +56,25 @@ cc_bool Platform_ReadonlyFilesystem; /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ -static u32 last_raw; -static u64 base_time; +static uint32_t last_raw; +static uint64_t base_time; + +static uint32_t GetTimerValues(void) { + uint16_t lo = TIMER_DATA(0); + uint16_t hi = TIMER_DATA(1); + + // Lo timer can possibly overflow between reading lo and hi + uint16_t lo_again = TIMER_DATA(0); + uint16_t hi_again = TIMER_DATA(1); + + // Check if lo timer has overflowed + if (lo_again < lo) { + // If so, use known stable timer read values instead + lo = lo_again; + hi = hi_again; + } + return lo | (hi << 16); +} cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; @@ -66,7 +83,7 @@ cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { } cc_uint64 Stopwatch_Measure(void) { - u32 raw = cpuGetTiming(); + uint32_t raw = GetTimerValues(); // Since counter is only a 32 bit integer, it overflows after a minute or two if (last_raw > 0xF0000000 && raw < 0x10000000) { base_time += 0x100000000ULL; @@ -76,6 +93,20 @@ cc_uint64 Stopwatch_Measure(void) { return base_time + raw; } +static void Stopwatch_Init(void) { + // Turn off both timers + TIMER_CR(0) = 0; + TIMER_CR(1) = 0; + + // Reset timer values to 0 + TIMER_DATA(0) = 0; + TIMER_DATA(1) = 0; + + // Turn on timer 1, with timer 1 incrementing timer 0 on overflow + TIMER_CR(1) = TIMER_CASCADE | TIMER_ENABLE; + TIMER_CR(0) = TIMER_ENABLE; +} + static void LogNocash(const char* msg, int len) { // Can only be up to 120 bytes total char buffer[120]; @@ -588,7 +619,7 @@ void Platform_Init(void) { InitFilesystem(); InitNetworking(); - cpuStartTiming(1); + Stopwatch_Init(); } void Platform_Free(void) { } diff --git a/src/Window_Terminal.c b/src/Window_Terminal.c index af370828e..1ede3c179 100644 --- a/src/Window_Terminal.c +++ b/src/Window_Terminal.c @@ -34,7 +34,7 @@ #define OutputConsole(buf, len) WriteConsoleA(hStdout, buf, len, NULL, NULL) #define BOX_CHAR "\xE2\x96\x84" #else - #define OutputConsole(buf, len) write(STDOUT_FILENO, buf, len) + #define OutputConsole(buf, len) !!write(STDOUT_FILENO, buf, len) #define BOX_CHAR "\xE2\x96\x84" #endif @@ -146,7 +146,7 @@ static void HookTerminal(void) { tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Normal-tracking-mode - OutputConst(DEC_PM_SET("1049")); // Use Normal Screen Buffer and restore cursor as in DECRC, xterm. + OutputConst(DEC_PM_SET("1049")); OutputConst(CSI "0m"); OutputConst(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. OutputConst(DEC_PM_SET("1003")); // Ps = 1 0 0 3 ⇒ Use All Motion Mouse Tracking, xterm. See @@ -161,7 +161,7 @@ static void UnhookTerminal(void) { //ioctl(STDIN_FILENO, KDSKBMODE, orig_KB); tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); - OutputConst(DEC_PM_RESET("1049")); + OutputConst(DEC_PM_RESET("1049")); // Return to Normal Screen Buffer and restore cursor OutputConst(CSI "0m"); OutputConst(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. OutputConst(DEC_PM_SET("25")); diff --git a/src/gba/Platform_GBA.c b/src/gba/Platform_GBA.c index 8e20f8c22..ec3118236 100644 --- a/src/gba/Platform_GBA.c +++ b/src/gba/Platform_GBA.c @@ -70,12 +70,13 @@ static uint32_t GetTimerValues(void) { uint16_t lo = REG_TMR2_DATA; uint16_t hi = REG_TMR3_DATA; - // Did lo timer possibly overflow between reading lo and hi? + // Lo timer can possibly overflow between reading lo and hi uint16_t lo_again = REG_TMR2_DATA; uint16_t hi_again = REG_TMR3_DATA; + // Check if lo timer has overflowed if (lo_again < lo) { - // If so, use known safe timer read values instead + // If so, use known stable timer read values instead lo = lo_again; hi = hi_again; } diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 627c65413..f555f85fc 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -91,10 +91,13 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -static volatile cc_uint32 overflow_count; +static volatile cc_uint32 overflow_count, wdt_overflows; + +static void wdt_handler(void) { wdt_overflows++; } +static void ovf_handler(void) { overflow_count++; } cc_uint64 Stopwatch_Measure(void) { - return cpu_frt_count_get() + (overflow_count * 65536); + return cpu_frt_count_get() | (overflow_count << 16); } cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { @@ -105,14 +108,16 @@ cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { return (delta * 1000) / CPU_FRT_NTSC_320_128_COUNT_1MS; } -static void ovf_handler(void) { overflow_count++; } - static void Stopwatch_Init(void) { //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); cpu_frt_init(CPU_FRT_CLOCK_DIV_128); cpu_frt_ovi_set(ovf_handler); - cpu_frt_interrupt_priority_set(15); + + //pu_wdt_init(CPU_WDT_CLOCK_DIV_4096); + //cpu_wdt_interrupt_priority_set(15); + //cpu_wdt_timer_mode_set(CPU_WDT_MODE_INTERVAL, wdt_handler); + //cpu_wdt_enable(); } From fa8ab487a1642990ed0f657b76e0d903b4183d4b Mon Sep 17 00:00:00 2001 From: Caleb Butler Date: Sat, 9 Aug 2025 12:43:32 -0400 Subject: [PATCH 016/115] Fix instructions for MSVC command-line build --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index e23955ec5..f90a13443 100644 --- a/readme.md +++ b/readme.md @@ -110,7 +110,7 @@ If you get a `The Windows SDK version 5.1 was not found` compilation error, [see ##### Using Visual Studio (command line) 1. Use 'Developer Tools for Visual Studio' from Start Menu 2. Navigate to the directory with ClassiCube's source code -3. Run `cl.exe *.c /link user32.lib gdi32.lib winmm.lib dbghelp.lib shell32.lib comdlg32.lib /out:ClassiCube.exe` +3. Run `cl.exe src\*.c third_party\bearssl\*.c /link user32.lib gdi32.lib winmm.lib dbghelp.lib shell32.lib comdlg32.lib /out:ClassiCube.exe` ##### Using MinGW-w64 Assuming that you used the installer from https://sourceforge.net/projects/mingw-w64/ : From af20525b187afe0dd3143f6236eb5507d7d0c3b2 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 13 Aug 2025 21:12:46 +1000 Subject: [PATCH 017/115] Fix buffer overflow if a plugin calls Chat_Add multiple times with very long messages that have URLs in them (Thanks SpiralP) --- src/Widgets.c | 4 ++++ src/saturn/Platform_Saturn.c | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Widgets.c b/src/Widgets.c index 2580df3a5..2bd1ae496 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -2184,6 +2184,10 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta for (i = 0; i < w->lines; i++) { line = TextGroupWidget_UNSAFE_Get(w, i); + /* TODO properly fix this buffer overflow if multiple lines */ + /* of max chat length are added by a plugin and have URLs */ + line.length = min(line.length, TEXTGROUPWIDGET_LEN); + begs[i] = -1; ends[i] = -1; if (!line.length) continue; diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index f555f85fc..6222e020c 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -100,12 +100,15 @@ cc_uint64 Stopwatch_Measure(void) { return cpu_frt_count_get() | (overflow_count << 16); } +#define US_PER_SEC 1000000 +#define NTSC_320_CLOCK 26846588 + cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - cc_uint32 delta = end - beg; + cc_uint64 delta = end - beg; - // TODO still wrong?? and overflows?? and PAL detection ??? - return (delta * 1000) / CPU_FRT_NTSC_320_128_COUNT_1MS; + // TODO still wrong?? PAL detection ??? + return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 128); } static void Stopwatch_Init(void) { @@ -114,7 +117,7 @@ static void Stopwatch_Init(void) { cpu_frt_ovi_set(ovf_handler); cpu_frt_interrupt_priority_set(15); - //pu_wdt_init(CPU_WDT_CLOCK_DIV_4096); + //cpu_wdt_init(CPU_WDT_CLOCK_DIV_4096); //cpu_wdt_interrupt_priority_set(15); //cpu_wdt_timer_mode_set(CPU_WDT_MODE_INTERVAL, wdt_handler); //cpu_wdt_enable(); From 9c9626b502a39792eabdc84a12cac3e0617c3038 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 15 Aug 2025 07:03:24 +1000 Subject: [PATCH 018/115] Saturn: Use WDT for measuring elapsed time --- src/saturn/Platform_Saturn.c | 31 +++++++-------- src/saturn/sh2_wdt.h | 73 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 src/saturn/sh2_wdt.h diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 6222e020c..2d386155a 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -91,36 +91,31 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -static volatile cc_uint32 overflow_count, wdt_overflows; +#include "sh2_wdt.h" -static void wdt_handler(void) { wdt_overflows++; } -static void ovf_handler(void) { overflow_count++; } +static void Stopwatch_Init(void) { + wdt_stop(); + + wdt_set_irq_number(CPU_INTC_INTERRUPT_WDT_ITI); + wdt_set_irq_priority(15); + cpu_intc_ihr_set(CPU_INTC_INTERRUPT_WDT_ITI, wdt_handler); + + wdt_enable(); +} cc_uint64 Stopwatch_Measure(void) { - return cpu_frt_count_get() | (overflow_count << 16); + return wdt_total_ticks(); } #define US_PER_SEC 1000000 -#define NTSC_320_CLOCK 26846588 +#define NTSC_320_CLOCK 26846587 cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; cc_uint64 delta = end - beg; // TODO still wrong?? PAL detection ??? - return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 128); -} - -static void Stopwatch_Init(void) { - //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); - cpu_frt_init(CPU_FRT_CLOCK_DIV_128); - cpu_frt_ovi_set(ovf_handler); - cpu_frt_interrupt_priority_set(15); - - //cpu_wdt_init(CPU_WDT_CLOCK_DIV_4096); - //cpu_wdt_interrupt_priority_set(15); - //cpu_wdt_timer_mode_set(CPU_WDT_MODE_INTERVAL, wdt_handler); - //cpu_wdt_enable(); + return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 1024); } diff --git a/src/saturn/sh2_wdt.h b/src/saturn/sh2_wdt.h new file mode 100644 index 000000000..ed792bb30 --- /dev/null +++ b/src/saturn/sh2_wdt.h @@ -0,0 +1,73 @@ +static cc_uint32 wdt_overflows; + +// Interrupt Priority Request A +#define SH2_REG_IPRA ((volatile uint16_t *)0xFFFFFEE2) +#define SH2_IPRA_WDT_NUM 4 + +// Vector Number Setting Register WDT +#define SH2_REG_VCRWDT ((volatile uint16_t *)0xFFFFFEE4) +#define SH2_VCRWDT_NUM 8 + +// Watchdog Timer Counter +#define SH2_REG_WTCNT_R ((volatile uint8_t *)0xFFFFFE81) +#define SH2_REG_WTCNT_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCNT(val) (0x5A00 | (uint8_t)(val)) + +// Watchdog Timer Control/Status Register +#define SH2_REG_WTCSR_R ((volatile uint8_t *)0xFFFFFE80) +#define SH2_REG_WTCSR_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCSR(val) (0xA500 | (uint8_t)(val)) + +#define SH2_WTCSR_CLOCK_DIV_2 0 +#define SH2_WTCSR_CLOCK_DIV_64 1 +#define SH2_WTCSR_CLOCK_DIV_128 2 +#define SH2_WTCSR_CLOCK_DIV_256 3 +#define SH2_WTCSR_CLOCK_DIV_512 4 +#define SH2_WTCSR_CLOCK_DIV_1024 5 +#define SH2_WTCSR_CLOCK_DIV_4096 6 +#define SH2_WTCSR_CLOCK_DIV_8192 7 + +#define SH2_WTCSR_ENA_FLG 0x20 +#define SH2_WTCSR_OVF_FLG 0x80 + + +static CC_INLINE void wdt_set_irq_number(int irq_num) { + uint16_t vcrwdt = *SH2_REG_VCRWDT; + vcrwdt &= ~( 0x7F << SH2_VCRWDT_NUM); + vcrwdt |= (irq_num << SH2_VCRWDT_NUM); + + *SH2_REG_VCRWDT = vcrwdt; +} + +static CC_INLINE void wdt_set_irq_priority(uint8_t pri) { + uint16_t ipra = *SH2_REG_IPRA; + ipra &= ~(0xF << SH2_IPRA_WDT_NUM); + ipra |= (pri << SH2_IPRA_WDT_NUM); + + *SH2_REG_IPRA = ipra; +} + + +static void __interrupt_handler wdt_handler(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); + wdt_overflows++; +} + +static CC_INLINE void wdt_stop(void) { + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(SH2_WTCSR_CLOCK_DIV_1024); +} + +static CC_INLINE void wdt_enable(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + wtcr |= SH2_WTCSR_ENA_FLG; + // interval mode is 0 anyways + + *SH2_REG_WTCNT_W = SH2_CMD_WTCNT(0); + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); +} + +static CC_INLINE uint32_t wdt_total_ticks(void) { + return (*SH2_REG_WTCNT_R) | (wdt_overflows << 8); +} From ef1decc6adb8ad29934d8d4d70833df8a7d82d52 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 15 Aug 2025 07:45:45 +1000 Subject: [PATCH 019/115] 32x: Non working WDT timer for measuring elapsed time --- .github/workflows/build_saturn.yml | 2 + misc/32x/32x.h | 1 - misc/32x/sh2_crt0.s | 101 ++++------------------------- src/32x/Platform_32x.c | 25 ++++++- src/saturn/sh2_wdt.h | 2 +- 5 files changed, 38 insertions(+), 93 deletions(-) diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index dba9c85b2..55e287f59 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -21,6 +21,8 @@ jobs: - uses: actions/checkout@v4 - name: Install prerequisites run: | + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6ED0E7B82643E131 + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 78DBA3BC47EF2265 apt-get update apt-get -y install curl diff --git a/misc/32x/32x.h b/misc/32x/32x.h index 1d45a3f3d..faad402cd 100644 --- a/misc/32x/32x.h +++ b/misc/32x/32x.h @@ -122,7 +122,6 @@ extern "C" { extern void fast_memcpy(void *dst, void *src, int len); extern void CacheControl(int mode); extern void CacheClearLine(void* ptr); -extern void ScreenStretch(int src, int width, int height, int interp); #ifdef __cplusplus } diff --git a/misc/32x/sh2_crt0.s b/misc/32x/sh2_crt0.s index 020718f72..45a1d141f 100644 --- a/misc/32x/sh2_crt0.s +++ b/misc/32x/sh2_crt0.s @@ -29,19 +29,19 @@ ! Master Vector Base Table at 0x06000000 - .long mstart /* Cold Start PC */ - .long 0x0603FC00 /* Cold Start SP */ - .long mstart /* Manual Reset PC */ - .long 0x0603FC00 /* Manual Reset SP */ - .long main_err /* Illegal instruction */ - .long 0x00000000 /* reserved */ - .long main_err /* Invalid slot instruction */ - .long 0x20100400 /* reserved */ - .long 0x20100420 /* reserved */ - .long main_err /* CPU address error */ - .long main_err /* DMA address error */ - .long main_err /* NMI vector */ - .long main_err /* User break vector */ + .long mstart /* 0, Cold Start PC */ + .long 0x0603FC00 /* 1, Cold Start SP */ + .long mstart /* 2, Manual Reset PC */ + .long 0x0603FC00 /* 3, Manual Reset SP */ + .long main_err /* 4, Illegal instruction */ + .long _wdt_handler/* 5, reserved - repurposed for WDT */ + .long main_err /* 6, Invalid slot instruction */ + .long 0x20100400 /* 7, reserved */ + .long 0x20100420 /* 8, reserved */ + .long main_err /* 9, CPU address error */ + .long main_err /* 10, DMA address error */ + .long main_err /* 11, NMI vector */ + .long main_err /* 12, User break vector */ .space 76 /* reserved */ .long main_err /* TRAPA #32 */ .long main_err /* TRAPA #33 */ @@ -637,81 +637,6 @@ _CacheControl: _sh2_cctl: .long 0xFFFFFE92 -! void ScreenStretch(int src, int width, int height, int interp); -! On entry: r4 = src pointer, r5 = width, r6 = height, r7 = interpolate - - .align 4 - .global _ScreenStretch -_ScreenStretch: - cmp/pl r7 - bt ss_interp - -! stretch screen without interpolation - -0: - mov r5,r3 - shll r3 - mov r3,r2 - shll r2 - add r4,r3 - add r4,r2 -1: - add #-2,r3 - mov.w @r3,r0 - extu.w r0,r1 - shll16 r0 - or r1,r0 - mov.l r0,@-r2 - cmp/eq r3,r4 - bf 1b - - /* next line */ - mov.w ss_pitch,r0 - dt r6 - bf/s 0b - add r0,r4 - rts - nop - -ss_interp: - -! stretch screen with interpolation - -0: - mov r5,r3 - shll r3 - mov r3,r2 - shll r2 - add r4,r3 - add r4,r2 - mov #0,r7 -1: - add #-2,r3 - mov.w @r3,r0 - mov.w ss_mask,r1 - and r0,r1 /* masked curr pixel */ - shll16 r0 - add r1,r7 /* add to masked prev pixel */ - shlr r7 /* blended pixel */ - or r7,r0 /* curr pixel << 16 | blended pixel */ - mov r1,r7 /* masked prev pixel = masked curr pixel */ - mov.l r0,@-r2 - cmp/eq r3,r4 - bf 1b - - /* next line */ - mov.w ss_pitch,r0 - dt r6 - bf/s 0b - add r0,r4 - rts - nop - -ss_mask: - .word 0x7BDE -ss_pitch: - .word 640 - .align 2 .text diff --git a/src/32x/Platform_32x.c b/src/32x/Platform_32x.c index 530d0be51..8e23fe818 100644 --- a/src/32x/Platform_32x.c +++ b/src/32x/Platform_32x.c @@ -95,13 +95,30 @@ void Process_Abort2(cc_result result, const char* raw_msg) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -cc_uint64 Stopwatch_Measure(void) { - return 0; +#include "../saturn/sh2_wdt.h" + +static void Stopwatch_Init(void) { + wdt_stop(); + + wdt_set_irq_number(5); // hardcoded in sh2_crt0.s + wdt_set_irq_priority(15); + + wdt_enable(); } +cc_uint64 Stopwatch_Measure(void) { + return wdt_total_ticks(); +} + +#define US_PER_SEC 1000000 +#define NTSC_CPU_CLOCK 23011360 // TODO + cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - return 1000 * 1000; + cc_uint64 delta = end - beg; + + // TODO still completely wrong?? PAL detection ??? + return (delta * US_PER_SEC) / (NTSC_CPU_CLOCK / 1024); } @@ -259,6 +276,8 @@ void Platform_Init(void) { int size = (int)(heap_end - heap_beg); Platform_Log3("HEAP SIZE: %i bytes (%x -> %x)", &size, &heap_beg, &heap_end); + + Stopwatch_Init(); } void Platform_Free(void) { } diff --git a/src/saturn/sh2_wdt.h b/src/saturn/sh2_wdt.h index ed792bb30..c1c0e4a51 100644 --- a/src/saturn/sh2_wdt.h +++ b/src/saturn/sh2_wdt.h @@ -48,7 +48,7 @@ static CC_INLINE void wdt_set_irq_priority(uint8_t pri) { } -static void __interrupt_handler wdt_handler(void) { +void __attribute__((interrupt_handler)) wdt_handler(void) { uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); From 725b5d5973ab372916363701b9ea495f93226d27 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 15 Aug 2025 17:57:57 +1000 Subject: [PATCH 020/115] Xbox: try to increase deadzone, and fix sprites always being drawn solidly --- .github/workflows/build_saturn.yml | 6 ++---- src/xbox/Graphics_Xbox.c | 12 +++++++++++- src/xbox/Window_Xbox.c | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index 55e287f59..015d16a90 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -21,10 +21,8 @@ jobs: - uses: actions/checkout@v4 - name: Install prerequisites run: | - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6ED0E7B82643E131 - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 78DBA3BC47EF2265 - apt-get update - apt-get -y install curl + apt-get --allow-unauthenticated update + apt-get --allow-unauthenticated -y install curl - name: Compile Saturn build id: compile diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index c59d4ac0b..e0bdeebaa 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -5,6 +5,8 @@ #include +#define _NV_ALPHAKILL_EN (1 << 4) + #define MAX_RAM_ADDR 0x03FFAFFF #define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) @@ -267,7 +269,8 @@ void Gfx_BindTexture(GfxResourceID texId) { MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 p = pb_push1(p, NV097_SET_TEXTURE_CONTROL0, - NV097_SET_TEXTURE_CONTROL0_ENABLE | + NV097_SET_TEXTURE_CONTROL0_ENABLE | + (gfx_alphaTest ? _NV_ALPHAKILL_EN : 0) | MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); p = pb_push1(p, NV097_SET_TEXTURE_ADDRESS, @@ -309,6 +312,13 @@ static void SetAlphaBlend(cc_bool enabled) { static void SetAlphaTest(cc_bool enabled) { uint32_t* p = pb_begin(); p = pb_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); + + // TODO not duplicate with Gfx_BindTexture + p = pb_push1(p, NV097_SET_TEXTURE_CONTROL0, + NV097_SET_TEXTURE_CONTROL0_ENABLE | + (gfx_alphaTest ? _NV_ALPHAKILL_EN : 0) | + MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | + MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); pb_end(p); } diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index f974f9a8a..1f610f898 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -170,8 +170,8 @@ static void HandleButtons(int port, xid_gamepad_in* gp) { #define AXIS_SCALE 8192.0f static void HandleJoystick(int port, int axis, int x, int y, float delta) { - if (Math_AbsI(x) <= 4096) x = 0; - if (Math_AbsI(y) <= 4096) y = 0; + if (Math_AbsI(x) <= 6144) x = 0; + if (Math_AbsI(y) <= 6144) y = 0; Gamepad_SetAxis(port, axis, x / AXIS_SCALE, -y / AXIS_SCALE, delta); } From c6abd086897b0f136321f500b9c55a551529dbfb Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 15 Aug 2025 18:25:08 +1000 Subject: [PATCH 021/115] Xbox: try to fix can't go back to launcher menu --- src/_PlatformConsole.h | 2 +- src/xbox/Graphics_Xbox.c | 9 ++++----- src/xbox/Window_Xbox.c | 3 +++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/_PlatformConsole.h b/src/_PlatformConsole.h index 7877e42bb..399ad0bfc 100644 --- a/src/_PlatformConsole.h +++ b/src/_PlatformConsole.h @@ -8,7 +8,7 @@ cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; int main(int argc, char** argv) { SetupProgram(argc, argv); while (Window_Main.Exists) { - RunProgram(argc, argv); + RunProgram(argc, argv); } Window_Free(); diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index e0bdeebaa..554093891 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -5,7 +5,7 @@ #include -#define _NV_ALPHAKILL_EN (1 << 4) +#define _NV_ALPHAKILL_EN (1 << 2) #define MAX_RAM_ADDR 0x03FFAFFF #define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) @@ -113,8 +113,7 @@ void Gfx_Create(void) { Gfx.MaxTexHeight = 512; // TODO: 1024? Gfx.Created = true; - InitDefaultResources(); - pb_init(); + InitDefaultResources(); pb_show_front_screen(); SetupShaders(); @@ -130,8 +129,8 @@ void Gfx_Create(void) { } void Gfx_Free(void) { - FreeDefaultResources(); - pb_kill(); + FreeDefaultResources(); + pb_show_debug_screen(); } cc_bool Gfx_TryRestoreContext(void) { return true; } diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index 1f610f898..299f78970 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -13,6 +13,7 @@ #include #include #include +#include static cc_bool launcherMode; struct _DisplayData DisplayInfo; @@ -20,6 +21,8 @@ struct cc_window WindowInfo; void Window_PreInit(void) { XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); // TODO not call + pb_init(); + pb_show_debug_screen(); } void Window_Init(void) { From 862519b051ec700336435960e4f8a666370a9ad2 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 15 Aug 2025 21:19:46 +1000 Subject: [PATCH 022/115] GBA/32x: Loading screen render time improved from ~19 to ~1.5 seconds --- src/Graphics_SoftMin.c | 21 ++------------------- src/Screens.c | 2 +- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index a6888a812..061ec6469 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -389,28 +389,11 @@ static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2) { int texIndex = texY * curTexWidth + texX; BitmapCol color = curTexPixels[texIndex]; - int R, G, B, A; + int R, G, B; - A = BitmapCol_A(color); - if (gfx_alphaBlend && A == 0) continue; + if ((color & BITMAPCOLOR_A_MASK) == 0) continue; int cb_index = y * cb_stride + x; - if (gfx_alphaBlend && A != 255) { - BitmapCol dst = colorBuffer[cb_index]; - int dstR = BitmapCol_R(dst); - int dstG = BitmapCol_G(dst); - int dstB = BitmapCol_B(dst); - - R = BitmapCol_R(color); - G = BitmapCol_G(color); - B = BitmapCol_B(color); - - R = (R * A + dstR * (255 - A)) >> 8; - G = (G * A + dstG * (255 - A)) >> 8; - B = (B * A + dstB * (255 - A)) >> 8; - color = BitmapCol_Make(R, G, B, 0xFF); - } - if (vColor != PACKEDCOL_WHITE) { int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(color); R = ( r1 * r2 ) >> 8; diff --git a/src/Screens.c b/src/Screens.c index 3bdc48bb2..10dfd844a 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -1955,7 +1955,7 @@ static void LoadingScreen_Render(void* screen, float delta) { if (s->rows) { loc = Block_Tex(BLOCK_DIRT, FACE_YMAX); Atlas1D_Bind(Atlas1D_Index(loc)); - Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, 0); + Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, DRAW_HINT_SPRITE); offset = s->rows * 4; } From 4cadc0009d4a4c9bceb0b1f2b970f08aec4e8714 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 16 Aug 2025 07:24:50 +1000 Subject: [PATCH 023/115] GBA/32x: Implement control scheme making it technically possible to move the camera --- src/32x/Window_32x.c | 19 ++++++++++++++++++- src/gba/Window_GBA.c | 19 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/32x/Window_32x.c b/src/32x/Window_32x.c index 6273424c1..acd66d0b0 100644 --- a/src/32x/Window_32x.c +++ b/src/32x/Window_32x.c @@ -94,12 +94,29 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping pad_defaults[BIND_COUNT] = { + [BIND_LOOK_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_LOOK_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_LOOK_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_LOOK_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_FORWARD] = { CCPAD_UP, 0 }, + [BIND_BACK] = { CCPAD_DOWN, 0 }, + [BIND_LEFT] = { CCPAD_LEFT, 0 }, + [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, + [BIND_JUMP] = { CCPAD_1, 0 }, + [BIND_INVENTORY] = { CCPAD_3, 0 }, + [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, + [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_HOTBAR_LEFT] = { CCPAD_4, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_4, CCPAD_RIGHT } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x32, PadBind_Defaults); + int port = Gamepad_Connect(0x32, pad_defaults); int mods = HwMdReadPad(0); Gamepad_SetButton(port, CCPAD_L, mods & SEGA_CTRL_X); diff --git a/src/gba/Window_GBA.c b/src/gba/Window_GBA.c index 4ddc77685..4b9867b30 100644 --- a/src/gba/Window_GBA.c +++ b/src/gba/Window_GBA.c @@ -85,12 +85,29 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping pad_defaults[BIND_COUNT] = { + [BIND_LOOK_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_LOOK_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_LOOK_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_LOOK_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_FORWARD] = { CCPAD_UP, 0 }, + [BIND_BACK] = { CCPAD_DOWN, 0 }, + [BIND_LEFT] = { CCPAD_LEFT, 0 }, + [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, + [BIND_JUMP] = { CCPAD_1, 0 }, + [BIND_INVENTORY] = { CCPAD_R, CCPAD_UP }, + [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, + [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_HOTBAR_LEFT] = { CCPAD_L, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_L, CCPAD_RIGHT } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x5BA, PadBind_Defaults); + int port = Gamepad_Connect(0x5BA, pad_defaults); int mods = ~REG_KEYINPUT; Gamepad_SetButton(port, CCPAD_L, mods & KEY_L); From 5efdf12738bd124bb9bbe772f8cbfb7d4edf5732 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 10:03:49 +1000 Subject: [PATCH 024/115] GBA/32x: Hardcode alpha of 128, saves 10 milliseconds per frame in test case --- src/Graphics_SoftMin.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index 061ec6469..d6ccfadb7 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -620,9 +620,10 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { int dstG = BitmapCol_G(dst); int dstB = BitmapCol_B(dst); - int finR = (R * A + dstR * (255 - A)) >> 8; - int finG = (G * A + dstG * (255 - A)) >> 8; - int finB = (B * A + dstB * (255 - A)) >> 8; + // Hardcode for alpha of 128 + int finR = (R + dstR) >> 1; + int finG = (G + dstG) >> 1; + int finB = (B + dstB) >> 1; colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); } } From 433f7cfa49516fb020da4508c76616f6cc16c42c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 10:19:15 +1000 Subject: [PATCH 025/115] GBA: Frame time down to 7.3 seconds --- src/Graphics_SoftMin.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index d6ccfadb7..9bab4ba2e 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -15,9 +15,6 @@ static BitmapCol clearColor; static cc_bool colWrite = true; static int cb_stride; -static float* depthBuffer; -static int db_stride; - static void* gfx_vertices; static GfxResourceID white_square; @@ -556,9 +553,7 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { float z0 = V0->z, z1 = V1->z, z2 = V2->z; PackedCol color = V0->c; - - float u0 = V0->u * curTexWidth, u1 = V1->u * curTexWidth, u2 = V2->u * curTexWidth; - float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight, v2 = V2->v * curTexHeight; + float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight; // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) @@ -603,10 +598,7 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) { - float ic0 = bc0 * factor; - float ic1 = bc1 * factor; - float ic2 = bc2 * factor; - if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + if (bc0 < 0 || bc1 < 0 || bc2 < 0) continue; int cb_index = y * cb_stride + x; From cbba51ddce4d2b6609069d9b652ccddc03a589bc Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 18:04:17 +1000 Subject: [PATCH 026/115] GBA: Now takes 1.1 seconds to render the frame --- src/Graphics_SoftMin.c | 17 ++++++++--------- src/Model.c | 9 ++++++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index 9bab4ba2e..64e6eda88 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -542,8 +542,7 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { minX = max(minX, 0); maxX = min(maxX, fb_maxX); minY = max(minY, 0); maxY = min(maxY, fb_maxY); - // NOTE: W in frag variables below is actually 1/W - float factor = 1.0f / area; + // NOTE: W in frag variables below is actually 1/W float w0 = V0->w, w1 = V1->w, w2 = V2->w; // TODO proper clipping @@ -561,9 +560,9 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { int dx12 = y1 - y2, dy12 = x2 - x1; int dx20 = y2 - y0, dy20 = x0 - x2; - float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); - float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); - float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + int bc0_start = edgeFunction(x1,y1, x2,y2, minX, minY); + int bc1_start = edgeFunction(x2,y2, x0,y0, minX, minY); + int bc2_start = edgeFunction(x0,y0, x1,y1, minX, minY); int R, G, B, A, x, y; int a1, r1, g1, b1; @@ -592,13 +591,13 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) { - float bc0 = bc0_start; - float bc1 = bc1_start; - float bc2 = bc2_start; + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) { - if (bc0 < 0 || bc1 < 0 || bc2 < 0) continue; + if ((bc0 | bc1 | bc2) < 0) continue; int cb_index = y * cb_stride + x; diff --git a/src/Model.c b/src/Model.c index 908b1d446..34f195ae4 100644 --- a/src/Model.c +++ b/src/Model.c @@ -212,14 +212,17 @@ void Model_DrawPart(struct ModelPart* part) { struct ModelVertex v; int i, count = part->count; + float uScale = Models.uScale; + float vScale = Models.vScale; - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) + { v = *src; dst->x = v.x; dst->y = v.y; dst->z = v.z; dst->Col = Models.Cols[i >> 2]; - dst->U = (v.u & UV_POS_MASK) * Models.uScale - (v.u >> UV_MAX_SHIFT) * 0.01f * Models.uScale; - dst->V = (v.v & UV_POS_MASK) * Models.vScale - (v.v >> UV_MAX_SHIFT) * 0.01f * Models.vScale; + dst->U = (v.u & UV_POS_MASK) * uScale - (v.u >> UV_MAX_SHIFT) * 0.01f * uScale; + dst->V = (v.v & UV_POS_MASK) * vScale - (v.v >> UV_MAX_SHIFT) * 0.01f * vScale; src++; dst++; } model->index += count; From 4fb5cec968203f362d91831c5f9de0f2baee918f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 18:46:17 +1000 Subject: [PATCH 027/115] GBA: Now down to ~0.94 seconds a frame --- src/Graphics_SoftMin.c | 206 ++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 125 deletions(-) diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index 64e6eda88..5d388558c 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -409,99 +409,6 @@ static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2) { #define edgeFunction(ax,ay, bx,by, cx,cy) (((bx) - (ax)) * ((cy) - (ay)) - ((by) - (ay)) * ((cx) - (ax))) -static void DrawTriangle2D(Vertex* V0, Vertex* V1, Vertex* V2) { - int x0 = (int)V0->x, y0 = (int)V0->y; - int x1 = (int)V1->x, y1 = (int)V1->y; - int x2 = (int)V2->x, y2 = (int)V2->y; - int minX = min(x0, min(x1, x2)); - int minY = min(y0, min(y1, y2)); - int maxX = max(x0, max(x1, x2)); - int maxY = max(y0, max(y1, y2)); - - // Reject triangles completely outside - if (maxX < 0 || minX > fb_maxX) return; - if (maxY < 0 || minY > fb_maxY) return; - - // Perform scissoring - minX = max(minX, 0); maxX = min(maxX, fb_maxX); - minY = max(minY, 0); maxY = min(maxY, fb_maxY); - - float u0 = V0->u * curTexWidth, u1 = V1->u * curTexWidth, u2 = V2->u * curTexWidth; - float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight, v2 = V2->v * curTexHeight; - PackedCol color = V0->c; - - int area = edgeFunction(x0,y0, x1,y1, x2,y2); - float factor = 1.0f / area; - int x, y; - - // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ - // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) - int dx01 = y0 - y1, dy01 = x1 - x0; - int dx12 = y1 - y2, dy12 = x2 - x1; - int dx20 = y2 - y0, dy20 = x0 - x2; - - float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); - float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); - float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); - - for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) - { - float bc0 = bc0_start; - float bc1 = bc1_start; - float bc2 = bc2_start; - - for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) - { - float ic0 = bc0 * factor; - float ic1 = bc1 * factor; - float ic2 = bc2 * factor; - - if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; - int cb_index = y * cb_stride + x; - - int R, G, B, A; - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - float u = ic0 * u0 + ic1 * u1 + ic2 * u2; - float v = ic0 * v0 + ic1 * v1 + ic2 * v2; - int texX = ((int)u) & texWidthMask; - int texY = ((int)v) & texHeightMask; - int texIndex = texY * curTexWidth + texX; - - BitmapCol tColor = curTexPixels[texIndex]; - int a1 = PackedCol_A(color), a2 = BitmapCol_A(tColor); - A = ( a1 * a2 ) >> 8; - int r1 = PackedCol_R(color), r2 = BitmapCol_R(tColor); - R = ( r1 * r2 ) >> 8; - int g1 = PackedCol_G(color), g2 = BitmapCol_G(tColor); - G = ( g1 * g2 ) >> 8; - int b1 = PackedCol_B(color), b2 = BitmapCol_B(tColor); - B = ( b1 * b2 ) >> 8; - } else { - R = PackedCol_R(color); - G = PackedCol_G(color); - B = PackedCol_B(color); - A = PackedCol_A(color); - } - - if (gfx_alphaTest && A < 0x80) continue; - if (gfx_alphaBlend && A == 0) continue; - - if (gfx_alphaBlend && A != 255) { - BitmapCol dst = colorBuffer[cb_index]; - int dstR = BitmapCol_R(dst); - int dstG = BitmapCol_G(dst); - int dstB = BitmapCol_B(dst); - - R = (R * A + dstR * (255 - A)) >> 8; - G = (G * A + dstG * (255 - A)) >> 8; - B = (B * A + dstB * (255 - A)) >> 8; - } - - colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); - } - } -} - #define MultiplyColors(vColor, tColor) \ a1 = PackedCol_A(vColor); \ a2 = BitmapCol_A(tColor); \ @@ -519,6 +426,73 @@ static void DrawTriangle2D(Vertex* V0, Vertex* V1, Vertex* V2) { b2 = BitmapCol_B(tColor); \ B = ( b1 * b2 ) >> 8; \ +static void DrawTriangle2D(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + // Reject triangles completely outside + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + // Perform scissoring + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + // TODO still too slow, costs 300 ms/frame + float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); + float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); + float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + + PackedCol color = V0->c; + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else { + /* Always use a single pixel */ + float rawY0 = V0->v * curTexHeight; + float rawY1 = V1->v * curTexHeight; + + float rawY = min(rawY0, rawY1); + int texY = (int)(rawY + 0.01f) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + } + + if (A == 0) return; + color = BitmapCol_Make(R, G, B, 0xFF); + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + float bc0 = bc0_start; + float bc1 = bc1_start; + float bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + if (bc0 < 0 || bc1 < 0 || bc2 < 0) continue; + int cb_index = y * cb_stride + x; + + colorBuffer[cb_index] = color; + } + } +} + static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { int x0 = (int)V0->x, y0 = (int)V0->y; int x1 = (int)V1->x, y1 = (int)V1->y; @@ -541,52 +515,38 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { // Perform scissoring minX = max(minX, 0); maxX = min(maxX, fb_maxX); minY = max(minY, 0); maxY = min(maxY, fb_maxY); - - // NOTE: W in frag variables below is actually 1/W - float w0 = V0->w, w1 = V1->w, w2 = V2->w; - - // TODO proper clipping - if (w0 <= 0 || w1 <= 0 || w2 <= 0) { - return; - } - - float z0 = V0->z, z1 = V1->z, z2 = V2->z; - PackedCol color = V0->c; - float v0 = V0->v * curTexHeight, v1 = V1->v * curTexHeight; // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) - int dx01 = y0 - y1, dy01 = x1 - x0; - int dx12 = y1 - y2, dy12 = x2 - x1; - int dx20 = y2 - y0, dy20 = x0 - x2; + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; int bc0_start = edgeFunction(x1,y1, x2,y2, minX, minY); int bc1_start = edgeFunction(x2,y2, x0,y0, minX, minY); int bc2_start = edgeFunction(x0,y0, x1,y1, minX, minY); + PackedCol color = V0->c; int R, G, B, A, x, y; int a1, r1, g1, b1; int a2, r2, g2, b2; - cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; - if (!texturing) { + if (gfx_format != VERTEX_FORMAT_TEXTURED) { R = PackedCol_R(color); G = PackedCol_G(color); B = PackedCol_B(color); A = PackedCol_A(color); } else { /* Always use a single pixel */ - float rawY0 = v0; - float rawY1 = v1; + float rawY0 = V0->v * curTexHeight; + float rawY1 = V1->v * curTexHeight; float rawY = min(rawY0, rawY1); int texY = (int)(rawY + 0.01f) & texHeightMask; MultiplyColors(color, curTexPixels[texY * curTexWidth]); - texturing = false; } - if (!colWrite) return; - if (gfx_alphaTest && A < 0x80) return; + if (gfx_alphaTest && A == 0) return; color = BitmapCol_Make(R, G, B, 0xFF); for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) @@ -598,7 +558,6 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) { if ((bc0 | bc1 | bc2) < 0) continue; - int cb_index = y * cb_stride + x; if (!gfx_alphaBlend) { @@ -606,15 +565,12 @@ static void DrawTriangle3D(Vertex* V0, Vertex* V1, Vertex* V2) { continue; } - BitmapCol dst = colorBuffer[cb_index]; - int dstR = BitmapCol_R(dst); - int dstG = BitmapCol_G(dst); - int dstB = BitmapCol_B(dst); - // Hardcode for alpha of 128 - int finR = (R + dstR) >> 1; - int finG = (G + dstG) >> 1; - int finB = (B + dstB) >> 1; + BitmapCol dst = colorBuffer[cb_index]; + int finR = (R + BitmapCol_R(dst)) >> 1; + int finG = (G + BitmapCol_G(dst)) >> 1; + int finB = (B + BitmapCol_B(dst)) >> 1; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); } } @@ -909,7 +865,7 @@ void DrawQuads(int startVertex, int verticesCount, DrawHints hints) { DrawTriangle2D(&vertices[0], &vertices[2], &vertices[1]); DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); } - } else { + } else if (colWrite) { // 4 vertices = 1 quad = 2 triangles for (i = 0; i < verticesCount / 4; i++, j += 4) { From 2c11be635da0bbef60fa3af47ab8dd987dbc095c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 20:06:26 +1000 Subject: [PATCH 028/115] GBA/32x: Render world without edge/horizon --- src/EnvRenderer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index df73d586c..7476c8071 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -704,7 +704,7 @@ static CC_NOINLINE void BuildMapSides(void) { struct VertexTextured* data; if (!World.Loaded) return; - /*if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return;*/ + if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return; block = Env.SidesBlock; if (Blocks.Draw[block] == DRAW_GAS) return; @@ -757,7 +757,7 @@ static CC_NOINLINE void BuildMapEdges(void) { struct VertexTextured* data; if (!World.Loaded) return; - /*if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return;*/ + if (Gfx.Limitations & GFX_LIMIT_WORLD_ONLY) return; block = Env.EdgeBlock; if (Blocks.Draw[block] == DRAW_GAS) return; From 17d7f82ffd12da202f8e78681cc9a399ddb84206 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 17 Aug 2025 20:44:22 +1000 Subject: [PATCH 029/115] 32x: Fix world being culled due to compiler bug --- src/Vectors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Vectors.c b/src/Vectors.c index 142df1194..04fdc1ad2 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -205,7 +205,7 @@ cc_bool FrustumCulling_SphereInFrustum(float x, float y, float z, float radius) if (d <= -radius) return false; /* Don't test NEAR plane, it's pointless */ -#ifdef CC_BUILD_SATURN +#if defined CC_BUILD_SATURN || defined CC_BUILD_32X /* Workaround a compiler bug causing the below statement to return 0 instead */ __asm__( "!" ); #endif From af6cbc9b9e906862f50bc0064d3249689e214874 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 19 Aug 2025 19:31:11 +1000 Subject: [PATCH 030/115] Try to simplify non updater/dynamic lib platform support --- src/32x/Platform_32x.c | 5 +++ src/3ds/Platform_3DS.c | 5 +++ src/Platform_Amiga.c | 45 ++------------------------ src/Platform_MacClassic.c | 45 ++------------------------ src/Platform_N64.c | 8 +++++ src/Platform_NDS.c | 8 +++++ src/Platform_PS4.c | 6 ++++ src/_PlatformBase.h | 35 ++++++++++++++++++++ src/_PlatformConsole.h | 51 ------------------------------ src/dreamcast/Platform_Dreamcast.c | 8 +++++ src/gba/Platform_GBA.c | 5 +++ src/gcwii/Platform_GCWii.c | 9 ++++++ src/msdos/Platform_MSDOS.c | 47 ++------------------------- src/ps1/Platform_PS1.c | 9 ++++++ src/ps2/Platform_PS2.c | 9 ++++++ src/ps3/Platform_PS3.c | 9 ++++++ src/psp/Platform_PSP.c | 9 ++++++ src/psvita/Platform_PSVita.c | 8 +++++ src/saturn/Platform_Saturn.c | 9 ++++++ src/switch/Platform_Switch.c | 9 ++++++ src/wiiu/Platform_WiiU.c | 9 ++++++ src/xbox/Platform_Xbox.c | 9 ++++++ src/xbox360/Platform_Xbox360.c | 9 ++++++ 23 files changed, 185 insertions(+), 181 deletions(-) diff --git a/src/32x/Platform_32x.c b/src/32x/Platform_32x.c index 8e23fe818..9e51645e1 100644 --- a/src/32x/Platform_32x.c +++ b/src/32x/Platform_32x.c @@ -1,4 +1,7 @@ #define OVERRIDE_MEM_FUNCTIONS +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -130,6 +133,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ReturnCode_DirectoryExists; } diff --git a/src/3ds/Platform_3DS.c b/src/3ds/Platform_3DS.c index dec2bfb58..00be4e84a 100644 --- a/src/3ds/Platform_3DS.c +++ b/src/3ds/Platform_3DS.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -110,6 +113,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, 0666) == -1 ? errno : 0; // FS has no permissions anyways } diff --git a/src/Platform_Amiga.c b/src/Platform_Amiga.c index f89e51b6c..c98b1836b 100644 --- a/src/Platform_Amiga.c +++ b/src/Platform_Amiga.c @@ -1,5 +1,7 @@ #include "Core.h" #if defined CC_BUILD_AMIGA +#define CC_NO_UPDATER +#define CC_NO_DYNLIB #include "_PlatformBase.h" #include "Stream.h" @@ -330,49 +332,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dylib"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/Platform_MacClassic.c b/src/Platform_MacClassic.c index 8c1b2f3c7..b3430ece5 100644 --- a/src/Platform_MacClassic.c +++ b/src/Platform_MacClassic.c @@ -1,5 +1,7 @@ #include "Core.h" #if defined CC_BUILD_MACCLASSIC +#define CC_NO_UPDATER +#define CC_NO_DYNLIB #include "_PlatformBase.h" #include "Stream.h" @@ -491,49 +493,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dylib"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/Platform_N64.c b/src/Platform_N64.c index 6a676d79c..b35ac06eb 100644 --- a/src/Platform_N64.c +++ b/src/Platform_N64.c @@ -1,5 +1,7 @@ #include "Core.h" #if defined CC_BUILD_N64 +#define CC_NO_UPDATER +#define CC_NO_DYNLIB #define CC_XTEA_ENCRYPTION #include "_PlatformBase.h" @@ -101,6 +103,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, &path_); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1 ? errno : 0; } @@ -334,4 +338,8 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} #endif diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index 6a3f86bdd..24ccdadaf 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -1,5 +1,7 @@ #include "Core.h" #if defined CC_BUILD_NDS +#define CC_NO_UPDATER +#define CC_NO_DYNLIB #define CC_XTEA_ENCRYPTION #include "_PlatformBase.h" @@ -216,6 +218,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return 0; @@ -655,4 +659,8 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} #endif diff --git a/src/Platform_PS4.c b/src/Platform_PS4.c index fa0f99546..30aa77ab1 100644 --- a/src/Platform_PS4.c +++ b/src/Platform_PS4.c @@ -113,6 +113,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -583,4 +585,8 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} #endif diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index 576dfb91a..f6c30eaa8 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -341,3 +341,38 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a } #endif + +/*########################################################################################################################* +*--------------------------------------------------------Updater----------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_UPDATER +cc_bool Updater_Supported = false; +cc_bool Updater_Clean(void) { return true; } + +const struct UpdaterInfo Updater_Info = { "&eRedownload or recompile to update", 0 }; + +cc_result Updater_Start(const char** action) { + *action = "Starting game"; + return ERR_NOT_SUPPORTED; +} + +cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } + +cc_result Updater_MarkExecutable(void) { return ERR_NOT_SUPPORTED; } + +cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } +#endif + + +/*########################################################################################################################* +*-------------------------------------------------------Dynamic lib-------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_DYNLIB +const cc_string DynamicLib_Ext = String_FromConst(".so"); + +void* DynamicLib_Load2(const cc_string* path) { return NULL; } +void* DynamicLib_Get2(void* lib, const char* name) { return NULL; } + +cc_bool DynamicLib_DescribeError(cc_string* dst) { return false; } +#endif + diff --git a/src/_PlatformConsole.h b/src/_PlatformConsole.h index 399ad0bfc..4bd178e6f 100644 --- a/src/_PlatformConsole.h +++ b/src/_PlatformConsole.h @@ -44,12 +44,6 @@ void Mem_Free(void* mem) { #endif -/*########################################################################################################################* -*-----------------------------------------------------Directory/File------------------------------------------------------* -*#########################################################################################################################*/ -void Directory_GetCachePath(cc_string* path) { } - - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* *#########################################################################################################################*/ @@ -88,48 +82,3 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { void Process_Exit(cc_result code) { exit(code); } - -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - *action = "Starting game"; - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } - -cc_result Updater_MarkExecutable(void) { return ERR_NOT_SUPPORTED; } - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -// TODO can this actually be supported somehow -const cc_string DynamicLib_Ext = String_FromConst(".so"); - -void* DynamicLib_Load2(const cc_string* path) { return NULL; } -void* DynamicLib_Get2(void* lib, const char* name) { return NULL; } - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - String_AppendConst(dst, "Dynamic linking unsupported"); - return true; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Encryption--------------------------------------------------------* -*#########################################################################################################################*/ -#ifndef CC_BUILD_3DS -cc_result Platform_GetEntropy(void* data, int len) { - return ERR_NOT_SUPPORTED; -} -#endif - diff --git a/src/dreamcast/Platform_Dreamcast.c b/src/dreamcast/Platform_Dreamcast.c index ffe86c437..e81133c2b 100644 --- a/src/dreamcast/Platform_Dreamcast.c +++ b/src/dreamcast/Platform_Dreamcast.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -319,6 +322,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int res = fs_mkdir(path->buffer); int err = res == -1 ? errno : 0; @@ -752,3 +757,6 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/gba/Platform_GBA.c b/src/gba/Platform_GBA.c index ec3118236..83f91e430 100644 --- a/src/gba/Platform_GBA.c +++ b/src/gba/Platform_GBA.c @@ -1,3 +1,6 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -181,6 +184,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ERR_NOT_SUPPORTED; } diff --git a/src/gcwii/Platform_GCWii.c b/src/gcwii/Platform_GCWii.c index 11d73737e..974ec2cec 100644 --- a/src/gcwii/Platform_GCWii.c +++ b/src/gcwii/Platform_GCWii.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -139,6 +142,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return ENOSYS; @@ -644,3 +649,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/msdos/Platform_MSDOS.c b/src/msdos/Platform_MSDOS.c index 56fc5ba13..f18d74b39 100644 --- a/src/msdos/Platform_MSDOS.c +++ b/src/msdos/Platform_MSDOS.c @@ -1,3 +1,6 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -343,50 +346,6 @@ cc_result Process_StartOpen(const cc_string* args) { } -/*########################################################################################################################* -*--------------------------------------------------------Updater----------------------------------------------------------* -*#########################################################################################################################*/ -cc_bool Updater_Supported = false; - -cc_bool Updater_Clean(void) { return true; } - -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; - -cc_result Updater_Start(const char** action) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_GetBuildTime(cc_uint64* timestamp) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_MarkExecutable(void) { - return ERR_NOT_SUPPORTED; -} - -cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { - return ERR_NOT_SUPPORTED; -} - - -/*########################################################################################################################* -*-------------------------------------------------------Dynamic lib-------------------------------------------------------* -*#########################################################################################################################*/ -const cc_string DynamicLib_Ext = String_FromConst(".dll"); - -void* DynamicLib_Load2(const cc_string* path) { - return NULL; -} - -void* DynamicLib_Get2(void* lib, const char* name) { - return NULL; -} - -cc_bool DynamicLib_DescribeError(cc_string* dst) { - return false; -} - - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ diff --git a/src/ps1/Platform_PS1.c b/src/ps1/Platform_PS1.c index 0f96bc8d7..6f1d999ce 100644 --- a/src/ps1/Platform_PS1.c +++ b/src/ps1/Platform_PS1.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -106,6 +109,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ERR_NOT_SUPPORTED; } @@ -275,3 +280,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/ps2/Platform_PS2.c b/src/ps2/Platform_PS2.c index 1e43b9dce..5edd24b9c 100644 --- a/src/ps2/Platform_PS2.c +++ b/src/ps2/Platform_PS2.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -150,6 +153,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return fioMkdir(path->buffer); } @@ -759,3 +764,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/ps3/Platform_PS3.c b/src/ps3/Platform_PS3.c index 28c8a4b70..aa87edd8f 100644 --- a/src/ps3/Platform_PS3.c +++ b/src/ps3/Platform_PS3.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -113,6 +116,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -492,3 +497,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/psp/Platform_PSP.c b/src/psp/Platform_PSP.c index adf48ab32..d16133fd9 100644 --- a/src/psp/Platform_PSP.c +++ b/src/psp/Platform_PSP.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -107,6 +110,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { #define GetSCEResult(result) (result >= 0 ? 0 : result & 0xFFFF) +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int result = sceIoMkdir(path->buffer, 0777); return GetSCEResult(result); @@ -493,3 +498,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/psvita/Platform_PSVita.c b/src/psvita/Platform_PSVita.c index 1bd5b9103..da0390719 100644 --- a/src/psvita/Platform_PSVita.c +++ b/src/psvita/Platform_PSVita.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -90,6 +93,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { #define GetSCEResult(result) (result >= 0 ? 0 : result & 0xFFFF) +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { int result = sceIoMkdir(path->buffer, 0777); return GetSCEResult(result); @@ -450,3 +455,6 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 2d386155a..f8a311305 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -137,6 +140,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return ReturnCode_DirectoryExists; } @@ -308,3 +313,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/switch/Platform_Switch.c b/src/switch/Platform_Switch.c index 7cabda845..f67e918b2 100644 --- a/src/switch/Platform_Switch.c +++ b/src/switch/Platform_Switch.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -128,6 +131,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { return mkdir(path->buffer, 0) == -1 ? errno : 0; } @@ -541,3 +546,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/wiiu/Platform_WiiU.c b/src/wiiu/Platform_WiiU.c index 15d8193a3..7bc0b438c 100644 --- a/src/wiiu/Platform_WiiU.c +++ b/src/wiiu/Platform_WiiU.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../ExtMath.h" @@ -124,6 +127,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { /* read/write/search permissions for owner and group, and with read/search permissions for others. */ /* TODO: Is the default mode in all cases */ @@ -475,3 +480,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} diff --git a/src/xbox/Platform_Xbox.c b/src/xbox/Platform_Xbox.c index ca1929076..1338750e5 100644 --- a/src/xbox/Platform_Xbox.c +++ b/src/xbox/Platform_Xbox.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../Funcs.h" @@ -113,6 +116,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { *str = '\0'; } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!hdd_mounted) return ERR_NOT_SUPPORTED; @@ -472,3 +477,7 @@ static cc_result GetMachineID(cc_uint32* key) { return 0; } +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/xbox360/Platform_Xbox360.c b/src/xbox360/Platform_Xbox360.c index ff5864032..d67c9654f 100644 --- a/src/xbox360/Platform_Xbox360.c +++ b/src/xbox360/Platform_Xbox360.c @@ -1,4 +1,7 @@ #define CC_XTEA_ENCRYPTION +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + #include "../_PlatformBase.h" #include "../Stream.h" #include "../Funcs.h" @@ -101,6 +104,8 @@ void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { String_EncodeUtf8(str, path); } +void Directory_GetCachePath(cc_string* path) { } + cc_result Directory_Create(const cc_filepath* path) { if (!fat_available) return ENOSYS; @@ -345,3 +350,7 @@ static cc_result GetMachineID(cc_uint32* key) { Mem_Copy(key, MACHINE_KEY, sizeof(MACHINE_KEY) - 1); return 0; } + +cc_result Platform_GetEntropy(void* data, int len) { + return ERR_NOT_SUPPORTED; +} From dc44cab8beddd3b0b05d75223a8538f49decc417 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 19 Aug 2025 20:13:45 +1000 Subject: [PATCH 031/115] GBA/32x: Increase free RAM by 18 kb and reduce binary size by 45/66 kb by going straight in-game rather than via the launcher --- src/32x/Platform_32x.c | 46 ++++++++++++++++++++++++++++++++++++----- src/_PlatformBase.h | 4 ++-- src/gba/Platform_GBA.c | 47 +++++++++++++++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/32x/Platform_32x.c b/src/32x/Platform_32x.c index 9e51645e1..835d72b8c 100644 --- a/src/32x/Platform_32x.c +++ b/src/32x/Platform_32x.c @@ -14,7 +14,6 @@ #include #include -#include "../_PlatformConsole.h" #include "../../misc/32x/32x.h" #include "../../misc/32x/hw_32x.h" @@ -30,24 +29,43 @@ const cc_result ReturnCode_SocketDropped = -1; const char* Platform_AppNameSuffix = " 32x"; cc_bool Platform_ReadonlyFilesystem = true; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; + + +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunGame(); + } + + Window_Free(); + return 0; +} /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" MALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("MALLOCED: %x", &ptr); + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); return ptr; } void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" CALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("CALLOCED: %x", &ptr); + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); if (ptr) Mem_Set(ptr, 0, size); return ptr; @@ -304,3 +322,21 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { _exit(code); } + diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index f6c30eaa8..9c6c5a7dc 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -102,7 +102,7 @@ static char gameArgs[GAME_MAX_CMDARGS][STRING_SIZE]; static int gameNumArgs; static cc_bool gameHasArgs; -static cc_result SetGameArgs(const cc_string* args, int numArgs) { +static CC_INLINE cc_result SetGameArgs(const cc_string* args, int numArgs) { int i; for (i = 0; i < numArgs; i++) { @@ -114,7 +114,7 @@ static cc_result SetGameArgs(const cc_string* args, int numArgs) { return 0; } -static int GetGameArgs(cc_string* args) { +static CC_INLINE int GetGameArgs(cc_string* args) { int i, count = gameNumArgs; for (i = 0; i < count; i++) { diff --git a/src/gba/Platform_GBA.c b/src/gba/Platform_GBA.c index 83f91e430..6951699ba 100644 --- a/src/gba/Platform_GBA.c +++ b/src/gba/Platform_GBA.c @@ -16,9 +16,6 @@ #include #include "gbadefs.h" -#define OVERRIDE_MEM_FUNCTIONS -#include "../_PlatformConsole.h" - #include "../../third_party/tinyalloc/tinyalloc.c" typedef volatile uint8_t vu8; @@ -34,24 +31,42 @@ const cc_result ReturnCode_SocketDropped = -1; const char* Platform_AppNameSuffix = " GBA"; cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunGame(); + } + + Window_Free(); + return 0; +} + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" MALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("MALLOCED: %x", &ptr); + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); return ptr; } void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); - Platform_Log1(" CALLOC: %i", &size); void* ptr = size ? ta_alloc(size) : NULL; - Platform_Log1("CALLOCED: %x", &ptr); + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); if (ptr) Mem_Set(ptr, 0, size); return ptr; @@ -354,3 +369,21 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { _exit(code); } + From 6e5474959f09f9085316abee3a5d5acfd2c16717 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 20 Aug 2025 07:43:34 +1000 Subject: [PATCH 032/115] macOS: Fix makefile compiled builds not compiling due to not linking to Security framework --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b7bf9acd4..caa7afb2b 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ endif ifeq ($(PLAT),darwin) OBJECTS += $(BUILD_DIR)/src/Window_cocoa.o LIBS = - LDFLAGS = -rdynamic -framework Cocoa -framework OpenGL -framework IOKit -lobjc + LDFLAGS = -rdynamic -framework Security -framework Cocoa -framework OpenGL -framework IOKit -lobjc BUILD_DIR = build/macos TARGET = $(ENAME).app endif From 2bb57c93176e90b9b3879122975622f633173049 Mon Sep 17 00:00:00 2001 From: blue <28228415+iblowmymind@users.noreply.github.com> Date: Wed, 20 Aug 2025 10:52:05 +0300 Subject: [PATCH 033/115] macOS: Add application category type to Info.plist Allows Game Mode to be enabled when playing ClassiCube --- misc/macOS/info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/macOS/info.plist b/misc/macOS/info.plist index 21fe5b85d..09f752537 100644 --- a/misc/macOS/info.plist +++ b/misc/macOS/info.plist @@ -16,5 +16,7 @@ APPL CFBundleDisplayName ClassiCube + LSApplicationCategoryType + public.app-category.games From 05c44ceb9161c3bf437b15748d66457fdc976577 Mon Sep 17 00:00:00 2001 From: blue <28228415+iblowmymind@users.noreply.github.com> Date: Wed, 20 Aug 2025 11:27:00 +0300 Subject: [PATCH 034/115] Add application category for iOS Info.plist --- misc/ios/Info.plist | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/misc/ios/Info.plist b/misc/ios/Info.plist index a4b063668..dbc77cf4c 100644 --- a/misc/ios/Info.plist +++ b/misc/ios/Info.plist @@ -18,6 +18,8 @@ 1.0 CFBundleVersion 1 + LSApplicationCategoryType + public.app-category.games LSRequiresIPhoneOS NSPhotoLibraryAddUsageDescription @@ -138,4 +140,4 @@ - \ No newline at end of file + From 321a829243a6c9abc7a84d6705c0e9b47d542895 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 20 Aug 2025 23:32:01 +1000 Subject: [PATCH 035/115] iOS/macOS: Add other game mode keys to info.plist --- misc/ios/Info.plist | 4 ++++ misc/macOS/info.plist | 4 ++++ src/ps3/Graphics_PS3.c | 6 ------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/misc/ios/Info.plist b/misc/ios/Info.plist index dbc77cf4c..19ca19c41 100644 --- a/misc/ios/Info.plist +++ b/misc/ios/Info.plist @@ -20,6 +20,10 @@ 1 LSApplicationCategoryType public.app-category.games + GCSupportsGameMode + + LSSupportsGameMode + LSRequiresIPhoneOS NSPhotoLibraryAddUsageDescription diff --git a/misc/macOS/info.plist b/misc/macOS/info.plist index 09f752537..b14b52894 100644 --- a/misc/macOS/info.plist +++ b/misc/macOS/info.plist @@ -18,5 +18,9 @@ ClassiCube LSApplicationCategoryType public.app-category.games + GCSupportsGameMode + + LSSupportsGameMode + diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index b1f635be6..4cbc0e77d 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -483,12 +483,6 @@ void Gfx_SetViewport(int x, int y, int w, int h) { offset[3] = 0.0f; rsxSetViewport(context, x, y, w, h, zmin, zmax, scale, offset); - - // TODO: even needed? - for (int i = 0; i < 8; i++) - { - rsxSetViewportClip(context, i, w, h); - } } void Gfx_SetScissor(int x, int y, int w, int h) { From 4c1919cdee2a2e0c1c2d951ba0f7495cd7f2f80c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 22 Aug 2025 07:00:14 +1000 Subject: [PATCH 036/115] iOS: Enable users to access app's Documents folder --- misc/ios/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/ios/Info.plist b/misc/ios/Info.plist index 19ca19c41..b7ed5df2a 100644 --- a/misc/ios/Info.plist +++ b/misc/ios/Info.plist @@ -24,6 +24,8 @@ LSSupportsGameMode + UIFileSharingEnabled + LSRequiresIPhoneOS NSPhotoLibraryAddUsageDescription From 7bb3943467cadf35b20995d35beaa537e8634919 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 22 Aug 2025 07:20:51 +1000 Subject: [PATCH 037/115] BearSSL: Remove some unneeded defines --- third_party/bearssl/config.h | 71 +------------------- third_party/bearssl/inner.h | 122 ++++------------------------------- 2 files changed, 17 insertions(+), 176 deletions(-) diff --git a/third_party/bearssl/config.h b/third_party/bearssl/config.h index 3ef9dbf20..b12d3dca9 100644 --- a/third_party/bearssl/config.h +++ b/third_party/bearssl/config.h @@ -35,18 +35,11 @@ /* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ #ifdef NXDK -#define BR_AES_X86NI 0 -#define BR_ENABLE_INTRINSICS 0 -#define BR_SSE2 0 -#define BR_RDRAND 0 -#undef _WIN32 + #define BR_AES_X86NI 0 + #define BR_ENABLE_INTRINSICS 0 + #define BR_SSE2 0 #endif -/* Rely on ClassiCube's implementation for RNG */ -#define BR_USE_WIN32_RAND 0 -#define BR_USE_URANDOM 0 -#define BR_USE_GETENTROPY 0 - /* intrin.h doesn't exist in older TinyC */ #if defined __TINYC__ #define BR_INT128 0 @@ -107,54 +100,6 @@ #define BR_NO_ARITH_SHIFT 1 */ -/* - * When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode - * to automatically obtain quality randomness for seeding its internal - * PRNG. Since that opcode is present only in recent x86 CPU, its - * support is dynamically tested; if the current CPU does not support - * it, then another random source will be used, such as /dev/urandom or - * CryptGenRandom(). - * -#define BR_RDRAND 1 - */ - -/* - * When BR_USE_GETENTROPY is enabled, the SSL engine will use the - * getentropy() function to obtain quality randomness for seeding its - * internal PRNG. On Linux and FreeBSD, getentropy() is implemented by - * the standard library with the system call getrandom(); on OpenBSD, - * getentropy() is the system call, and there is no getrandom() wrapper, - * hence the use of the getentropy() function for maximum portability. - * - * If the getentropy() call fails, and BR_USE_URANDOM is not explicitly - * disabled, then /dev/urandom will be used as a fallback mechanism. On - * FreeBSD and OpenBSD, this does not change much, since /dev/urandom - * will block if not enough entropy has been obtained since last boot. - * On Linux, /dev/urandom might not block, which can be troublesome in - * early boot stages, which is why getentropy() is preferred. - * -#define BR_USE_GETENTROPY 1 - */ - -/* - * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom - * to automatically obtain quality randomness for seeding its internal - * PRNG. - * -#define BR_USE_URANDOM 1 - */ - -/* - * When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32 - * (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to - * automatically obtain quality randomness for seeding its internal PRNG. - * - * Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the - * former takes precedence. - * -#define BR_USE_WIN32_RAND 1 - */ - /* * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with * inline assembly which is shorter and/or faster. This should be used @@ -190,16 +135,6 @@ #define BR_SSE2 1 */ -/* - * When BR_POWER8 is enabled, the AES implementation using the POWER ISA - * 2.07 opcodes (available on POWER8 processors and later) is compiled. - * If this is not enabled explicitly, then that implementation will be - * compiled only if a compatible compiler is detected, _and_ the target - * architecture is POWER8 or later. - * -#define BR_POWER8 1 - */ - /* * When BR_INT128 is enabled, then code using the 'unsigned __int64' * and 'unsigned __int128' types will be used to leverage 64x64->128 diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index 3cc6b4c09..b9a80eb49 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -290,106 +290,22 @@ #endif /* - * RDRAND intrinsics are available on x86 (32-bit and 64-bit) with - * GCC 4.6+, Clang 3.7+ and MSC 2012+. + * Detect support for unaligned accesses with known endianness. + * + * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned + * accesses. + * + * POWER/PowerPC allows unaligned accesses when big-endian. */ -#ifndef BR_RDRAND -#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012) -#define BR_RDRAND 1 -#endif +#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED + +#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 +#define BR_LE_UNALIGNED 1 +#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ + && __BIG_ENDIAN__ +#define BR_BE_UNALIGNED 1 #endif -/* - * Determine type of OS for random number generation. Macro names and - * values are documented on: - * https://sourceforge.net/p/predef/wiki/OperatingSystems/ - * - * Win32's CryptGenRandom() should be available on Windows systems. - * - * /dev/urandom should work on all Unix-like systems (including macOS X). - * - * getentropy() is present on Linux (Glibc 2.25+), FreeBSD (12.0+) and - * OpenBSD (5.6+). For OpenBSD, there does not seem to be easy to use - * macros to test the minimum version, so we just assume that it is - * recent enough (last version without getentropy() has gone out of - * support in May 2015). - * - * Ideally we should use getentropy() on macOS (10.12+) too, but I don't - * know how to test the exact OS version with preprocessor macros. - * - * TODO: enrich the list of detected system. - */ - -#ifndef BR_USE_URANDOM -#if defined _AIX \ - || defined __ANDROID__ \ - || defined __FreeBSD__ \ - || defined __NetBSD__ \ - || defined __OpenBSD__ \ - || defined __DragonFly__ \ - || defined __linux__ \ - || (defined __sun && (defined __SVR4 || defined __svr4__)) \ - || (defined __APPLE__ && defined __MACH__) -#define BR_USE_URANDOM 1 -#endif -#endif - -#ifndef BR_USE_GETENTROPY -#if (defined __linux__ \ - && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \ - || (defined __FreeBSD__ && __FreeBSD__ >= 12) \ - || defined __OpenBSD__ -#define BR_USE_GETENTROPY 1 -#endif -#endif - -#ifndef BR_USE_WIN32_RAND -#if defined _WIN32 || defined _WIN64 -#define BR_USE_WIN32_RAND 1 -#endif -#endif - -/* - * POWER8 crypto support. We rely on compiler macros for the - * architecture, since we do not have a reliable, simple way to detect - * the required support at runtime (we could try running an opcode, and - * trapping the exception or signal on illegal instruction, but this - * induces some non-trivial OS dependencies that we would prefer to - * avoid if possible). - */ -#ifndef BR_POWER8 -#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__) -#define BR_POWER8 1 -#endif -#endif - -/* - * Detect endinanness on POWER8. - */ -#if BR_POWER8 -#if defined BR_POWER8_LE -#undef BR_POWER8_BE -#if BR_POWER8_LE -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_BE 1 -#endif -#elif defined BR_POWER8_BE -#undef BR_POWER8_LE -#if BR_POWER8_BE -#define BR_POWER8_LE 0 -#else -#define BR_POWER8_LE 1 -#endif -#else -#if __LITTLE_ENDIAN__ -#define BR_POWER8_LE 1 -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_LE 0 -#define BR_POWER8_BE 1 -#endif -#endif #endif /* @@ -408,21 +324,11 @@ * * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned * accesses. - * - * POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and - * later also allow unaligned accesses when little-endian. */ -#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED +#if !defined BR_LE_UNALIGNED #if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 #define BR_LE_UNALIGNED 1 -#elif BR_POWER8_BE -#define BR_BE_UNALIGNED 1 -#elif BR_POWER8_LE -#define BR_LE_UNALIGNED 1 -#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ - && __BIG_ENDIAN__ -#define BR_BE_UNALIGNED 1 #endif #endif From ac4dfe9df7aca77a9917809ccdd05a1938987fe1 Mon Sep 17 00:00:00 2001 From: Pear <20259871+TheRealPear@users.noreply.github.com> Date: Thu, 21 Aug 2025 12:36:25 -0400 Subject: [PATCH 038/115] Enable file sharing in Files app --- misc/ios/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/ios/Info.plist b/misc/ios/Info.plist index b7ed5df2a..695b3943a 100644 --- a/misc/ios/Info.plist +++ b/misc/ios/Info.plist @@ -26,6 +26,8 @@ UIFileSharingEnabled + LSSupportsOpeningDocumentsInPlace + LSRequiresIPhoneOS NSPhotoLibraryAddUsageDescription From a3e54ebcf3581372ac770e9d7e27d4d65db05d12 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 23 Aug 2025 12:22:54 +1000 Subject: [PATCH 039/115] Avoid calling strlen with BearSSL --- src/Http_Worker.c | 173 +++++----------------------- src/TexturePack.c | 6 + src/_HttpBase.h | 134 ++++++++++++++++++++- third_party/bearssl/config.h | 12 -- third_party/bearssl/inner.h | 24 ++++ third_party/bearssl/ssl_client.c | 2 +- third_party/bearssl/ssl_hs_client.c | 10 +- third_party/bearssl/x509_minimal.c | 2 +- 8 files changed, 196 insertions(+), 167 deletions(-) diff --git a/src/Http_Worker.c b/src/Http_Worker.c index d74509228..d9f70c269 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -1,131 +1,36 @@ #include "Core.h" -#ifndef CC_BUILD_WEB + +#if defined CC_BUILD_WEB +/* Implemented in web http backend without C worker thread(s) */ +#elif !defined CC_BUILD_NETWORKING +#include "Http.h" +#include "Game.h" + +void HttpRequest_Free(struct HttpRequest* request) { } + +cc_bool Http_GetResult(int reqID, struct HttpRequest* item) { + return false; +} + +int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) { + return -1; +} + +int Http_CheckProgress(int reqID) { + return -1; +} + +void Http_LogError(const char* action, const struct HttpRequest* item) { +} + +static void Http_NullInit(void) { } + +struct IGameComponent Http_Component = { + Http_NullInit +}; +#else #include "_HttpBase.h" -/* Ensures data buffer has enough space left to append amount bytes */ -static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) { - cc_uint32 newSize = req->size + amount; - cc_uint8* ptr; - if (newSize <= req->_capacity) return true; - - if (!req->_capacity) { - /* Allocate initial storage */ - req->_capacity = req->contentLength ? req->contentLength : 1; - req->_capacity = max(req->_capacity, newSize); - - ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1); - } else { - /* Reallocate if capacity reached */ - req->_capacity = newSize; - ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1); - } - - if (!ptr) return false; - req->data = ptr; - return true; -} - -/* Increases size and updates current progress */ -static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) { - req->size += read; - if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength); -} - - -/*########################################################################################################################* -*---------------------------------------------------Common backend code---------------------------------------------------* -*#########################################################################################################################*/ -static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) { - cc_string name, data; - int dataEnd; - String_UNSAFE_Separate(value, '=', &name, &data); - /* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */ - /* However only the __cfduid=xyz part of the cookie should be stored */ - dataEnd = String_IndexOf(&data, ';'); - if (dataEnd >= 0) data.length = dataEnd; - - EntryList_Set(req->cookies, &name, &data, '='); -} - -static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) { - int contentLen = 0; - Convert_ParseInt(value, &contentLen); - - if (contentLen <= 0) return; - req->contentLength = contentLen; -} - -/* Parses a HTTP header */ -static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { - static const cc_string httpVersion = String_FromConst("HTTP"); - cc_string name, value, parts[3]; - int numParts; - - /* HTTP[version] [status code] [status reason] */ - if (String_CaselessStarts(line, &httpVersion)) { - numParts = String_UNSAFE_Split(line, ' ', parts, 3); - if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode); - } - /* For all other headers: name: value */ - if (!String_UNSAFE_Separate(line, ':', &name, &value)) return; - - if (String_CaselessEqualsConst(&name, "ETag")) { - String_CopyToRawArray(req->etag, &value); - } else if (String_CaselessEqualsConst(&name, "Content-Length")) { - Http_ParseContentLength(req, &value); - } else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) { - /* dropbox stopped returning Content-Length header since switching to chunked transfer */ - /* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */ - Http_ParseContentLength(req, &value); - } else if (String_CaselessEqualsConst(&name, "Last-Modified")) { - String_CopyToRawArray(req->lastModified, &value); - } else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) { - Http_ParseCookie(req, &value); - } -} - -/* Adds a http header to the request headers. */ -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value); - -/* Adds all the appropriate headers for a request. */ -static void Http_SetRequestHeaders(struct HttpRequest* req) { - static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded"); - cc_string str, cookies; char cookiesBuffer[1024]; - int i; - - if (req->lastModified[0]) { - str = String_FromRawArray(req->lastModified); - Http_AddHeader(req, "If-Modified-Since", &str); - } - if (req->etag[0]) { - str = String_FromRawArray(req->etag); - Http_AddHeader(req, "If-None-Match", &str); - } - - if (req->data) Http_AddHeader(req, "Content-Type", &contentType); - if (!req->cookies || !req->cookies->count) return; - - String_InitArray(cookies, cookiesBuffer); - for (i = 0; i < req->cookies->count; i++) { - if (i) String_AppendConst(&cookies, "; "); - str = StringsBuffer_UNSAFE_Get(req->cookies, i); - String_AppendString(&cookies, &str); - } - Http_AddHeader(req, "Cookie", &cookies); -} - -/* TODO: Rewrite to use a local variable instead */ -static cc_string* Http_GetUserAgent_UNSAFE(void) { - static char userAgentBuffer[STRING_SIZE]; - static cc_string userAgent; - - String_InitArray(userAgent, userAgentBuffer); - String_AppendConst(&userAgent, GAME_APP_NAME); - String_AppendConst(&userAgent, Platform_AppNameSuffix); - return &userAgent; -} - - #if CC_NET_BACKEND == CC_NET_BACKEND_BUILTIN #include "Errors.h" #include "PackedCol.h" @@ -737,24 +642,6 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) { static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { return SSLBackend_DescribeError(res, dst); } -#elif !defined CC_BUILD_NETWORKING -/*########################################################################################################################* -*------------------------------------------------------Null backend-------------------------------------------------------* -*#########################################################################################################################*/ -#include "Errors.h" - -static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { - return false; -} - -static void HttpBackend_Init(void) { } - -static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value) { } - -static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) { - req->progress = 100; - return ERR_NOT_SUPPORTED; -} #endif diff --git a/src/TexturePack.c b/src/TexturePack.c index 4e5c02e72..4b9d0d4f4 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -578,6 +578,7 @@ static cc_result ExtractFrom(struct Stream* stream, const cc_string* path) { } #if defined CC_BUILD_PS1 || defined CC_BUILD_SATURN +/* Load hardcoded texture pack */ #include "../misc/ps1/classicubezip.h" static cc_result ExtractFromFile(const cc_string* path) { @@ -586,6 +587,11 @@ static cc_result ExtractFromFile(const cc_string* path) { return ExtractFrom(&stream, path); } +#elif !defined CC_BUILD_FILESYSTEM +/* E.g. GBA/32X don't support textures at all */ +static cc_result ExtractFromFile(const cc_string* path) { + return ERR_NOT_SUPPORTED; +} #else static cc_result ExtractFromFile(const cc_string* path) { struct Stream stream; diff --git a/src/_HttpBase.h b/src/_HttpBase.h index 3ac646c98..af32751cf 100644 --- a/src/_HttpBase.h +++ b/src/_HttpBase.h @@ -23,14 +23,11 @@ void HttpRequest_Free(struct HttpRequest* request) { } #define HttpRequest_Copy(dst, src) Mem_Copy(dst, src, sizeof(struct HttpRequest)) + /*########################################################################################################################* *----------------------------------------------------Http requests list---------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_NETWORKING - #define HTTP_DEF_ELEMS 10 -#else - #define HTTP_DEF_ELEMS 1 /* TODO better unused code removal */ -#endif +#define HTTP_DEF_ELEMS 10 struct RequestList { int count, capacity; @@ -111,6 +108,133 @@ static void RequestList_Free(struct RequestList* list) { } +/*########################################################################################################################* +*---------------------------------------------------Common buffer code----------------------------------------------------* +*#########################################################################################################################*/ +/* Ensures data buffer has enough space left to append amount bytes */ +static cc_bool Http_BufferExpand(struct HttpRequest* req, cc_uint32 amount) { + cc_uint32 newSize = req->size + amount; + cc_uint8* ptr; + if (newSize <= req->_capacity) return true; + + if (!req->_capacity) { + /* Allocate initial storage */ + req->_capacity = req->contentLength ? req->contentLength : 1; + req->_capacity = max(req->_capacity, newSize); + + ptr = (cc_uint8*)Mem_TryAlloc(req->_capacity, 1); + } else { + /* Reallocate if capacity reached */ + req->_capacity = newSize; + ptr = (cc_uint8*)Mem_TryRealloc(req->data, newSize, 1); + } + + if (!ptr) return false; + req->data = ptr; + return true; +} + +/* Increases size and updates current progress */ +static void Http_BufferExpanded(struct HttpRequest* req, cc_uint32 read) { + req->size += read; + if (req->contentLength) req->progress = (int)(100.0f * req->size / req->contentLength); +} + + +/*########################################################################################################################* +*---------------------------------------------------Common header code----------------------------------------------------* +*#########################################################################################################################*/ +static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) { + cc_string name, data; + int dataEnd; + String_UNSAFE_Separate(value, '=', &name, &data); + /* Cookie is: __cfduid=xyz; expires=abc; path=/; domain=.classicube.net; HttpOnly */ + /* However only the __cfduid=xyz part of the cookie should be stored */ + dataEnd = String_IndexOf(&data, ';'); + if (dataEnd >= 0) data.length = dataEnd; + + EntryList_Set(req->cookies, &name, &data, '='); +} + +static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) { + int contentLen = 0; + Convert_ParseInt(value, &contentLen); + + if (contentLen <= 0) return; + req->contentLength = contentLen; +} + +/* Parses a HTTP header */ +static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { + static const cc_string httpVersion = String_FromConst("HTTP"); + cc_string name, value, parts[3]; + int numParts; + + /* HTTP[version] [status code] [status reason] */ + if (String_CaselessStarts(line, &httpVersion)) { + numParts = String_UNSAFE_Split(line, ' ', parts, 3); + if (numParts >= 2) Convert_ParseInt(&parts[1], &req->statusCode); + } + /* For all other headers: name: value */ + if (!String_UNSAFE_Separate(line, ':', &name, &value)) return; + + if (String_CaselessEqualsConst(&name, "ETag")) { + String_CopyToRawArray(req->etag, &value); + } else if (String_CaselessEqualsConst(&name, "Content-Length")) { + Http_ParseContentLength(req, &value); + } else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) { + /* dropbox stopped returning Content-Length header since switching to chunked transfer */ + /* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */ + Http_ParseContentLength(req, &value); + } else if (String_CaselessEqualsConst(&name, "Last-Modified")) { + String_CopyToRawArray(req->lastModified, &value); + } else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) { + Http_ParseCookie(req, &value); + } +} + +/* Adds a http header to the request headers. */ +static void Http_AddHeader(struct HttpRequest* req, const char* key, const cc_string* value); + +/* Adds all the appropriate headers for a request. */ +static void Http_SetRequestHeaders(struct HttpRequest* req) { + static const cc_string contentType = String_FromConst("application/x-www-form-urlencoded"); + cc_string str, cookies; char cookiesBuffer[1024]; + int i; + + if (req->lastModified[0]) { + str = String_FromRawArray(req->lastModified); + Http_AddHeader(req, "If-Modified-Since", &str); + } + if (req->etag[0]) { + str = String_FromRawArray(req->etag); + Http_AddHeader(req, "If-None-Match", &str); + } + + if (req->data) Http_AddHeader(req, "Content-Type", &contentType); + if (!req->cookies || !req->cookies->count) return; + + String_InitArray(cookies, cookiesBuffer); + for (i = 0; i < req->cookies->count; i++) { + if (i) String_AppendConst(&cookies, "; "); + str = StringsBuffer_UNSAFE_Get(req->cookies, i); + String_AppendString(&cookies, &str); + } + Http_AddHeader(req, "Cookie", &cookies); +} + +/* TODO: Rewrite to use a local variable instead */ +static cc_string* Http_GetUserAgent_UNSAFE(void) { + static char userAgentBuffer[STRING_SIZE]; + static cc_string userAgent; + + String_InitArray(userAgent, userAgentBuffer); + String_AppendConst(&userAgent, GAME_APP_NAME); + String_AppendConst(&userAgent, Platform_AppNameSuffix); + return &userAgent; +} + + /*########################################################################################################################* *--------------------------------------------------Common downloader code-------------------------------------------------* *#########################################################################################################################*/ diff --git a/third_party/bearssl/config.h b/third_party/bearssl/config.h index b12d3dca9..09791b8ba 100644 --- a/third_party/bearssl/config.h +++ b/third_party/bearssl/config.h @@ -32,18 +32,6 @@ * non-zero integer (normally 1). If the macro is not defined, then * autodetection applies. */ - -/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ -#ifdef NXDK - #define BR_AES_X86NI 0 - #define BR_ENABLE_INTRINSICS 0 - #define BR_SSE2 0 -#endif - -/* intrin.h doesn't exist in older TinyC */ -#if defined __TINYC__ -#define BR_INT128 0 -#endif /* * When BR_64 is enabled, 64-bit integer types are assumed to be diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index b9a80eb49..57ccd0600 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -35,6 +35,30 @@ #include "config.h" #include "bearssl.h" +/* ==== BEG ClassiCube specific ==== */ +static size_t br_strlen(const char* a) { + int i = 0; + while (*a++) i++; + return i; +} + +#define br_memcpy memcpy +#define br_memset memset +#define br_memmove memmove + +/* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ +#ifdef NXDK + #define BR_AES_X86NI 0 + #define BR_ENABLE_INTRINSICS 0 + #define BR_SSE2 0 +#endif + +/* intrin.h doesn't exist in older TinyC */ +#if defined __TINYC__ + #define BR_INT128 0 +#endif +/* ==== END ClassiCube specific ==== */ + /* * On MSVC, disable the warning about applying unary minus on an * unsigned type: it is standard, we do it all the time, and for diff --git a/third_party/bearssl/ssl_client.c b/third_party/bearssl/ssl_client.c index 28c404b83..7975bcace 100644 --- a/third_party/bearssl/ssl_client.c +++ b/third_party/bearssl/ssl_client.c @@ -64,7 +64,7 @@ br_ssl_client_reset(br_ssl_client_context *cc, if (server_name == NULL) { cc->eng.server_name[0] = 0; } else { - n = strlen(server_name) + 1; + n = br_strlen(server_name) + 1; if (n > sizeof cc->eng.server_name) { br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM); return 0; diff --git a/third_party/bearssl/ssl_hs_client.c b/third_party/bearssl/ssl_hs_client.c index 1a1cf4b31..8aeebe505 100644 --- a/third_party/bearssl/ssl_hs_client.c +++ b/third_party/bearssl/ssl_hs_client.c @@ -1246,7 +1246,7 @@ br_ssl_hs_client_run(void *t0ctx) /* copy-protocol-name */ size_t idx = T0_POP(); - size_t len = strlen(ENG->protocol_names[idx]); + size_t len = br_strlen(ENG->protocol_names[idx]); memcpy(ENG->pad, ENG->protocol_names[idx], len); T0_PUSH(len); @@ -1346,7 +1346,7 @@ br_ssl_hs_client_run(void *t0ctx) } len = 6; for (u = 0; u < ENG->protocol_names_num; u ++) { - len += 1 + strlen(ENG->protocol_names[u]); + len += 1 + br_strlen(ENG->protocol_names[u]); } T0_PUSH(len); @@ -1591,10 +1591,10 @@ br_ssl_hs_client_run(void *t0ctx) } break; case 63: { - /* strlen */ + /* br_strlen */ void *str = (unsigned char *)ENG + (size_t)T0_POP(); - T0_PUSH((uint32_t)strlen(str)); + T0_PUSH((uint32_t)br_strlen(str)); } break; @@ -1766,7 +1766,7 @@ br_ssl_hs_client_run(void *t0ctx) const char *name; name = ENG->protocol_names[u]; - if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { + if (len == br_strlen(name) && memcmp(ENG->pad, name, len) == 0) { T0_PUSH(u); T0_RET(); } diff --git a/third_party/bearssl/x509_minimal.c b/third_party/bearssl/x509_minimal.c index b3079deca..9611a8e77 100644 --- a/third_party/bearssl/x509_minimal.c +++ b/third_party/bearssl/x509_minimal.c @@ -1440,7 +1440,7 @@ br_x509_minimal_run(void *t0ctx) T0_PUSH(0); T0_RET(); } - n1 = strlen(CTX->server_name); + n1 = br_strlen(CTX->server_name); n2 = CTX->pad[0]; if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { T0_PUSHi(-1); From aa175c75ac5273116410f86fcbfcf44c2571f17c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 23 Aug 2025 12:40:12 +1000 Subject: [PATCH 040/115] Fix platforms without networking support not compiling --- src/Http_Worker.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Http_Worker.c b/src/Http_Worker.c index d9f70c269..d0cc18b2d 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -15,13 +15,28 @@ cc_bool Http_GetResult(int reqID, struct HttpRequest* item) { int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) { return -1; } +int Http_AsyncGetData(const cc_string* url, cc_uint8 flags) { + return -1; +} +int Http_AsyncGetHeaders(const cc_string* url, cc_uint8 flags) { + return -1; +} +int Http_AsyncPostData(const cc_string* url, cc_uint8 flags, const void* data, cc_uint32 size, struct StringsBuffer* cookies) { + return -1; +} +int Http_AsyncGetDataEx(const cc_string* url, cc_uint8 flags, const cc_string* lastModified, const cc_string* etag, struct StringsBuffer* cookies) { + return -1; +} int Http_CheckProgress(int reqID) { return -1; } -void Http_LogError(const char* action, const struct HttpRequest* item) { -} +void Http_LogError(const char* action, const struct HttpRequest* item) { } + +void Http_TryCancel(int reqID) { } + +void Http_UrlEncodeUtf8(cc_string* dst, const cc_string* src) { } static void Http_NullInit(void) { } From dfb014d4a850a66d84e78160f85927c6b55b4734 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 23 Aug 2025 13:38:58 +1000 Subject: [PATCH 041/115] Mac classic: Use softmin GPU backend for 68k build --- misc/macclassic/Makefile_68k | 2 +- src/Graphics_SoftMin.c | 4 ++-- src/Http_Worker.c | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/misc/macclassic/Makefile_68k b/misc/macclassic/Makefile_68k index 070a6ba64..4c8d88342 100644 --- a/misc/macclassic/Makefile_68k +++ b/misc/macclassic/Makefile_68k @@ -19,7 +19,7 @@ ifdef ARCH_68040 else TARGET := ClassiCube-68k BUILD_DIR := build/mac_68k - CFLAGS += -DCC_BUILD_NOFPU -DCC_BUILD_TINYMEM + CFLAGS += -DCC_BUILD_NOFPU -DCC_BUILD_TINYMEM -DCC_GFX_BACKEND=CC_GFX_BACKEND_SOFTMIN endif SOURCE_DIR := src diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index 5d388558c..e6689441f 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -34,8 +34,8 @@ void Gfx_FreeState(void) { } void Gfx_Create(void) { - Gfx.MaxTexWidth = 16; - Gfx.MaxTexHeight = 16; + Gfx.MaxTexWidth = 256; + Gfx.MaxTexHeight = 256; Gfx.Created = true; Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; Gfx.Limitations = GFX_LIMIT_MINIMAL | GFX_LIMIT_WORLD_ONLY; diff --git a/src/Http_Worker.c b/src/Http_Worker.c index d0cc18b2d..9f843cdaa 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -12,6 +12,10 @@ cc_bool Http_GetResult(int reqID, struct HttpRequest* item) { return false; } +cc_bool Http_GetCurrent(int* reqID, int* progress) { + return false; +} + int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) { return -1; } @@ -28,9 +32,7 @@ int Http_AsyncGetDataEx(const cc_string* url, cc_uint8 flags, const cc_string* l return -1; } -int Http_CheckProgress(int reqID) { - return -1; -} +int Http_CheckProgress(int reqID) { return -1; } void Http_LogError(const char* action, const struct HttpRequest* item) { } @@ -38,6 +40,8 @@ void Http_TryCancel(int reqID) { } void Http_UrlEncodeUtf8(cc_string* dst, const cc_string* src) { } +void Http_ClearPending(void) { } + static void Http_NullInit(void) { } struct IGameComponent Http_Component = { From aabc23348bb6e13e0f1cd041d4a6a7d415ba92d3 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 23 Aug 2025 23:34:37 +1000 Subject: [PATCH 042/115] WIP Atari ST port --- Makefile | 2 + misc/atari_st/Makefile | 36 ++++ src/3ds/Graphics_3DS.c | 4 +- src/Bitmap.c | 33 ++-- src/Core.h | 22 +++ src/Deflate.c | 30 ++++ src/ExtMath.c | 2 +- src/Graphics_SoftGPU.c | 4 +- src/Graphics_SoftMin.c | 4 +- src/Input.c | 2 +- src/Vorbis.c | 3 + src/atari_st/Platform_Atari.c | 322 ++++++++++++++++++++++++++++++++++ src/atari_st/Window_Atari.c | 205 ++++++++++++++++++++++ src/gba/Window_GBA.c | 1 - src/gcwii/Graphics_GCWii.c | 4 +- src/ps1/Graphics_PS1.c | 4 +- src/ps2/Graphics_PS2.c | 4 +- src/ps3/Graphics_PS3.c | 4 +- src/psp/Graphics_PSP.c | 4 +- src/psvita/Graphics_PSVita.c | 4 +- src/saturn/Graphics_Saturn.c | 4 +- src/xbox/Graphics_Xbox.c | 4 +- 22 files changed, 663 insertions(+), 39 deletions(-) create mode 100644 misc/atari_st/Makefile create mode 100644 src/atari_st/Platform_Atari.c create mode 100644 src/atari_st/Window_Atari.c diff --git a/Makefile b/Makefile index caa7afb2b..a94f5dfe1 100644 --- a/Makefile +++ b/Makefile @@ -304,6 +304,8 @@ amiga_68k: $(MAKE) -f misc/amiga/Makefile_68k amiga_ppc: $(MAKE) -f misc/amiga/Makefile_ppc +atari_st: + $(MAKE) -f misc/atari_st/Makefile # Cleans up all build .o files clean: diff --git a/misc/atari_st/Makefile b/misc/atari_st/Makefile new file mode 100644 index 000000000..328989a11 --- /dev/null +++ b/misc/atari_st/Makefile @@ -0,0 +1,36 @@ +TARGET := ClassiCube +BUILD_DIR := build/atari_st +SOURCE_DIRS := src src/atari_st + +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +CC = vc +tos +CFLAGS = -O1 -DPLAT_ATARIOS + +AS = vasmm68k_mot +ASFLAGS = -Fvobj -m68000 -no-fpu + +LDFLAGS = $(CFLAGS) +LDLIBS = -lm + +#--------------------------------------------------------------------------------- +# targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).tos + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(TARGET).tos: $(OBJS) + $(CC) $(LDFLAGS) -final -o $@ $^ $(LDLIBS) + +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/%.o : src/atari_st/%.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/3ds/Graphics_3DS.c b/src/3ds/Graphics_3DS.c index 9ec7dc877..3db6521dd 100644 --- a/src/3ds/Graphics_3DS.c +++ b/src/3ds/Graphics_3DS.c @@ -201,7 +201,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 8x8 dummy white texture @@ -213,7 +213,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/Bitmap.c b/src/Bitmap.c index 3d445021e..e4077ec1f 100644 --- a/src/Bitmap.c +++ b/src/Bitmap.c @@ -64,7 +64,7 @@ void Bitmap_Scale(struct Bitmap* dst, struct Bitmap* src, /*########################################################################################################################* -*------------------------------------------------------PNG decoder--------------------------------------------------------* +*------------------------------------------------------PNG common---------------------------------------------------------* *#########################################################################################################################*/ #define PNG_IHDR_SIZE 13 #define PNG_PALETTE 256 @@ -79,7 +79,6 @@ enum PngFilter { PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH }; -typedef void (*Png_RowExpander)(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst); static const cc_uint8 pngSig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 }; /* 5.2 PNG signature */ @@ -87,6 +86,17 @@ cc_bool Png_Detect(const cc_uint8* data, cc_uint32 len) { return len >= PNG_SIG_SIZE && Mem_Equal(data, pngSig, PNG_SIG_SIZE); } + +/*########################################################################################################################* +*------------------------------------------------------PNG decoder--------------------------------------------------------* +*#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { + return ERR_NOT_SUPPORTED; +} +#else +typedef void (*Png_RowExpander)(int width, BitmapCol* palette, cc_uint8* src, BitmapCol* dst); + /* 9 Filtering */ /* 13.9 Filtering */ static void Png_ReconstructFirst(cc_uint8 type, cc_uint8 bytesPerPixel, cc_uint8* line, cc_uint32 lineLen) { @@ -329,11 +339,6 @@ static BitmapCol ExpandRGB(cc_uint8 bitsPerSample, int r, int g, int b) { return BitmapCol_Make(r, g, b, 0); } -#ifdef CC_BUILD_32X -cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { - return ERR_NOT_SUPPORTED; -} -#else cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { cc_uint8 tmp[64]; cc_uint32 dataSize, fourCC; @@ -559,7 +564,13 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { /*########################################################################################################################* *------------------------------------------------------PNG encoder--------------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_FILESYSTEM +#if !defined CC_BUILD_FILESYSTEM +/* No point including encoding code when can't save screenshots anyways */ +cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, + Png_RowGetter getRow, cc_bool alpha, void* ctx) { + return ERR_NOT_SUPPORTED; +} +#else static void Png_Filter(cc_uint8 filter, const cc_uint8* cur, const cc_uint8* prior, cc_uint8* best, int lineLen, int bpp) { /* 3 bytes per pixel constant */ cc_uint8 a, b, c; @@ -749,11 +760,5 @@ cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, Mem_Free(buffer); return res; } -#else -/* No point including encoding code when can't save screenshots anyways */ -cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream, - Png_RowGetter getRow, cc_bool alpha, void* ctx) { - return ERR_NOT_SUPPORTED; -} #endif diff --git a/src/Core.h b/src/Core.h index c6defa787..de2b3f433 100644 --- a/src/Core.h +++ b/src/Core.h @@ -171,6 +171,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_PLUGINS #define CC_BUILD_FILESYSTEM #define CC_BUILD_ADVLIGHTING +#define CC_BUILD_COMPRESSION /*#define CC_BUILD_GL11*/ #ifndef CC_BUILD_MANUAL @@ -269,6 +270,25 @@ typedef cc_uint8 cc_bool; #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU +#elif defined PLAT_ATARIOS + #undef CC_BUILD_FREETYPE + #define CC_BUILD_ATARIOS + #define CC_BUILD_COOPTHREADED + #define CC_BUILD_LOWMEM + #define CC_BUILD_NOMUSIC + #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_RESOURCES + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_NETWORKING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION + #define CC_BUILD_MAXSTACK (32 * 1024) + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ + #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL + #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTMIN #elif defined __linux__ #define CC_BUILD_LINUX #define CC_BUILD_POSIX @@ -493,6 +513,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_NETWORKING #undef CC_BUILD_ADVLIGHTING #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI @@ -593,6 +614,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_NETWORKING #undef CC_BUILD_ADVLIGHTING #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define CC_DISABLE_UI diff --git a/src/Deflate.c b/src/Deflate.c index 89ef37444..3d30f3980 100644 --- a/src/Deflate.c +++ b/src/Deflate.c @@ -141,6 +141,19 @@ cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) { /*########################################################################################################################* *--------------------------------------------------Inflate (decompress)---------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +void Inflate_Init2(struct InflateState* state, struct Stream* source) { + Process_Abort("Should never be called"); +} + +void Inflate_Process(struct InflateState* s) { + Process_Abort("Should never be called"); +} + +void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, struct Stream* underlying) { + Process_Abort("Should never be called"); +} +#else enum INFLATE_STATE_ { INFLATE_STATE_HEADER, INFLATE_STATE_UNCOMPRESSED_HEADER, INFLATE_STATE_UNCOMPRESSED_DATA, INFLATE_STATE_DYNAMIC_HEADER, @@ -787,11 +800,18 @@ void Inflate_MakeStream2(struct Stream* stream, struct InflateState* state, stru stream->meta.inflate = state; stream->Read = Inflate_StreamRead; } +#endif /*########################################################################################################################* *---------------------------------------------------Deflate (compress)----------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +void GZip_MakeStream(struct Stream* stream, struct GZipState* state, struct Stream* underlying) { + Process_Abort("Should never be called"); +} +#else + /* these are copies of len_base and dist_base, with UINT16_MAX instead of 0 for sentinel cutoff */ static const cc_uint16 deflate_len[30] = { 3,4,5,6,7,8,9,10,11,13, @@ -1141,11 +1161,19 @@ void ZLib_MakeStream(struct Stream* stream, struct ZLibState* state, struct Stre stream->Write = ZLib_StreamWriteFirst; stream->Close = ZLib_StreamClose; } +#endif /*########################################################################################################################* *--------------------------------------------------------ZipReader--------------------------------------------------------* *#########################################################################################################################*/ +#if !defined CC_BUILD_COMPRESSION +cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_ProcessEntry processor, + struct ZipEntry* entries, int maxEntries) { + return ERR_NOT_SUPPORTED; +} +#else + #define ZIP_MAXNAMELEN 512 /* Stores state for reading and processing entries in a .zip archive */ struct ZipState { @@ -1337,3 +1365,5 @@ cc_result Zip_Extract(struct Stream* source, Zip_SelectEntry selector, Zip_Proce } return 0; } +#endif + diff --git a/src/ExtMath.c b/src/ExtMath.c index 5c31554d6..eb5563ac5 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -98,7 +98,7 @@ float sqrtf(float x) { } #elif defined __GNUC__ || defined NXDK /* Defined in .h using builtins */ -#elif defined __TINYC__ +#elif defined __TINYC__ || defined CC_BUILD_ATARIOS /* Older versions of TinyC don't support fabsf or sqrtf */ /* Those can be used though if compiling with newer TinyC */ /* versions for a very small performance improvement */ diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index 9a591248f..ad32d9596 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -23,7 +23,7 @@ static int db_stride; static void* gfx_vertices; static GfxResourceID white_square; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -33,7 +33,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/Graphics_SoftMin.c b/src/Graphics_SoftMin.c index e6689441f..2ceba1d57 100644 --- a/src/Graphics_SoftMin.c +++ b/src/Graphics_SoftMin.c @@ -18,7 +18,7 @@ static int cb_stride; static void* gfx_vertices; static GfxResourceID white_square; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -28,7 +28,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/Input.c b/src/Input.c index 6c9da0736..7f9e16a1b 100644 --- a/src/Input.c +++ b/src/Input.c @@ -327,7 +327,7 @@ struct InputDevice TouchDevice = { struct Pointer Pointers[INPUT_MAX_POINTERS]; struct _PointerHooks PointerHooks; -void Pointer_SetPressed(int idx, cc_bool pressed) { +static void Pointer_SetPressed(int idx, cc_bool pressed) { if (pressed) { if (PointerHooks.DownHook && PointerHooks.DownHook(idx)) return; diff --git a/src/Vorbis.c b/src/Vorbis.c index f0fc89263..f69a418cd 100644 --- a/src/Vorbis.c +++ b/src/Vorbis.c @@ -7,6 +7,7 @@ #include "Errors.h" #include "Stream.h" +#if !defined CC_BUILD_ATARIOS /*########################################################################################################################* *-------------------------------------------------------Ogg stream--------------------------------------------------------* *#########################################################################################################################*/ @@ -1672,3 +1673,5 @@ int Vorbis_OutputFrame(struct VorbisState* ctx, cc_int16* data) { ctx->prevBlockSize = ctx->curBlockSize; return (prevQrtr + curQrtr) * ctx->channels; } +#endif + diff --git a/src/atari_st/Platform_Atari.c b/src/atari_st/Platform_Atari.c new file mode 100644 index 000000000..26871a2af --- /dev/null +++ b/src/atari_st/Platform_Atari.c @@ -0,0 +1,322 @@ +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../Options.h" +#include "../Animations.h" + +#include +#include +#include + +#include "../../third_party/tinyalloc/tinyalloc.c" + +typedef volatile uint8_t vu8; +typedef volatile uint16_t vu16; +typedef volatile uint32_t vu32; + +const cc_result ReturnCode_FileShareViolation = 1000000000; // not used +const cc_result ReturnCode_FileNotFound = -1; +const cc_result ReturnCode_DirectoryExists = -1; +const cc_result ReturnCode_SocketInProgess = -1; +const cc_result ReturnCode_SocketWouldBlock = -1; +const cc_result ReturnCode_SocketDropped = -1; + +const char* Platform_AppNameSuffix = " GBA"; +cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; + + +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + //RunGame(); + RunProgram(argc, argv); + } + + Window_Free(); + return 0; +} + +/*########################################################################################################################* +*---------------------------------------------------------Memory----------------------------------------------------------* +*#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + +void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + void* ptr = size ? ta_alloc(size) : NULL; + Platform_Log2("MALLOCED: %x (%i bytes)", &ptr, &size); + return ptr; +} + +void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + void* ptr = size ? ta_alloc(size) : NULL; + Platform_Log2("CALLOCED: %x (%i bytes)", &ptr, &size); + + if (ptr) Mem_Set(ptr, 0, size); + return ptr; +} + +void* Mem_TryRealloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize) { + return NULL; // TODO +} + +void Mem_Free(void* mem) { + if (mem) ta_free(mem); +} + + +/*########################################################################################################################* +*------------------------------------------------------Logging/Time-------------------------------------------------------* +*#########################################################################################################################*/ +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + + cc_uint64 delta = end - beg; + return 1; // TODO implement +} + +cc_uint64 Stopwatch_Measure(void) { + return 1; // TODO implement +} + +void Platform_Log(const char* msg, int len) { + for (int i = 0; i < len; i++) + { + Bconout(2, msg[i]); + } + Bconout(2, '\r'); + Bconout(2, '\n'); +} + +TimeMS DateTime_CurrentUTC(void) { + return 0; +} + +void DateTime_CurrentLocal(struct cc_datetime* t) { + Mem_Set(t, 0, sizeof(*t)); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Crash handling----------------------------------------------------* +*#########################################################################################################################*/ +void CrashHandler_Install(void) { +} + +void Process_Abort2(cc_result result, const char* raw_msg) { + Platform_LogConst(raw_msg); + exit(0); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Directory/File------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_EncodePath(cc_filepath* dst, const cc_string* path) { + char* str = dst->buffer; + String_EncodeUtf8(str, path); +} + +void Directory_GetCachePath(cc_string* path) { } + +cc_result Directory_Create(const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +int File_Exists(const cc_filepath* path) { + return false; +} + +cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Open(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Create(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Close(cc_file file) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Seek(cc_file file, int offset, int seekType) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Position(cc_file file, cc_uint32* pos) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Length(cc_file file, cc_uint32* len) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +// !!! NOTE: PSP uses cooperative multithreading (not preemptive multithreading) !!! +void Thread_Sleep(cc_uint32 milliseconds) { + // TODO probably wrong +} + +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + *handle = NULL; +} + +void Thread_Detach(void* handle) { +} + +void Thread_Join(void* handle) { +} + +void* Mutex_Create(const char* name) { + return NULL; +} + +void Mutex_Free(void* handle) { +} + +void Mutex_Lock(void* handle) { +} + +void Mutex_Unlock(void* handle) { +} + +void* Waitable_Create(const char* name) { + return NULL; +} + +void Waitable_Free(void* handle) { +} + +void Waitable_Signal(void* handle) { +} + +void Waitable_Wait(void* handle) { +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { +} + + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +void Socket_Close(cc_socket s) { +} + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ + +void Platform_Init(void) { + LONG size = (LONG)Malloc(-1); + char* ptr = Malloc(size); + + char* heap_beg = ptr; + char* heap_end = ptr + size; + ta_init(heap_beg, heap_end, 256, 16, 4); + + int size_ = (int)(heap_end - heap_beg); + Platform_Log3("HEAP: %i bytes (%x -> %x)", &size_, &heap_beg, &heap_end); +} + +void Platform_Free(void) { } + +cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { + return false; +} + +cc_bool Process_OpenSupported = false; +cc_result Process_StartOpen(const cc_string* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} + +cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return 0; +} + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + return 0; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +void Process_Exit(cc_result code) { exit(code); } + diff --git a/src/atari_st/Window_Atari.c b/src/atari_st/Window_Atari.c new file mode 100644 index 000000000..7209e8bcb --- /dev/null +++ b/src/atari_st/Window_Atari.c @@ -0,0 +1,205 @@ +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Camera.h" + +#include +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 + +/*########################################################################################################################* +*------------------------------------------------------General data-------------------------------------------------------* +*#########################################################################################################################*/ +struct _DisplayData DisplayInfo; +struct cc_window WindowInfo; + +// TODO backup palette +void Window_PreInit(void) { + for (int i = 0; i < 16; i++) + { + int R = (i & 0x1) >> 0; + int G = (i & 0x2) >> 1; + int B = (i & 0xC) >> 2; + + R = R ? ((R << 3) | 0x07) : 0; + G = G ? ((G << 3) | 0x07) : 0; + B = B ? ((B << 2) | 0x03) : 0; + + Setcolor(i, (R << 8) | (G << 4) | B); + } +} + +void Window_Init(void) { + DisplayInfo.Width = SCREEN_WIDTH; + DisplayInfo.Height = SCREEN_HEIGHT; + DisplayInfo.ScaleX = 0.5f; + DisplayInfo.ScaleY = 0.5f; + + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; + Window_Main.Focused = true; + + Window_Main.Exists = true; + Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; + Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; +} + +void Window_Free(void) { } + +void Window_Create2D(int width, int height) { +} + +void Window_Create3D(int width, int height) { +} + +void Window_Destroy(void) { } + +void Window_SetTitle(const cc_string* title) { } +void Clipboard_GetText(cc_string* value) { } +void Clipboard_SetText(const cc_string* value) { } + +int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; } +cc_result Window_EnterFullscreen(void) { return 0; } +cc_result Window_ExitFullscreen(void) { return 0; } +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } +void Window_SetSize(int width, int height) { } + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +void Window_ProcessEvents(float delta) { + +} + +void Cursor_SetPosition(int x, int y) { } // Makes no sense for PSP +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } + +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +void Gamepads_Init(void) { } + +void Gamepads_Process(float delta) { } + + +/*########################################################################################################################* +*------------------------------------------------------Framebuffer--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels"); + bmp->width = width; + bmp->height = height; +} + +// TODO should be done in assembly.. search up 'chunky to planar atari ST' +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO + UWORD* ptr = Physbase(); + Mem_Set(ptr, 0, 32000); + int idx = 0; + + UWORD* plane1 = ptr + 0; + UWORD* plane2 = ptr + 4000; + UWORD* plane3 = ptr + 8000; + UWORD* plane4 = ptr + 12000; + + for (int y = 0; y < r.height; y++) + { + BitmapCol* row = Bitmap_GetRow(bmp, y); + + for (int x = 0; x < r.width; x++, idx++) + { + // TODO optimise + BitmapCol col = row[x]; + cc_uint8 R = BitmapCol_R(col) >> 7; + cc_uint8 G = BitmapCol_G(col) >> 7; + cc_uint8 B = BitmapCol_B(col) >> 6; + + //int pal = R | (G << 1) | (B << 2); + int b1 = B & 0x01, b2 = (B >> 1); + + plane1[idx >> 4] |= R << (idx & 0x0F); + plane2[idx >> 4] |= G << (idx & 0x0F); + plane3[idx >> 4] |= b1<< (idx & 0x0F); + plane4[idx >> 4] |= b2<< (idx & 0x0F); + } + } +} +/* +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO + UWORD* ptr = Physbase(); + + for (int y = 0; y < r.height; ++y) + { + BitmapCol* row = Bitmap_GetRow(bmp, y); + UWORD* src = ptr + 80 * y; + Mem_Set(src, 0, sizeof(UWORD) * 80); + + for (int x = 0; x < r.width; ++x) + { + // TODO optimise + BitmapCol col = row[x]; + cc_uint8 R = BitmapCol_R(col) >> 7; + cc_uint8 G = BitmapCol_G(col) >> 7; + cc_uint8 B = BitmapCol_B(col) >> 6; + + int idx = R | (G << 1) | (B << 2); + src[x] |= idx << ((x & 0x03) * 4); + } + } +} +*/ + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + + +/*########################################################################################################################* +*------------------------------------------------------Soft keyboard------------------------------------------------------* +*#########################################################################################################################*/ +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { +} + +void OnscreenKeyboard_SetText(const cc_string* text) { } + +void OnscreenKeyboard_Close(void) { +} + + +/*########################################################################################################################* +*-------------------------------------------------------Misc/Other--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_ShowDialog(const char* title, const char* msg) { + /* TODO implement */ + //Platform_LogConst(title); + //Platform_LogConst(msg); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + diff --git a/src/gba/Window_GBA.c b/src/gba/Window_GBA.c index 4b9867b30..ca7df6f6a 100644 --- a/src/gba/Window_GBA.c +++ b/src/gba/Window_GBA.c @@ -142,7 +142,6 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { } void Window_FreeFramebuffer(struct Bitmap* bmp) { - Mem_Free(bmp->scan0); } diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index 822c035f2..e3321c246 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -77,7 +77,7 @@ void Gfx_Free(void) { } cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 4x4 dummy white texture (textures must be at least 1 4x4 tile) @@ -88,7 +88,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/ps1/Graphics_PS1.c b/src/ps1/Graphics_PS1.c index ac73191e4..94b5a3b43 100644 --- a/src/ps1/Graphics_PS1.c +++ b/src/ps1/Graphics_PS1.c @@ -154,7 +154,7 @@ static void SetupContexts(int w, int h) { static GfxResourceID white_square; static cc_bool cullingEnabled; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // dummy texture (grey works better in menus than white) @@ -164,7 +164,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/ps2/Graphics_PS2.c b/src/ps2/Graphics_PS2.c index 2a6e8df33..22b586973 100644 --- a/src/ps2/Graphics_PS2.c +++ b/src/ps2/Graphics_PS2.c @@ -46,7 +46,7 @@ static qword_t* Q; static GfxResourceID white_square; static int primitive_type; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 4x4 dummy white texture @@ -57,7 +57,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index 4cbc0e77d..8e2f184ed 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -269,7 +269,7 @@ cc_bool Gfx_TryRestoreContext(void) { return true; } cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -279,7 +279,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index 3c5902df1..e6ef5dc98 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -86,7 +86,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -96,7 +96,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/psvita/Graphics_PSVita.c b/src/psvita/Graphics_PSVita.c index 0b40def54..c0790f71e 100644 --- a/src/psvita/Graphics_PSVita.c +++ b/src/psvita/Graphics_PSVita.c @@ -588,7 +588,7 @@ void Gfx_Free(void) { cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); // 1x1 dummy white texture @@ -599,7 +599,7 @@ void Gfx_RestoreState(void) { // TODO } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/saturn/Graphics_Saturn.c b/src/saturn/Graphics_Saturn.c index ceb733911..4699c5691 100644 --- a/src/saturn/Graphics_Saturn.c +++ b/src/saturn/Graphics_Saturn.c @@ -96,7 +96,7 @@ static void CalcGouraudColours(void) { } static GfxResourceID white_square; -void Gfx_RestoreState(void) { +static void Gfx_RestoreState(void) { InitDefaultResources(); struct Bitmap bmp; @@ -107,7 +107,7 @@ void Gfx_RestoreState(void) { white_square = Gfx_CreateTexture(&bmp, 0, false); } -void Gfx_FreeState(void) { +static void Gfx_FreeState(void) { FreeDefaultResources(); Gfx_DeleteTexture(&white_square); } diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 554093891..eed41320f 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -134,8 +134,8 @@ void Gfx_Free(void) { } cc_bool Gfx_TryRestoreContext(void) { return true; } -void Gfx_RestoreState(void) { } -void Gfx_FreeState(void) { } +static void Gfx_RestoreState(void) { } +static void Gfx_FreeState(void) { } /*########################################################################################################################* From 28ef8faaa1faa7cb727e8496c3a7bf2996559e10 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 24 Aug 2025 07:08:07 +1000 Subject: [PATCH 043/115] Atari ST: Launcher graphics render --- src/atari_st/Window_Atari.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/atari_st/Window_Atari.c b/src/atari_st/Window_Atari.c index 7209e8bcb..70f10c919 100644 --- a/src/atari_st/Window_Atari.c +++ b/src/atari_st/Window_Atari.c @@ -109,17 +109,16 @@ void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { bmp->height = height; } +// Each group of 16 pixels is interleaved across 4 bitplanes +struct GRWORD { UWORD plane1, plane2, plane3, plane4; }; + // TODO should be done in assembly.. search up 'chunky to planar atari ST' void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { // TODO UWORD* ptr = Physbase(); Mem_Set(ptr, 0, 32000); int idx = 0; - - UWORD* plane1 = ptr + 0; - UWORD* plane2 = ptr + 4000; - UWORD* plane3 = ptr + 8000; - UWORD* plane4 = ptr + 12000; + struct GRWORD* planes = (struct GRWORD*)ptr; for (int y = 0; y < r.height; y++) { @@ -136,10 +135,12 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { //int pal = R | (G << 1) | (B << 2); int b1 = B & 0x01, b2 = (B >> 1); - plane1[idx >> 4] |= R << (idx & 0x0F); - plane2[idx >> 4] |= G << (idx & 0x0F); - plane3[idx >> 4] |= b1<< (idx & 0x0F); - plane4[idx >> 4] |= b2<< (idx & 0x0F); + int word = idx >> 4, bit = 15 - (idx & 0x0F); + + planes[word].plane1 |= R << bit; + planes[word].plane2 |= G << bit; + planes[word].plane3 |= b1<< bit; + planes[word].plane4 |= b2<< bit; } } } From afdfa295471dea3f857e5b90153dbb33b3bb30d5 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 24 Aug 2025 15:50:08 +1000 Subject: [PATCH 044/115] Atari ST: In-game technically renders --- src/Core.h | 1 + src/Server.c | 4 ++-- src/atari_st/Platform_Atari.c | 18 +++++++++++------- src/atari_st/Window_Atari.c | 24 ++++++++++++------------ 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/Core.h b/src/Core.h index de2b3f433..259d556c8 100644 --- a/src/Core.h +++ b/src/Core.h @@ -274,6 +274,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_FREETYPE #define CC_BUILD_ATARIOS #define CC_BUILD_COOPTHREADED + #define CC_BUILD_TINYMEM #define CC_BUILD_LOWMEM #define CC_BUILD_NOMUSIC #define CC_BUILD_NOSOUNDS diff --git a/src/Server.c b/src/Server.c index f6fea3c60..c554b5a41 100644 --- a/src/Server.c +++ b/src/Server.c @@ -132,7 +132,7 @@ static void SPConnection_BeginConnect(void) { Random_SeedFromCurrentTime(&rnd); World_NewMap(); -#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_MACCLASSIC || defined CC_BUILD_32X || defined CC_BUILD_GBA +#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_MACCLASSIC || defined CC_BUILD_TINYMEM horSize = 16; verSize = 16; #elif defined CC_BUILD_LOWMEM @@ -144,7 +144,7 @@ static void SPConnection_BeginConnect(void) { #endif World_SetDimensions(horSize, verSize, horSize); -#if defined CC_BUILD_N64 || defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_32X || defined CC_BUILD_GBA +#if defined CC_BUILD_N64 || defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_TINYMEM Gen_Active = &FlatgrassGen; #else Gen_Active = &NotchyGen; diff --git a/src/atari_st/Platform_Atari.c b/src/atari_st/Platform_Atari.c index 26871a2af..2a09beb03 100644 --- a/src/atari_st/Platform_Atari.c +++ b/src/atari_st/Platform_Atari.c @@ -41,8 +41,8 @@ cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS | PLAT_FLAG_APP_EXIT; int main(int argc, char** argv) { SetupProgram(argc, argv); while (Window_Main.Exists) { - //RunGame(); - RunProgram(argc, argv); + RunGame(); + //RunProgram(argc, argv); } Window_Free(); @@ -84,15 +84,21 @@ void Mem_Free(void* mem) { /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ +// Number of ticks 200 HZ system timer +// Must be called when in supervisor mode +static LONG Read_200HZ(void) { return *((LONG*)0x04BA); } + cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - cc_uint64 delta = end - beg; - return 1; // TODO implement + // 200 ticks a second + // 1,000,000 microseconds a second + // > one tick = 10^6/200 = 5000 microseconds + return (end - beg) * 5000; } cc_uint64 Stopwatch_Measure(void) { - return 1; // TODO implement + return Supexec(Read_200HZ); } void Platform_Log(const char* msg, int len) { @@ -270,7 +276,6 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ - void Platform_Init(void) { LONG size = (LONG)Malloc(-1); char* ptr = Malloc(size); @@ -280,7 +285,6 @@ void Platform_Init(void) { ta_init(heap_beg, heap_end, 256, 16, 4); int size_ = (int)(heap_end - heap_beg); - Platform_Log3("HEAP: %i bytes (%x -> %x)", &size_, &heap_beg, &heap_end); } void Platform_Free(void) { } diff --git a/src/atari_st/Window_Atari.c b/src/atari_st/Window_Atari.c index 70f10c919..1314f558e 100644 --- a/src/atari_st/Window_Atari.c +++ b/src/atari_st/Window_Atari.c @@ -25,12 +25,12 @@ void Window_PreInit(void) { for (int i = 0; i < 16; i++) { int R = (i & 0x1) >> 0; - int G = (i & 0x2) >> 1; - int B = (i & 0xC) >> 2; + int B = (i & 0x2) >> 1; + int G = (i & 0xC) >> 2; R = R ? ((R << 3) | 0x07) : 0; - G = G ? ((G << 3) | 0x07) : 0; - B = B ? ((B << 2) | 0x03) : 0; + B = B ? ((B << 3) | 0x07) : 0; + G = G ? ((G << 2) | 0x03) : 0; Setcolor(i, (R << 8) | (G << 4) | B); } @@ -129,18 +129,18 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { // TODO optimise BitmapCol col = row[x]; cc_uint8 R = BitmapCol_R(col) >> 7; - cc_uint8 G = BitmapCol_G(col) >> 7; - cc_uint8 B = BitmapCol_B(col) >> 6; + cc_uint8 G = BitmapCol_G(col) >> 6; + cc_uint8 B = BitmapCol_B(col) >> 7; //int pal = R | (G << 1) | (B << 2); - int b1 = B & 0x01, b2 = (B >> 1); + int g1 = G & 0x01, g2 = (G >> 1); int word = idx >> 4, bit = 15 - (idx & 0x0F); planes[word].plane1 |= R << bit; - planes[word].plane2 |= G << bit; - planes[word].plane3 |= b1<< bit; - planes[word].plane4 |= b2<< bit; + planes[word].plane2 |= B << bit; + planes[word].plane3 |= g1<< bit; + planes[word].plane4 |= g2<< bit; } } } @@ -192,8 +192,8 @@ void OnscreenKeyboard_Close(void) { *#########################################################################################################################*/ void Window_ShowDialog(const char* title, const char* msg) { /* TODO implement */ - //Platform_LogConst(title); - //Platform_LogConst(msg); + Platform_LogConst(title); + Platform_LogConst(msg); } cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { From 5e4443a1f92acb200f4f461693e62a7c13a38407 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 24 Aug 2025 18:05:28 +1000 Subject: [PATCH 045/115] Amiga: WIP vbcc support --- Makefile | 6 +++--- misc/amiga/Makefile | 42 +++++++++++++++++++++++++++++++++++++++++ misc/amiga/Makefile_68k | 34 +++++++++++++++++++-------------- misc/atari_st/Makefile | 10 ++++++++-- src/Core.h | 10 ++++++++++ src/ExtMath.c | 2 +- src/Platform_Amiga.c | 14 ++++++++++++-- src/Vorbis.c | 2 +- 8 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 misc/amiga/Makefile diff --git a/Makefile b/Makefile index a94f5dfe1..49754220a 100644 --- a/Makefile +++ b/Makefile @@ -300,10 +300,10 @@ macclassic_68k: $(MAKE) -f misc/macclassic/Makefile_68k macclassic_ppc: $(MAKE) -f misc/macclassic/Makefile_ppc -amiga_68k: +amiga_gcc: $(MAKE) -f misc/amiga/Makefile_68k -amiga_ppc: - $(MAKE) -f misc/amiga/Makefile_ppc +amiga: + $(MAKE) -f misc/amiga/Makefile atari_st: $(MAKE) -f misc/atari_st/Makefile diff --git a/misc/amiga/Makefile b/misc/amiga/Makefile new file mode 100644 index 000000000..0d5ee083c --- /dev/null +++ b/misc/amiga/Makefile @@ -0,0 +1,42 @@ +TARGET := ClassiCube-amiga +BUILD_DIR := build/amiga +SOURCE_DIRS := src src/amiga + +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) + + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +CC = vc +aos68k +CFLAGS = -rmcfg-amiga-softfloat -O1 -DPLAT_AMIGA + +AS = vasmm68k_mot +ASFLAGS = -Fvobj -m68000 -no-fpu + +LDFLAGS = $(CFLAGS) +LDLIBS = -lamiga -lmsoft + + +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) -final -o $@ $^ $(LDLIBS) + + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/%.o : src/amiga/%.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/misc/amiga/Makefile_68k b/misc/amiga/Makefile_68k index 43276ca2a..498fff892 100644 --- a/misc/amiga/Makefile_68k +++ b/misc/amiga/Makefile_68k @@ -1,20 +1,23 @@ -AS=m68k-amigaos-as -CC=m68k-amigaos-gcc -CXX=m68k-amigaos-g++ +TARGET := ClassiCube-amiga +BUILD_DIR := build/amiga_68k +SOURCE_DIRS := src src/amiga -CFLAGS :=-O1 -fno-math-errno -DPLAT_AMIGA -DCC_BUILD_NOFPU -TARGET := ClassiCube-68k -BUILD_DIR := build-amiga-68k -SOURCE_DIR := src -LDFLAGS := +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -C_SOURCES := $(wildcard $(SOURCE_DIR)/*.c) -C_ASSEMS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.S, $(C_SOURCES)) -C_OBJECTS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(C_SOURCES)) + +#--------------------------------------------------------------------------------- +# Code generation +#--------------------------------------------------------------------------------- +AS := m68k-amigaos-as +CC := m68k-amigaos-gcc +CXX := m68k-amigaos-g++ +CFLAGS := -O1 -fno-math-errno -DPLAT_AMIGA -DCC_BUILD_NOFPU # Dependency tracking DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d -DEPFILES := $(C_OBJECTS:%.o=%.d) +DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- @@ -32,10 +35,13 @@ $(TARGET).exe: $(C_OBJECTS) #--------------------------------------------------------------------------------- # object generation #--------------------------------------------------------------------------------- -$(C_OBJECTS): $(BUILD_DIR)/%.o : $(BUILD_DIR)/%.S +$(BUILD_DIR)/%.o : src/amiga/%.S $(AS) $< -o $@ -$(C_ASSEMS): $(BUILD_DIR)/%.S : $(SOURCE_DIR)/%.c +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ + +$(BUILD_DIR)/%.S : src/amiga/%.c $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ # Dependency tracking diff --git a/misc/atari_st/Makefile b/misc/atari_st/Makefile index 328989a11..a415dc85d 100644 --- a/misc/atari_st/Makefile +++ b/misc/atari_st/Makefile @@ -1,4 +1,4 @@ -TARGET := ClassiCube +TARGET := ClassiCube-atari BUILD_DIR := build/atari_st SOURCE_DIRS := src src/atari_st @@ -6,6 +6,7 @@ S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) + #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- @@ -18,8 +19,9 @@ ASFLAGS = -Fvobj -m68000 -no-fpu LDFLAGS = $(CFLAGS) LDLIBS = -lm + #--------------------------------------------------------------------------------- -# targets +# Main targets #--------------------------------------------------------------------------------- default: $(BUILD_DIR) $(TARGET).tos @@ -29,6 +31,10 @@ $(BUILD_DIR): $(TARGET).tos: $(OBJS) $(CC) $(LDFLAGS) -final -o $@ $^ $(LDLIBS) + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- $(BUILD_DIR)/%.o : src/%.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/Core.h b/src/Core.h index 259d556c8..8922a03a1 100644 --- a/src/Core.h +++ b/src/Core.h @@ -264,9 +264,19 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_FREETYPE #define CC_BUILD_AMIGA #define CC_BUILD_COOPTHREADED + #define CC_BUILD_TINYMEM #define CC_BUILD_LOWMEM #define CC_BUILD_NOMUSIC #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_RESOURCES + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_NETWORKING + #undef CC_BUILD_FILESYSTEM + #undef CC_BUILD_COMPRESSION + #define CC_BUILD_MAXSTACK (32 * 1024) + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU diff --git a/src/ExtMath.c b/src/ExtMath.c index eb5563ac5..c032f283a 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -98,7 +98,7 @@ float sqrtf(float x) { } #elif defined __GNUC__ || defined NXDK /* Defined in .h using builtins */ -#elif defined __TINYC__ || defined CC_BUILD_ATARIOS +#elif defined __TINYC__ || defined CC_BUILD_ATARIOS || defined CC_BUILD_AMIGA /* Older versions of TinyC don't support fabsf or sqrtf */ /* Those can be used though if compiling with newer TinyC */ /* versions for a very small performance improvement */ diff --git a/src/Platform_Amiga.c b/src/Platform_Amiga.c index c98b1836b..6ec0d9559 100644 --- a/src/Platform_Amiga.c +++ b/src/Platform_Amiga.c @@ -31,7 +31,11 @@ const char* Platform_AppNameSuffix = " Amiga"; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; cc_bool Platform_ReadonlyFilesystem; +#ifdef __GNUC__ static const char __attribute__((used)) min_stack[] = "$STACK:102400"; +#else +size_t __stack = 65536; // vbcc +#endif /*########################################################################################################################* *-----------------------------------------------------Main entrypoint-----------------------------------------------------* @@ -87,9 +91,10 @@ void Platform_Log(const char* msg, int len) { TimeMS DateTime_CurrentUTC(void) { ULONG secs, micro; - CurrentTime(&secs, µ); + //CurrentTime(&secs, µ); // TODO epoch adjustment - return secs; + //return secs; + return 0; } void DateTime_CurrentLocal(struct cc_datetime* t) { @@ -113,9 +118,14 @@ void Process_Abort2(cc_result result, const char* raw_msg) { #define US_PER_SEC 1000000ULL cc_uint64 Stopwatch_Measure(void) { +#ifdef __GNUC__ ULONG secs, micro; CurrentTime(&secs, µ); return secs * US_PER_SEC + micro; +#else + // TODO + return 10; +#endif } cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { diff --git a/src/Vorbis.c b/src/Vorbis.c index f69a418cd..f82a6af82 100644 --- a/src/Vorbis.c +++ b/src/Vorbis.c @@ -7,7 +7,7 @@ #include "Errors.h" #include "Stream.h" -#if !defined CC_BUILD_ATARIOS +#if !defined CC_BUILD_ATARIOS && !defined CC_BUILD_AMIGA /*########################################################################################################################* *-------------------------------------------------------Ogg stream--------------------------------------------------------* *#########################################################################################################################*/ From e49446df61f75337fecc72b90efb8e0a978a8950 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 25 Aug 2025 21:30:00 +1000 Subject: [PATCH 046/115] Xbox 360: Try disabling some functionality --- src/{ => amiga}/Platform_Amiga.c | 0 src/{ => amiga}/Window_Amiga.c | 0 src/ps3/Graphics_PS3.c | 29 +++++++++++++++-------------- src/ps3/Platform_PS3.c | 10 +++++++--- src/xbox360/Graphics_Xbox360.c | 24 ++++++++++++------------ 5 files changed, 34 insertions(+), 29 deletions(-) rename src/{ => amiga}/Platform_Amiga.c (100%) rename src/{ => amiga}/Window_Amiga.c (100%) diff --git a/src/Platform_Amiga.c b/src/amiga/Platform_Amiga.c similarity index 100% rename from src/Platform_Amiga.c rename to src/amiga/Platform_Amiga.c diff --git a/src/Window_Amiga.c b/src/amiga/Window_Amiga.c similarity index 100% rename from src/Window_Amiga.c rename to src/amiga/Window_Amiga.c diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index 8e2f184ed..174b3d100 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -101,7 +101,7 @@ static void FP_Load(FragmentProgram* fp, const u8* source) { fp->buffer = (u32*)rsxMemalign(128, size); Mem_Copy(fp->buffer, fp->ucode, size); - rsxAddressToOffset(fp->buffer, &fp->offset); + gcmAddressToOffset(fp->buffer, &fp->offset); } static void LoadFragmentPrograms(void) { @@ -132,7 +132,7 @@ static u32 depth_offset; static u32* depth_buffer; #define GCM_LABEL_INDEX 255 -static u32 slabelval = 1; +static u32 labelID = 1; static void CreateContext(void) { void* host_addr = memalign(1024 * 1024, HOST_SIZE); @@ -140,26 +140,27 @@ static void CreateContext(void) { } static void WaitRSXFinish(void) { - rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, slabelval); + rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, labelID); rsxFlushBuffer(context); - while (*(vu32*)gcmGetLabelAddress(GCM_LABEL_INDEX) != slabelval) + while (*(vu32*)gcmGetLabelAddress(GCM_LABEL_INDEX) != labelID) usleep(30); - slabelval++; + labelID++; } static void WaitRSXIdle(void) { - rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, slabelval); - rsxSetWaitLabel(context, GCM_LABEL_INDEX, slabelval); + rsxSetWriteBackendLabel(context, GCM_LABEL_INDEX, labelID); + rsxSetWaitLabel(context, GCM_LABEL_INDEX, labelID); - slabelval++; + labelID++; WaitRSXFinish(); } static void ConfigureVideo(void) { - videoState state; WaitRSXIdle(); + + videoState state; videoGetState(0, 0, &state); videoConfiguration vconfig = { 0 }; @@ -179,7 +180,7 @@ static void AllocColorSurface(u32 i) { color_pitch = DisplayInfo.Width * 4; color_buffer[i] = (u32*)rsxMemalign(64, DisplayInfo.Height * color_pitch); - rsxAddressToOffset(color_buffer[i], &color_offset[i]); + gcmAddressToOffset(color_buffer[i], &color_offset[i]); gcmSetDisplayBuffer(i, color_offset[i], color_pitch, DisplayInfo.Width, DisplayInfo.Height); } @@ -188,7 +189,7 @@ static void AllocDepthSurface(void) { depth_pitch = DisplayInfo.Width * 4; depth_buffer = (u32*)rsxMemalign(64, DisplayInfo.Height * depth_pitch); - rsxAddressToOffset(depth_buffer, &depth_offset); + gcmAddressToOffset(depth_buffer, &depth_offset); } @@ -287,7 +288,7 @@ static void Gfx_FreeState(void) { u32* Gfx_AllocImage(u32* offset, s32 w, s32 h) { u32* pixels = (u32*)rsxMemalign(64, w * h * 4); - rsxAddressToOffset(pixels, offset); + gcmAddressToOffset(pixels, offset); return pixels; } @@ -512,7 +513,7 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { void Gfx_BindVb(GfxResourceID vb) { u32 offset; - rsxAddressToOffset(vb, &offset); + gcmAddressToOffset(vb, &offset); if (gfx_format == VERTEX_FORMAT_TEXTURED) { rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_POS, 0, offset, @@ -638,7 +639,7 @@ void Gfx_BindTexture(GfxResourceID texId) { /* TODO */ u32 offset; - rsxAddressToOffset(tex->pixels, &offset); + gcmAddressToOffset(tex->pixels, &offset); gcmTexture texture; texture.format = GCM_TEXTURE_FORMAT_A8R8G8B8 | GCM_TEXTURE_FORMAT_SWZ; diff --git a/src/ps3/Platform_PS3.c b/src/ps3/Platform_PS3.c index aa87edd8f..b038ad38e 100644 --- a/src/ps3/Platform_PS3.c +++ b/src/ps3/Platform_PS3.c @@ -63,10 +63,14 @@ TimeMS DateTime_CurrentUTC(void) { } void DateTime_CurrentLocal(struct cc_datetime* t) { - struct timeval cur; + time_t cur_sec; struct tm loc_time; - gettimeofday(&cur, NULL); - localtime_r(&cur.tv_sec, &loc_time); + + u64 sec, nsec; + sysGetCurrentTime(&sec, &nsec); + + cur_sec = sec; + localtime_r(&cur_sec, &loc_time); t->year = loc_time.tm_year + 1900; t->month = loc_time.tm_mon + 1; diff --git a/src/xbox360/Graphics_Xbox360.c b/src/xbox360/Graphics_Xbox360.c index c1d13e6a7..fb312e3b4 100644 --- a/src/xbox360/Graphics_Xbox360.c +++ b/src/xbox360/Graphics_Xbox360.c @@ -57,7 +57,7 @@ static void CreateShaders(void) { void Gfx_Create(void) { if (!Gfx.Created) { CreateState(); - CreateShaders(); + //CreateShaders(); TODO } Gfx.Created = true; Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); @@ -231,7 +231,7 @@ void Gfx_DeleteVb(GfxResourceID* vb) { void Gfx_BindVb(GfxResourceID vb) { struct XenosVertexBuffer* xvb = (struct XenosVertexBuffer*)vb; - Xe_SetStreamSource(xe, 0, xvb, 0, gfx_stride); + //Xe_SetStreamSource(xe, 0, xvb, 0, gfx_stride); TODO } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { @@ -274,33 +274,33 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_stride = strideSizes[fmt]; if (fmt == VERTEX_FORMAT_COLOURED) { - Xe_SetTexture(xe, 0, NULL); - Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_col_ps, 0); - Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_col_vs, 0); + //Xe_SetTexture(xe, 0, NULL); TODO + //Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_col_ps, 0); TODO + //Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_col_vs, 0); TODO } else { - Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_tex_ps, 0); - Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_tex_vs, 0); + //Xe_SetShader(xe, SHADER_TYPE_PIXEL, shdr_tex_ps, 0); TODO + //Xe_SetShader(xe, SHADER_TYPE_VERTEX, shdr_tex_vs, 0); TODO } } void Gfx_DrawVb_Lines(int verticesCount) { Platform_Log1("DRAW_LINES: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_LINELIST, 0, verticesCount >> 1); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_LINELIST, 0, verticesCount >> 1); TODO } void Gfx_DrawVb_IndexedTris(int verticesCount) { Platform_Log1("DRAW_TRIS: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, 0, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, 0, verticesCount >> 2); TODO } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { Platform_Log1("DRAW_TRIS_RANGE: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); TODO } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { Platform_Log1("DRAW_TRIS_MAP: %i", &verticesCount); - Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); + //Xe_DrawPrimitive(xe, XE_PRIMTYPE_QUADLIST, startVertex, verticesCount >> 2); TODO } @@ -316,7 +316,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { Matrix_Mul(&_mvp, &_view, &_proj); // TODO: Is this a global uniform, or does it need to be reloaded on shader change? - Xe_SetVertexShaderConstantF(xe, 0, (float*)&_mvp, 4); + //Xe_SetVertexShaderConstantF(xe, 0, (float*)&_mvp, 4); TODO } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { From edc2e32b3fcafde3d165348f3b93a6bac7f8d313 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 26 Aug 2025 06:28:18 +1000 Subject: [PATCH 047/115] Xbox 360: Try to fix clear colour --- src/PackedCol.h | 6 ++++++ src/xbox360/Graphics_Xbox360.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/PackedCol.h b/src/PackedCol.h index 7d8eb2da8..3555fab79 100644 --- a/src/PackedCol.h +++ b/src/PackedCol.h @@ -18,6 +18,12 @@ typedef cc_uint32 PackedCol; #define PACKEDCOL_G_SHIFT 16 #define PACKEDCOL_B_SHIFT 8 #define PACKEDCOL_A_SHIFT 0 +#elif defined CC_BUILD_XBOX360 + /* TODO verify */ + #define PACKEDCOL_B_SHIFT 24 + #define PACKEDCOL_G_SHIFT 16 + #define PACKEDCOL_R_SHIFT 8 + #define PACKEDCOL_A_SHIFT 0 #else #define PACKEDCOL_R_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 diff --git a/src/xbox360/Graphics_Xbox360.c b/src/xbox360/Graphics_Xbox360.c index fb312e3b4..8bd0c1e73 100644 --- a/src/xbox360/Graphics_Xbox360.c +++ b/src/xbox360/Graphics_Xbox360.c @@ -177,7 +177,7 @@ void Gfx_SetAlphaArgBlend(cc_bool enabled) { // TODO } -void Gfx_ClearColor(PackedCol color) { +void Gfx_ClearColor(PackedCol color) { Xe_SetClearColor(xe, color); } From 980a27427d55a4bb1282673b2efd804ab4301ba4 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 26 Aug 2025 07:02:31 +1000 Subject: [PATCH 048/115] Xbox 360: Try to fix clear colour 2 --- src/PackedCol.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/PackedCol.h b/src/PackedCol.h index 3555fab79..0646e3916 100644 --- a/src/PackedCol.h +++ b/src/PackedCol.h @@ -8,7 +8,7 @@ CC_BEGIN_HEADER */ typedef cc_uint32 PackedCol; -#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST +#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST || defined CC_BUILD_XBOX360 #define PACKEDCOL_B_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 #define PACKEDCOL_R_SHIFT 16 @@ -18,12 +18,6 @@ typedef cc_uint32 PackedCol; #define PACKEDCOL_G_SHIFT 16 #define PACKEDCOL_B_SHIFT 8 #define PACKEDCOL_A_SHIFT 0 -#elif defined CC_BUILD_XBOX360 - /* TODO verify */ - #define PACKEDCOL_B_SHIFT 24 - #define PACKEDCOL_G_SHIFT 16 - #define PACKEDCOL_R_SHIFT 8 - #define PACKEDCOL_A_SHIFT 0 #else #define PACKEDCOL_R_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 From 3a66c9b35913289564008e35b0db91421fa7641e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 27 Aug 2025 07:42:53 +1000 Subject: [PATCH 049/115] BearSSL: Support relying on classicube's builtin mem functions when compiling in NO_STDLIB mode --- src/SystemFonts.c | 1 - third_party/bearssl/aes_big_cbcdec.c | 4 +-- third_party/bearssl/aes_big_cbcenc.c | 2 +- third_party/bearssl/aes_big_ctr.c | 2 +- third_party/bearssl/aes_x86ni.c | 2 +- third_party/bearssl/aes_x86ni_ctr.c | 2 +- third_party/bearssl/aesctr_drbg.c | 30 +++++++++---------- third_party/bearssl/asn1enc.c | 2 +- third_party/bearssl/bearssl_hash.h | 2 +- third_party/bearssl/bearssl_ssl.h | 5 ++-- third_party/bearssl/bearssl_stdlib.h | 24 +++++++++++++++ third_party/bearssl/ccm.c | 24 +++++++-------- third_party/bearssl/chacha20_ct.c | 6 ++-- third_party/bearssl/chacha20_sse2.c | 2 +- third_party/bearssl/ec_c25519_i31.c | 30 +++++++++---------- third_party/bearssl/ec_c25519_m31.c | 22 +++++++------- third_party/bearssl/ec_c25519_m62.c | 20 ++++++------- third_party/bearssl/ec_c25519_m64.c | 20 ++++++------- third_party/bearssl/ec_p256_m31.c | 26 ++++++++-------- third_party/bearssl/ec_p256_m62.c | 36 +++++++++++------------ third_party/bearssl/ec_p256_m64.c | 36 +++++++++++------------ third_party/bearssl/ec_prime_i31.c | 30 +++++++++---------- third_party/bearssl/ecdsa_atr.c | 8 ++--- third_party/bearssl/ecdsa_i31_vrfy_asn1.c | 2 +- third_party/bearssl/ecdsa_i31_vrfy_raw.c | 4 +-- third_party/bearssl/gcm.c | 26 ++++++++-------- third_party/bearssl/ghash_ctmul.c | 6 ++-- third_party/bearssl/ghash_ctmul64.c | 4 +-- third_party/bearssl/ghash_pclmul.c | 4 +-- third_party/bearssl/hmac.c | 8 ++--- third_party/bearssl/hmac_ct.c | 4 +-- third_party/bearssl/hmac_drbg.c | 6 ++-- third_party/bearssl/i31_encode.c | 2 +- third_party/bearssl/i31_moddiv.c | 6 ++-- third_party/bearssl/i31_modpow.c | 4 +-- third_party/bearssl/i31_modpow2.c | 6 ++-- third_party/bearssl/i31_muladd.c | 4 +-- third_party/bearssl/i31_reduce.c | 4 +-- third_party/bearssl/i62_modpow2.c | 10 +++---- third_party/bearssl/inner.h | 18 ++++-------- third_party/bearssl/md5.c | 14 ++++----- third_party/bearssl/md5sha1.c | 18 ++++++------ third_party/bearssl/multihash.c | 4 +-- third_party/bearssl/poly1305_ctmul.c | 8 ++--- third_party/bearssl/poly1305_ctmulq.c | 6 ++-- third_party/bearssl/prf_md5sha1.c | 2 +- third_party/bearssl/prf_sha256.c | 2 +- third_party/bearssl/prf_sha384.c | 2 +- third_party/bearssl/rsa_i31_pkcs1_vrfy.c | 2 +- third_party/bearssl/rsa_i31_priv.c | 2 +- third_party/bearssl/rsa_i62_pkcs1_vrfy.c | 2 +- third_party/bearssl/rsa_i62_priv.c | 2 +- third_party/bearssl/rsa_pkcs1_sig_unpad.c | 6 ++-- third_party/bearssl/sha1.c | 14 ++++----- third_party/bearssl/sha2big.c | 16 +++++----- third_party/bearssl/sha2small.c | 16 +++++----- third_party/bearssl/ssl_client.c | 6 ++-- third_party/bearssl/ssl_engine.c | 2 +- third_party/bearssl/ssl_hs_client.c | 22 +++++++------- third_party/bearssl/ssl_io.c | 4 +-- third_party/bearssl/ssl_rec_cbc.c | 14 ++++----- third_party/bearssl/ssl_rec_ccm.c | 10 +++---- third_party/bearssl/ssl_rec_chapol.c | 6 ++-- third_party/bearssl/ssl_rec_gcm.c | 14 ++++----- third_party/bearssl/x509_minimal.c | 18 ++++++------ 65 files changed, 341 insertions(+), 325 deletions(-) create mode 100644 third_party/bearssl/bearssl_stdlib.h diff --git a/src/SystemFonts.c b/src/SystemFonts.c index 83eba18d1..10a8303f3 100644 --- a/src/SystemFonts.c +++ b/src/SystemFonts.c @@ -405,7 +405,6 @@ void cc_qsort(void* v, size_t count, size_t size, } - static FT_Library ft_lib; static struct FT_MemoryRec_ ft_mem; static struct StringsBuffer font_list; diff --git a/third_party/bearssl/aes_big_cbcdec.c b/third_party/bearssl/aes_big_cbcdec.c index d969a3bf1..0ea6df841 100644 --- a/third_party/bearssl/aes_big_cbcdec.c +++ b/third_party/bearssl/aes_big_cbcdec.c @@ -46,12 +46,12 @@ br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, unsigned char tmp[16]; int i; - memcpy(tmp, buf, 16); + br_memcpy(tmp, buf, 16); br_aes_big_decrypt(ctx->num_rounds, ctx->skey, buf); for (i = 0; i < 16; i ++) { buf[i] ^= ivbuf[i]; } - memcpy(ivbuf, tmp, 16); + br_memcpy(ivbuf, tmp, 16); buf += 16; len -= 16; } diff --git a/third_party/bearssl/aes_big_cbcenc.c b/third_party/bearssl/aes_big_cbcenc.c index 265e53b80..bd32af8e7 100644 --- a/third_party/bearssl/aes_big_cbcenc.c +++ b/third_party/bearssl/aes_big_cbcenc.c @@ -49,7 +49,7 @@ br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, buf[i] ^= ivbuf[i]; } br_aes_big_encrypt(ctx->num_rounds, ctx->skey, buf); - memcpy(ivbuf, buf, 16); + br_memcpy(ivbuf, buf, 16); buf += 16; len -= 16; } diff --git a/third_party/bearssl/aes_big_ctr.c b/third_party/bearssl/aes_big_ctr.c index 18fbb8467..97024c711 100644 --- a/third_party/bearssl/aes_big_ctr.c +++ b/third_party/bearssl/aes_big_ctr.c @@ -57,7 +57,7 @@ br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, while (len > 0) { unsigned char tmp[16]; - memcpy(tmp, iv, 12); + br_memcpy(tmp, iv, 12); br_enc32be(tmp + 12, cc ++); br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); if (len <= 16) { diff --git a/third_party/bearssl/aes_x86ni.c b/third_party/bearssl/aes_x86ni.c index d5408f136..d2fd25d0d 100644 --- a/third_party/bearssl/aes_x86ni.c +++ b/third_party/bearssl/aes_x86ni.c @@ -213,7 +213,7 @@ br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) unsigned num_rounds; num_rounds = x86ni_keysched(sk, key, len); - memcpy(skni, sk, (num_rounds + 1) << 4); + br_memcpy(skni, sk, (num_rounds + 1) << 4); return num_rounds; } diff --git a/third_party/bearssl/aes_x86ni_ctr.c b/third_party/bearssl/aes_x86ni_ctr.c index 1cddd6065..42f1ed2b8 100644 --- a/third_party/bearssl/aes_x86ni_ctr.c +++ b/third_party/bearssl/aes_x86ni_ctr.c @@ -59,7 +59,7 @@ br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, unsigned u; buf = data; - memcpy(ivbuf, iv, 12); + br_memcpy(ivbuf, iv, 12); num_rounds = ctx->num_rounds; for (u = 0; u <= num_rounds; u ++) { sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); diff --git a/third_party/bearssl/aesctr_drbg.c b/third_party/bearssl/aesctr_drbg.c index 8dbd50102..93c08e962 100644 --- a/third_party/bearssl/aesctr_drbg.c +++ b/third_party/bearssl/aesctr_drbg.c @@ -33,7 +33,7 @@ br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, unsigned char tmp[16]; ctx->vtable = &br_aesctr_drbg_vtable; - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); aesctr->init(&ctx->sk.vtable, tmp, 16); ctx->cc = 0; br_aesctr_drbg_update(ctx, seed, len); @@ -47,7 +47,7 @@ br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) unsigned char iv[12]; buf = out; - memset(iv, 0, sizeof iv); + br_memset(iv, 0, sizeof iv); while (len > 0) { size_t clen; @@ -76,7 +76,7 @@ br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) /* * Run CTR. */ - memset(buf, 0, clen); + br_memset(buf, 0, clen); ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable, iv, ctx->cc, buf, clen); buf += clen; @@ -131,15 +131,15 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) * Use an all-one IV to get a fresh output block that depends on the * current seed. */ - memset(iv, 0xFF, sizeof iv); - memset(s, 0, 16); + br_memset(iv, 0xFF, sizeof iv); + br_memset(s, 0, 16); ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16); /* * Set G[] and H[] to conventional start values. */ - memset(G, 0xB6, sizeof G); - memset(H, 0x5A, sizeof H); + br_memset(G, 0xB6, sizeof G); + br_memset(H, 0x5A, sizeof H); /* * Process the concatenation of the current state and the seed @@ -153,9 +153,9 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) /* * Assemble new key H||m into tmp[]. */ - memcpy(tmp, H, 16); + br_memcpy(tmp, H, 16); if (first) { - memcpy(tmp + 16, s, 16); + br_memcpy(tmp + 16, s, 16); first = 0; } else { size_t clen; @@ -164,8 +164,8 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) break; } clen = len < 16 ? len : 16; - memcpy(tmp + 16, seed, clen); - memset(tmp + 16 + clen, 0, 16 - clen); + br_memcpy(tmp + 16, seed, clen); + br_memset(tmp + 16 + clen, 0, 16 - clen); seed = (const unsigned char *)seed + clen; len -= clen; } @@ -174,16 +174,16 @@ br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) /* * Compute new G and H values. */ - memcpy(iv, G, 12); - memcpy(newG, G, 16); + br_memcpy(iv, G, 12); + br_memcpy(newG, G, 16); ctx->sk.vtable->run(&ctx->sk.vtable, iv, br_dec32be(G + 12), newG, 16); iv[0] ^= 0x01; - memcpy(H, G, 16); + br_memcpy(H, G, 16); H[0] ^= 0x01; ctx->sk.vtable->run(&ctx->sk.vtable, iv, br_dec32be(G + 12), H, 16); - memcpy(G, newG, 16); + br_memcpy(G, newG, 16); } /* diff --git a/third_party/bearssl/asn1enc.c b/third_party/bearssl/asn1enc.c index 7a7496334..290035d45 100644 --- a/third_party/bearssl/asn1enc.c +++ b/third_party/bearssl/asn1enc.c @@ -88,6 +88,6 @@ br_asn1_encode_uint(void *dest, br_asn1_uint pp) lenlen = br_asn1_encode_length(buf, pp.asn1len); buf += lenlen; *buf = 0x00; - memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); + br_memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); return 1 + lenlen + pp.asn1len; } diff --git a/third_party/bearssl/bearssl_hash.h b/third_party/bearssl/bearssl_hash.h index 00c1e1d07..f924bc272 100644 --- a/third_party/bearssl/bearssl_hash.h +++ b/third_party/bearssl/bearssl_hash.h @@ -75,7 +75,7 @@ extern "C" { * Context for an ongoing computation. It is allocated by the * caller, and a pointer to it is passed to all functions. A * context contains no interior pointer, so it can be moved around - * and cloned (with a simple `memcpy()` or equivalent) in order to + * and cloned (with a simple `br_memcpy()` or equivalent) in order to * capture the function state at some point. Computations that use * distinct context structures are independent of each other. The * first field of `br_xxx_context` is always a pointer to the diff --git a/third_party/bearssl/bearssl_ssl.h b/third_party/bearssl/bearssl_ssl.h index 14d09d035..c5d38ed6c 100644 --- a/third_party/bearssl/bearssl_ssl.h +++ b/third_party/bearssl/bearssl_ssl.h @@ -34,6 +34,7 @@ #include "bearssl_prf.h" #include "bearssl_rand.h" #include "bearssl_x509.h" +#include "bearssl_stdlib.h" #ifdef __cplusplus extern "C" { @@ -1889,7 +1890,7 @@ static inline void br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, br_ssl_session_parameters *pp) { - memcpy(pp, &cc->session, sizeof *pp); + br_memcpy(pp, &cc->session, sizeof *pp); } /** @@ -1906,7 +1907,7 @@ static inline void br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, const br_ssl_session_parameters *pp) { - memcpy(&cc->session, pp, sizeof *pp); + br_memcpy(&cc->session, pp, sizeof *pp); } /** diff --git a/third_party/bearssl/bearssl_stdlib.h b/third_party/bearssl/bearssl_stdlib.h new file mode 100644 index 000000000..7f9f0316f --- /dev/null +++ b/third_party/bearssl/bearssl_stdlib.h @@ -0,0 +1,24 @@ +#ifndef BR_BEARSSL_STDLIB_H__ +#define BR_BEARSSL_STDLIB_H__ +/* ==== BEG ClassiCube specific ==== */ +static size_t br_strlen(const char* a) { + int i = 0; + while (*a++) i++; + return i; +} + +#ifdef CC_BUILD_NOSTDLIB + extern void* Mem_Copy(void* dst, const void* src, unsigned size); + extern void* Mem_Move(void* dst, const void* src, unsigned size); + extern void* Mem_Set(void* dst, unsigned char val, unsigned size); + + #define br_memcpy Mem_Copy + #define br_memmove Mem_Move + #define br_memset Mem_Set +#else + #define br_memcpy memcpy + #define br_memset memset + #define br_memmove memmove +#endif +/* ==== END ClassiCube specific ==== */ +#endif diff --git a/third_party/bearssl/ccm.c b/third_party/bearssl/ccm.c index 68cc913ec..d2dde6531 100644 --- a/third_party/bearssl/ccm.c +++ b/third_party/bearssl/ccm.c @@ -76,7 +76,7 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, tmp[0] = (aad_len > 0 ? 0x40 : 0x00) | (((unsigned)tag_len - 2) << 2) | (q - 1); - memcpy(tmp + 1, nonce, nonce_len); + br_memcpy(tmp + 1, nonce, nonce_len); for (u = 0; u < q; u ++) { tmp[15 - u] = (unsigned char)data_len; data_len >>= 8; @@ -93,7 +93,7 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, /* * Start CBC-MAC. */ - memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); + br_memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp); /* @@ -120,9 +120,9 @@ br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, * Make initial counter value and compute tag mask. */ ctx->ctr[0] = q - 1; - memcpy(ctx->ctr + 1, nonce, nonce_len); - memset(ctx->ctr + 1 + nonce_len, 0, q); - memset(ctx->tagmask, 0, sizeof ctx->tagmask); + br_memcpy(ctx->ctr + 1, nonce, nonce_len); + br_memset(ctx->ctr + 1 + nonce_len, 0, q); + br_memset(ctx->tagmask, 0, sizeof ctx->tagmask); (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->tagmask, sizeof ctx->tagmask); @@ -147,11 +147,11 @@ br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) clen = (sizeof ctx->buf) - ptr; if (clen > len) { - memcpy(ctx->buf + ptr, dbuf, len); + br_memcpy(ctx->buf + ptr, dbuf, len); ctx->ptr = ptr + len; return; } - memcpy(ctx->buf + ptr, dbuf, clen); + br_memcpy(ctx->buf + ptr, dbuf, clen); dbuf += clen; len -= clen; (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, @@ -169,7 +169,7 @@ br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) /* * Copy last partial block in the context buffer. */ - memcpy(ctx->buf, dbuf, ptr); + br_memcpy(ctx->buf, dbuf, ptr); ctx->ptr = ptr; } @@ -184,7 +184,7 @@ br_ccm_flip(br_ccm_context *ctx) */ ptr = ctx->ptr; if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + br_memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); ctx->ptr = 0; @@ -276,7 +276,7 @@ br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len) if (ptr != 0) { size_t u; - memset(ctx->buf, 0, sizeof ctx->buf); + br_memset(ctx->buf, 0, sizeof ctx->buf); (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf); if (encrypt) { @@ -314,7 +314,7 @@ br_ccm_get_tag(br_ccm_context *ctx, void *tag) */ ptr = ctx->ptr; if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); + br_memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); } @@ -325,7 +325,7 @@ br_ccm_get_tag(br_ccm_context *ctx, void *tag) for (u = 0; u < ctx->tag_len; u ++) { ctx->cbcmac[u] ^= ctx->tagmask[u]; } - memcpy(tag, ctx->cbcmac, ctx->tag_len); + br_memcpy(tag, ctx->cbcmac, ctx->tag_len); return ctx->tag_len; } diff --git a/third_party/bearssl/chacha20_ct.c b/third_party/bearssl/chacha20_ct.c index 9961eb119..1159c85f2 100644 --- a/third_party/bearssl/chacha20_ct.c +++ b/third_party/bearssl/chacha20_ct.c @@ -50,10 +50,10 @@ br_chacha20_ct_run(const void *key, size_t clen; unsigned char tmp[64]; - memcpy(&state[0], CW, sizeof CW); - memcpy(&state[4], kw, sizeof kw); + br_memcpy(&state[0], CW, sizeof CW); + br_memcpy(&state[4], kw, sizeof kw); state[12] = cc; - memcpy(&state[13], ivw, sizeof ivw); + br_memcpy(&state[13], ivw, sizeof ivw); for (i = 0; i < 10; i ++) { #define QROUND(a, b, c, d) do { \ diff --git a/third_party/bearssl/chacha20_sse2.c b/third_party/bearssl/chacha20_sse2.c index 2905d09b4..2e16bdf31 100644 --- a/third_party/bearssl/chacha20_sse2.c +++ b/third_party/bearssl/chacha20_sse2.c @@ -72,7 +72,7 @@ br_chacha20_sse2_run(const void *key, kw0 = _mm_loadu_si128(key); kw1 = _mm_loadu_si128((const void *)((const unsigned char *)key + 16)); ivtmp[0] = cc; - memcpy(ivtmp + 1, iv, 12); + br_memcpy(ivtmp + 1, iv, 12); iw = _mm_loadu_si128((const void *)ivtmp); cw = _mm_loadu_si128((const void *)CW); one = _mm_set_epi32(0, 0, 0, 1); diff --git a/third_party/bearssl/ec_c25519_i31.c b/third_party/bearssl/ec_c25519_i31.c index f8ffc2c24..4b6389f3b 100644 --- a/third_party/bearssl/ec_c25519_i31.c +++ b/third_party/bearssl/ec_c25519_i31.c @@ -61,7 +61,7 @@ print_int_mont(const char *name, const uint32_t *x) size_t u; printf("%s = ", name); - memcpy(y, x, sizeof y); + br_memcpy(y, x, sizeof y); br_i31_from_monty(y, C255_P, P0I); br_i31_encode(tmp, sizeof tmp, y); for (u = 0; u < sizeof tmp; u ++) { @@ -132,11 +132,11 @@ c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) uint32_t ctl; uint32_t t[10]; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); ctl = br_i31_add(t, b, 1); ctl |= NOT(br_i31_sub(t, C255_P, 0)); br_i31_sub(t, C255_P, ctl); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -144,9 +144,9 @@ c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) { uint32_t t[10]; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); br_i31_add(t, C255_P, br_i31_sub(t, b, 1)); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -155,7 +155,7 @@ c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) uint32_t t[10]; br_i31_montymul(t, a, b, C255_P, P0I); - memcpy(d, t, sizeof t); + br_memcpy(d, t, sizeof t); } static void @@ -224,17 +224,17 @@ api_mul(unsigned char *G, size_t Glen, * into Montgomery representation. */ br_i31_montymul(x1, a, C255_R2, C255_P, P0I); - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); br_i31_zero(z2, C255_P[0]); - memcpy(x2, z2, sizeof z2); + br_memcpy(x2, z2, sizeof z2); x2[1] = 0x13000000; - memcpy(z3, x2, sizeof x2); + br_memcpy(z3, x2, sizeof x2); /* * kb[] is in big-endian notation, but possibly shorter than k[]. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -307,12 +307,12 @@ api_mul(unsigned char *G, size_t Glen, * square-and-multiply algorithm; we mutualise most non-squarings * since the exponent contains almost only ones. */ - memcpy(a, z2, sizeof z2); + br_memcpy(a, z2, sizeof z2); for (i = 0; i < 15; i ++) { c255_mul(a, a, a); c255_mul(a, a, z2); } - memcpy(b, a, sizeof a); + br_memcpy(b, a, sizeof a); for (i = 0; i < 14; i ++) { int j; @@ -332,7 +332,7 @@ api_mul(unsigned char *G, size_t Glen, /* * To avoid a dependency on br_i31_from_monty(), we use * a Montgomery multiplication with 1. - * memcpy(x2, b, sizeof b); + * br_memcpy(x2, b, sizeof b); * br_i31_from_monty(x2, C255_P, P0I); */ br_i31_zero(a, C255_P[0]); @@ -352,7 +352,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m31.c b/third_party/bearssl/ec_c25519_m31.c index 1dd6d514f..619135bac 100644 --- a/third_party/bearssl/ec_c25519_m31.c +++ b/third_party/bearssl/ec_c25519_m31.c @@ -44,7 +44,7 @@ print_int(const char *name, const uint32_t *x) return; } } - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); for (u = 0; u < 9; u ++) { uint64_t w; int j, k; @@ -348,7 +348,7 @@ reduce_final_f255(uint32_t *d) uint32_t cc; int i; - memcpy(t, d, sizeof t); + br_memcpy(t, d, sizeof t); cc = 19; for (i = 0; i < 9; i ++) { uint32_t w; @@ -647,15 +647,15 @@ api_mul(unsigned char *G, size_t Glen, * into Montgomery representation. */ x1[8] = le8_to_le30(x1, G, 32); - memcpy(x3, x1, sizeof x1); - memset(z2, 0, sizeof z2); - memset(x2, 0, sizeof x2); + br_memcpy(x3, x1, sizeof x1); + br_memset(z2, 0, sizeof z2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z3, 0, sizeof z3); + br_memset(z3, 0, sizeof z3); z3[0] = 1; - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -728,12 +728,12 @@ api_mul(unsigned char *G, size_t Glen, * square-and-multiply algorithm; we mutualise most non-squarings * since the exponent contains almost only ones. */ - memcpy(a, z2, sizeof z2); + br_memcpy(a, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_square(a, a); f255_mul(a, a, z2); } - memcpy(b, a, sizeof a); + br_memcpy(b, a, sizeof a); for (i = 0; i < 14; i ++) { int j; @@ -762,7 +762,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m62.c b/third_party/bearssl/ec_c25519_m62.c index 6b058eb1b..516e9d4ce 100644 --- a/third_party/bearssl/ec_c25519_m62.c +++ b/third_party/bearssl/ec_c25519_m62.c @@ -403,22 +403,22 @@ api_mul(unsigned char *G, size_t Glen, x1[4] = (br_dec64le(&G[24]) >> 12) & MASK51; /* - * We can use memset() to clear values, because exact-width types + * We can use br_memset() to clear values, because exact-width types * like uint64_t are guaranteed to have no padding bits or * trap representations. */ - memset(x2, 0, sizeof x2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z2, 0, sizeof z2); - memcpy(x3, x1, sizeof x1); - memcpy(z3, x2, sizeof x2); + br_memset(z2, 0, sizeof z2); + br_memcpy(x3, x1, sizeof x1); + br_memcpy(z3, x2, sizeof x2); /* * The multiplier is provided in big-endian notation, and * possibly shorter than 32 bytes. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -499,12 +499,12 @@ api_mul(unsigned char *G, size_t Glen, * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize * most non-squarings. We use x1 and x3, now useless, as temporaries. */ - memcpy(x1, z2, sizeof z2); + br_memcpy(x1, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_mul(x1, x1, x1); f255_mul(x1, x1, z2); } - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); for (i = 0; i < 14; i ++) { int j; @@ -549,7 +549,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_c25519_m64.c b/third_party/bearssl/ec_c25519_m64.c index df4883467..7fca81b4e 100644 --- a/third_party/bearssl/ec_c25519_m64.c +++ b/third_party/bearssl/ec_c25519_m64.c @@ -645,22 +645,22 @@ api_mul(unsigned char *G, size_t Glen, x1[3] = br_dec64le(&G[24]) & MASK63; /* - * We can use memset() to clear values, because exact-width types + * We can use br_memset() to clear values, because exact-width types * like uint64_t are guaranteed to have no padding bits or * trap representations. */ - memset(x2, 0, sizeof x2); + br_memset(x2, 0, sizeof x2); x2[0] = 1; - memset(z2, 0, sizeof z2); - memcpy(x3, x1, sizeof x1); - memcpy(z3, x2, sizeof x2); + br_memset(z2, 0, sizeof z2); + br_memcpy(x3, x1, sizeof x1); + br_memcpy(z3, x2, sizeof x2); /* * The multiplier is provided in big-endian notation, and * possibly shorter than 32 bytes. */ - memset(k, 0, (sizeof k) - kblen); - memcpy(k + (sizeof k) - kblen, kb, kblen); + br_memset(k, 0, (sizeof k) - kblen); + br_memcpy(k + (sizeof k) - kblen, kb, kblen); k[31] &= 0xF8; k[0] &= 0x7F; k[0] |= 0x40; @@ -730,12 +730,12 @@ api_mul(unsigned char *G, size_t Glen, * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize * most non-squarings. We use x1 and x3, now useless, as temporaries. */ - memcpy(x1, z2, sizeof z2); + br_memcpy(x1, z2, sizeof z2); for (i = 0; i < 15; i ++) { f255_mul(x1, x1, x1); f255_mul(x1, x1, z2); } - memcpy(x3, x1, sizeof x1); + br_memcpy(x3, x1, sizeof x1); for (i = 0; i < 14; i ++) { int j; @@ -775,7 +775,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ec_p256_m31.c b/third_party/bearssl/ec_p256_m31.c index b185937e1..b93fda714 100644 --- a/third_party/bearssl/ec_p256_m31.c +++ b/third_party/bearssl/ec_p256_m31.c @@ -690,7 +690,7 @@ p256_to_affine(p256_jacobian *P) * two dozen multiplications here with an addition chain, but * this would require a bit more code, and extra stack buffers. */ - memcpy(t1, P->z, sizeof P->z); + br_memcpy(t1, P->z, sizeof P->z); for (i = 0; i < 30; i ++) { square_f256(t1, t1); mul_f256(t1, t1, P->z); @@ -701,7 +701,7 @@ p256_to_affine(p256_jacobian *P) * multiplications to set bits to 1; we multiply by the original z * for setting 1 bit, and by t1 for setting 31 bits. */ - memcpy(t2, P->z, sizeof P->z); + br_memcpy(t2, P->z, sizeof P->z); for (i = 1; i < 256; i ++) { square_f256(t2, t2); switch (i) { @@ -976,8 +976,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1085,9 +1085,9 @@ p256_decode(p256_jacobian *P, const void *src, size_t len) /* * Copy coordinates to the point structure. */ - memcpy(P->x, tx, sizeof tx); - memcpy(P->y, ty, sizeof ty); - memset(P->z, 0, sizeof P->z); + br_memcpy(P->x, tx, sizeof tx); + br_memcpy(P->y, ty, sizeof ty); + br_memset(P->z, 0, sizeof P->z); P->z[0] = 1; return EQ(bad, 0); } @@ -1136,7 +1136,7 @@ p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) /* * We start with Q = 0. We process multiplier bits 2 by 2. */ - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (xlen -- > 0) { int k; @@ -1272,7 +1272,7 @@ lookup_Gwin(p256_jacobian *T, uint32_t idx) uint32_t k; size_t u; - memset(xy, 0, sizeof xy); + br_memset(xy, 0, sizeof xy); for (k = 0; k < 15; k ++) { uint32_t m; @@ -1281,9 +1281,9 @@ lookup_Gwin(p256_jacobian *T, uint32_t idx) xy[u] |= m & Gwin[k][u]; } } - memcpy(T->x, &xy[0], sizeof T->x); - memcpy(T->y, &xy[9], sizeof T->y); - memset(T->z, 0, sizeof T->z); + br_memcpy(T->x, &xy[0], sizeof T->x); + br_memcpy(T->y, &xy[9], sizeof T->y); + br_memset(T->z, 0, sizeof T->z); T->z[0] = 1; } @@ -1305,7 +1305,7 @@ p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (xlen -- > 0) { int k; diff --git a/third_party/bearssl/ec_p256_m62.c b/third_party/bearssl/ec_p256_m62.c index a43179052..6e3814ede 100644 --- a/third_party/bearssl/ec_p256_m62.c +++ b/third_party/bearssl/ec_p256_m62.c @@ -498,13 +498,13 @@ f256_invert(uint64_t *d, const uint64_t *a) uint64_t r[5], t[5]; int i; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); for (i = 0; i < 30; i ++) { f256_montysquare(t, t); f256_montymul(t, t, a); } - memcpy(r, t, sizeof t); + br_memcpy(r, t, sizeof t); for (i = 224; i >= 0; i --) { f256_montysquare(r, r); switch (i) { @@ -521,7 +521,7 @@ f256_invert(uint64_t *d, const uint64_t *a) break; } } - memcpy(d, r, sizeof r); + br_memcpy(d, r, sizeof r); } /* @@ -703,9 +703,9 @@ point_decode(p256_jacobian *P, const unsigned char *buf) * Return the point in Jacobian coordinates (and Montgomery * representation). */ - memcpy(P->x, x, sizeof x); - memcpy(P->y, y, sizeof y); - memcpy(P->z, F256_R, sizeof F256_R); + br_memcpy(P->x, x, sizeof x); + br_memcpy(P->y, y, sizeof y); + br_memcpy(P->z, F256_R, sizeof F256_R); return r; } @@ -994,8 +994,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1117,8 +1117,8 @@ p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1254,7 +1254,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (klen -- > 0) { int i; @@ -1283,7 +1283,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, * problem because we will use it only if the * bits are non-zero. */ - memset(&T, 0, sizeof T); + br_memset(&T, 0, sizeof T); for (n = 0; n < 15; n ++) { m = -(uint64_t)EQ(bits, n + 1); T.x[0] |= m & W[n].x[0]; @@ -1399,14 +1399,14 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) * extra one with coordinate Z = 1 (in Montgomery representation). */ for (i = 0; (i + 1) < num; i += 2) { - memcpy(zt, jac[i].z, sizeof zt); - memcpy(jac[i].z, jac[i + 1].z, sizeof zt); - memcpy(jac[i + 1].z, zt, sizeof zt); + br_memcpy(zt, jac[i].z, sizeof zt); + br_memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + br_memcpy(jac[i + 1].z, zt, sizeof zt); f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); } if ((num & 1) != 0) { - memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); - memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + br_memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + br_memcpy(jac[num - 1].z, F256_R, sizeof F256_R); } /* @@ -1425,7 +1425,7 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); } if ((n & 1) != 0) { - memmove(z[n >> 1], z[n], sizeof zt); + br_memmove(z[n >> 1], z[n], sizeof zt); } } diff --git a/third_party/bearssl/ec_p256_m64.c b/third_party/bearssl/ec_p256_m64.c index 71a527c36..0d8a9d64d 100644 --- a/third_party/bearssl/ec_p256_m64.c +++ b/third_party/bearssl/ec_p256_m64.c @@ -561,13 +561,13 @@ f256_invert(uint64_t *d, const uint64_t *a) uint64_t r[4], t[4]; int i; - memcpy(t, a, sizeof t); + br_memcpy(t, a, sizeof t); for (i = 0; i < 30; i ++) { f256_montysquare(t, t); f256_montymul(t, t, a); } - memcpy(r, t, sizeof t); + br_memcpy(r, t, sizeof t); for (i = 224; i >= 0; i --) { f256_montysquare(r, r); switch (i) { @@ -584,7 +584,7 @@ f256_invert(uint64_t *d, const uint64_t *a) break; } } - memcpy(d, r, sizeof r); + br_memcpy(d, r, sizeof r); } /* @@ -713,9 +713,9 @@ point_decode(p256_jacobian *P, const unsigned char *buf) * Return the point in Jacobian coordinates (and Montgomery * representation). */ - memcpy(P->x, x, sizeof x); - memcpy(P->y, y, sizeof y); - memcpy(P->z, F256_R, sizeof F256_R); + br_memcpy(P->x, x, sizeof x); + br_memcpy(P->y, y, sizeof y); + br_memcpy(P->z, F256_R, sizeof F256_R); return r; } @@ -1014,8 +1014,8 @@ p256_add_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1137,8 +1137,8 @@ p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2) /* * Compute u1 = x1 (in t1) and s1 = y1 (in t3). */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); + br_memcpy(t1, P1->x, sizeof t1); + br_memcpy(t3, P1->y, sizeof t3); /* * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). @@ -1272,7 +1272,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, p256_jacobian Q; uint32_t qz; - memset(&Q, 0, sizeof Q); + br_memset(&Q, 0, sizeof Q); qz = 1; while (klen -- > 0) { int i; @@ -1301,7 +1301,7 @@ point_mul_inner(p256_jacobian *R, const p256_affine *W, * problem because we will use it only if the * bits are non-zero. */ - memset(&T, 0, sizeof T); + br_memset(&T, 0, sizeof T); for (n = 0; n < 15; n ++) { m = -(uint64_t)EQ(bits, n + 1); T.x[0] |= m & W[n].x[0]; @@ -1415,14 +1415,14 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) * extra one with coordinate Z = 1 (in Montgomery representation). */ for (i = 0; (i + 1) < num; i += 2) { - memcpy(zt, jac[i].z, sizeof zt); - memcpy(jac[i].z, jac[i + 1].z, sizeof zt); - memcpy(jac[i + 1].z, zt, sizeof zt); + br_memcpy(zt, jac[i].z, sizeof zt); + br_memcpy(jac[i].z, jac[i + 1].z, sizeof zt); + br_memcpy(jac[i + 1].z, zt, sizeof zt); f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z); } if ((num & 1) != 0) { - memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); - memcpy(jac[num - 1].z, F256_R, sizeof F256_R); + br_memcpy(z[num >> 1], jac[num - 1].z, sizeof zt); + br_memcpy(jac[num - 1].z, F256_R, sizeof F256_R); } /* @@ -1441,7 +1441,7 @@ window_to_affine(p256_affine *aff, p256_jacobian *jac, int num) f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]); } if ((n & 1) != 0) { - memmove(z[n >> 1], z[n], sizeof zt); + br_memmove(z[n >> 1], z[n], sizeof zt); } } diff --git a/third_party/bearssl/ec_prime_i31.c b/third_party/bearssl/ec_prime_i31.c index b205f367a..56fc6ca66 100644 --- a/third_party/bearssl/ec_prime_i31.c +++ b/third_party/bearssl/ec_prime_i31.c @@ -461,8 +461,8 @@ run_code(jacobian *P1, const jacobian *P2, /* * Copy the two operands in the dedicated registers. */ - memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); - memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); /* * Run formulas. @@ -484,7 +484,7 @@ run_code(jacobian *P1, const jacobian *P2, unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; case 0: - memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); + br_memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); break; case 1: ctl = br_i31_add(t[d], t[a], 1); @@ -513,7 +513,7 @@ run_code(jacobian *P1, const jacobian *P2, /* * Copy back result. */ - memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); + br_memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); return r; } @@ -523,7 +523,7 @@ set_one(uint32_t *x, const uint32_t *p) size_t plen; plen = (p[0] + 63) >> 5; - memset(x, 0, plen * sizeof *x); + br_memset(x, 0, plen * sizeof *x); x[0] = p[0]; x[1] = 0x00000001; } @@ -531,7 +531,7 @@ set_one(uint32_t *x, const uint32_t *p) static void point_zero(jacobian *P, const curve_params *cc) { - memset(P, 0, sizeof *P); + br_memset(P, 0, sizeof *P); P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; } @@ -568,9 +568,9 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, uint32_t qz; jacobian P2, P3, Q, T, U; - memcpy(&P2, P, sizeof P2); + br_memcpy(&P2, P, sizeof P2); point_double(&P2, cc); - memcpy(&P3, P, sizeof P3); + br_memcpy(&P3, P, sizeof P3); point_add(&P3, &P2, cc); point_zero(&Q, cc); @@ -584,8 +584,8 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, point_double(&Q, cc); point_double(&Q, cc); - memcpy(&T, P, sizeof T); - memcpy(&U, &Q, sizeof U); + br_memcpy(&T, P, sizeof T); + br_memcpy(&U, &Q, sizeof U); bits = (*x >> k) & (uint32_t)3; bnz = NEQ(bits, 0); CCOPY(EQ(bits, 2), &T, &P2, sizeof T); @@ -597,7 +597,7 @@ point_mul(jacobian *P, const unsigned char *x, size_t xlen, } x ++; } - memcpy(P, &Q, sizeof Q); + br_memcpy(P, &Q, sizeof Q); } /* @@ -652,8 +652,8 @@ point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) * Convert coordinates and check that the point is valid. */ zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t); - memcpy(Q.c[0], cc->R2, zlen); - memcpy(Q.c[1], cc->b, zlen); + br_memcpy(Q.c[0], cc->R2, zlen); + br_memcpy(Q.c[1], cc->b, zlen); set_one(Q.c[2], cc->p); r &= ~run_code(P, &Q, cc, code_check); return r; @@ -677,7 +677,7 @@ point_encode(void *dst, const jacobian *P, const curve_params *cc) xbl -= (xbl >> 5); plen = (xbl + 7) >> 3; buf[0] = 0x04; - memcpy(&Q, P, sizeof *P); + br_memcpy(&Q, P, sizeof *P); set_one(T.c[2], cc->p); run_code(&Q, &T, cc, code_affine); br_i31_encode(buf + 1, plen, Q.c[0]); @@ -752,7 +752,7 @@ api_mulgen(unsigned char *R, size_t Glen; G = api_generator(curve, &Glen); - memcpy(R, G, Glen); + br_memcpy(R, G, Glen); api_mul(R, Glen, x, xlen, curve); return Glen; } diff --git a/third_party/bearssl/ecdsa_atr.c b/third_party/bearssl/ecdsa_atr.c index 3a11226e4..c4c1e932a 100644 --- a/third_party/bearssl/ecdsa_atr.c +++ b/third_party/bearssl/ecdsa_atr.c @@ -126,9 +126,9 @@ br_ecdsa_asn1_to_raw(void *sig, size_t sig_len) */ zlen = rlen > slen ? rlen : slen; sig_len = zlen << 1; - memset(tmp, 0, sig_len); - memcpy(tmp + zlen - rlen, r, rlen); - memcpy(tmp + sig_len - slen, s, slen); - memcpy(sig, tmp, sig_len); + br_memset(tmp, 0, sig_len); + br_memcpy(tmp + zlen - rlen, r, rlen); + br_memcpy(tmp + sig_len - slen, s, slen); + br_memcpy(sig, tmp, sig_len); return sig_len; } diff --git a/third_party/bearssl/ecdsa_i31_vrfy_asn1.c b/third_party/bearssl/ecdsa_i31_vrfy_asn1.c index 4161aaaa3..5e9db87a7 100644 --- a/third_party/bearssl/ecdsa_i31_vrfy_asn1.c +++ b/third_party/bearssl/ecdsa_i31_vrfy_asn1.c @@ -42,7 +42,7 @@ br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, if (sig_len > ((sizeof rsig) >> 1)) { return 0; } - memcpy(rsig, sig, sig_len); + br_memcpy(rsig, sig, sig_len); sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); } diff --git a/third_party/bearssl/ecdsa_i31_vrfy_raw.c b/third_party/bearssl/ecdsa_i31_vrfy_raw.c index 259477fdb..f1e76c1c4 100644 --- a/third_party/bearssl/ecdsa_i31_vrfy_raw.c +++ b/third_party/bearssl/ecdsa_i31_vrfy_raw.c @@ -113,7 +113,7 @@ br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, * the inversion (because (1/s)*R = 1/(s/R)). */ br_i31_from_monty(s, n, n0i); - memcpy(tx, cd->order, nlen); + br_memcpy(tx, cd->order, nlen); tx[nlen - 1] -= 2; br_i31_modpow(s, tx, nlen, n, n0i, t1, t2); @@ -143,7 +143,7 @@ br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, * Compute the point x*Q + y*G. */ ulen = cd->generator_len; - memcpy(eU, pk->q, ulen); + br_memcpy(eU, pk->q, ulen); res = impl->muladd(eU, NULL, ulen, tx, nlen, ty, nlen, cd->curve); diff --git a/third_party/bearssl/gcm.c b/third_party/bearssl/gcm.c index ede5f0872..bb6911ec1 100644 --- a/third_party/bearssl/gcm.c +++ b/third_party/bearssl/gcm.c @@ -66,8 +66,8 @@ br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh) * with an all-zero IV and a zero counter, to CTR-encrypt an * all-zero block. */ - memset(ctx->h, 0, sizeof ctx->h); - memset(iv, 0, sizeof iv); + br_memset(ctx->h, 0, sizeof ctx->h); + br_memset(iv, 0, sizeof iv); (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h); } @@ -85,21 +85,21 @@ br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len) * (both 12-byte IV and 32-bit counter). */ if (len == 12) { - memcpy(ctx->j0_1, iv, 12); + br_memcpy(ctx->j0_1, iv, 12); ctx->j0_2 = 1; } else { unsigned char ty[16], tmp[16]; - memset(ty, 0, sizeof ty); + br_memset(ty, 0, sizeof ty); ctx->gh(ty, ctx->h, iv, len); - memset(tmp, 0, 8); + br_memset(tmp, 0, 8); br_enc64be(tmp + 8, (uint64_t)len << 3); ctx->gh(ty, ctx->h, tmp, 16); - memcpy(ctx->j0_1, ty, 12); + br_memcpy(ctx->j0_1, ty, 12); ctx->j0_2 = br_dec32be(ty + 12); } ctx->jc = ctx->j0_2 + 1; - memset(ctx->y, 0, sizeof ctx->y); + br_memset(ctx->y, 0, sizeof ctx->y); ctx->count_aad = 0; ctx->count_ctr = 0; } @@ -120,11 +120,11 @@ br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) clen = 16 - ptr; if (len < clen) { - memcpy(ctx->buf + ptr, data, len); + br_memcpy(ctx->buf + ptr, data, len); ctx->count_aad += (uint64_t)len; return; } - memcpy(ctx->buf + ptr, data, clen); + br_memcpy(ctx->buf + ptr, data, clen); ctx->gh(ctx->y, ctx->h, ctx->buf, 16); data = (const unsigned char *)data + clen; len -= clen; @@ -138,7 +138,7 @@ br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) */ dlen = len & ~(size_t)15; ctx->gh(ctx->y, ctx->h, data, dlen); - memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); + br_memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); ctx->count_aad += (uint64_t)len; } @@ -216,7 +216,7 @@ br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len) */ size_t u; - memset(ctx->buf, 0, sizeof ctx->buf); + br_memset(ctx->buf, 0, sizeof ctx->buf); ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, ctx->buf, 16); for (u = 0; u < len; u ++) { @@ -259,7 +259,7 @@ br_gcm_get_tag(br_gcm_context *ctx, void *tag) * Tag is the GHASH output XORed with the encryption of the * nonce with the initial counter value. */ - memcpy(tag, ctx->y, 16); + br_memcpy(tag, ctx->y, 16); (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16); } @@ -270,7 +270,7 @@ br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len) unsigned char tmp[16]; br_gcm_get_tag(ctx, tmp); - memcpy(tag, tmp, len); + br_memcpy(tag, tmp, len); } /* see bearssl_aead.h */ diff --git a/third_party/bearssl/ghash_ctmul.c b/third_party/bearssl/ghash_ctmul.c index 362320252..8a10ce772 100644 --- a/third_party/bearssl/ghash_ctmul.c +++ b/third_party/bearssl/ghash_ctmul.c @@ -232,8 +232,8 @@ br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) buf += 16; len -= 16; } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); src = tmp; len = 0; } @@ -332,7 +332,7 @@ br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); } - memcpy(yw, zw + 4, sizeof yw); + br_memcpy(yw, zw + 4, sizeof yw); } /* diff --git a/third_party/bearssl/ghash_ctmul64.c b/third_party/bearssl/ghash_ctmul64.c index a46f16fee..cd762fa74 100644 --- a/third_party/bearssl/ghash_ctmul64.c +++ b/third_party/bearssl/ghash_ctmul64.c @@ -105,8 +105,8 @@ br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len) buf += 16; len -= 16; } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); src = tmp; len = 0; } diff --git a/third_party/bearssl/ghash_pclmul.c b/third_party/bearssl/ghash_pclmul.c index a58e7dc02..81d61c25f 100644 --- a/third_party/bearssl/ghash_pclmul.c +++ b/third_party/bearssl/ghash_pclmul.c @@ -250,8 +250,8 @@ br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) buf2 = buf1 + (num4 << 6); num1 = (len + 15) >> 4; if ((len & 15) != 0) { - memcpy(tmp, buf2, len); - memset(tmp + len, 0, (num1 << 4) - len); + br_memcpy(tmp, buf2, len); + br_memset(tmp + len, 0, (num1 << 4) - len); buf2 = tmp; } diff --git a/third_party/bearssl/hmac.c b/third_party/bearssl/hmac.c index b43879887..b4ab81d83 100644 --- a/third_party/bearssl/hmac.c +++ b/third_party/bearssl/hmac.c @@ -42,11 +42,11 @@ process_key(const br_hash_class **hc, void *ks, size_t blen, u; blen = block_size(*hc); - memcpy(tmp, key, key_len); + br_memcpy(tmp, key, key_len); for (u = 0; u < key_len; u ++) { tmp[u] ^= (unsigned char)bb; } - memset(tmp + key_len, bb, blen - key_len); + br_memset(tmp + key_len, bb, blen - key_len); (*hc)->init(hc); (*hc)->update(hc, tmp, blen); (*hc)->state(hc, ks); @@ -85,7 +85,7 @@ br_hmac_init(br_hmac_context *ctx, blen = block_size(dig); dig->init(&ctx->dig.vtable); dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen); - memcpy(ctx->kso, kc->kso, sizeof kc->kso); + br_memcpy(ctx->kso, kc->kso, sizeof kc->kso); hlen = br_digest_size(dig); if (out_len > 0 && out_len < hlen) { hlen = out_len; @@ -117,6 +117,6 @@ br_hmac_out(const br_hmac_context *ctx, void *out) hlen = br_digest_size(dig); dig->update(&hc.vtable, tmp, hlen); dig->out(&hc.vtable, tmp); - memcpy(out, tmp, ctx->out_len); + br_memcpy(out, tmp, ctx->out_len); return ctx->out_len; } diff --git a/third_party/bearssl/hmac_ct.c b/third_party/bearssl/hmac_ct.c index e1c1d8024..546903767 100644 --- a/third_party/bearssl/hmac_ct.c +++ b/third_party/bearssl/hmac_ct.c @@ -150,7 +150,7 @@ br_hmac_outCT(const br_hmac_context *ctx, * Hash state is obtained whenever we reach a full block. This * is the result we want if and only if u == kz. */ - memset(tmp2, 0, sizeof tmp2); + br_memset(tmp2, 0, sizeof tmp2); for (u = 0; u < km; u ++) { uint32_t v; uint32_t d, e, x0, x1; @@ -188,6 +188,6 @@ br_hmac_outCT(const br_hmac_context *ctx, dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs); dig->update(&hc.vtable, tmp2, hlen); dig->out(&hc.vtable, tmp2); - memcpy(out, tmp2, ctx->out_len); + br_memcpy(out, tmp2, ctx->out_len); return ctx->out_len; } diff --git a/third_party/bearssl/hmac_drbg.c b/third_party/bearssl/hmac_drbg.c index d746756df..46f70087c 100644 --- a/third_party/bearssl/hmac_drbg.c +++ b/third_party/bearssl/hmac_drbg.c @@ -33,8 +33,8 @@ br_hmac_drbg_init(br_hmac_drbg_context *ctx, ctx->vtable = &br_hmac_drbg_vtable; hlen = br_digest_size(digest_class); - memset(ctx->K, 0x00, hlen); - memset(ctx->V, 0x01, hlen); + br_memset(ctx->K, 0x00, hlen); + br_memset(ctx->V, 0x01, hlen); ctx->digest_class = digest_class; br_hmac_drbg_update(ctx, seed, len); } @@ -64,7 +64,7 @@ br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len) if (clen > len) { clen = len; } - memcpy(buf, ctx->V, clen); + br_memcpy(buf, ctx->V, clen); buf += clen; len -= clen; } diff --git a/third_party/bearssl/i31_encode.c b/third_party/bearssl/i31_encode.c index b6b40c456..2ccadca88 100644 --- a/third_party/bearssl/i31_encode.c +++ b/third_party/bearssl/i31_encode.c @@ -35,7 +35,7 @@ br_i31_encode(void *dst, size_t len, const uint32_t *x) xlen = (x[0] + 31) >> 5; if (xlen == 0) { - memset(dst, 0, len); + br_memset(dst, 0, len); return; } buf = (unsigned char *)dst + len; diff --git a/third_party/bearssl/i31_moddiv.c b/third_party/bearssl/i31_moddiv.c index 995059119..0444b0b39 100644 --- a/third_party/bearssl/i31_moddiv.c +++ b/third_party/bearssl/i31_moddiv.c @@ -323,9 +323,9 @@ br_i31_moddiv(uint32_t *x, const uint32_t *y, const uint32_t *m, uint32_t m0i, b = a + len; u = x + 1; v = b + len; - memcpy(a, y + 1, len * sizeof *y); - memcpy(b, m + 1, len * sizeof *m); - memset(v, 0, len * sizeof *v); + br_memcpy(a, y + 1, len * sizeof *y); + br_memcpy(b, m + 1, len * sizeof *m); + br_memset(v, 0, len * sizeof *v); /* * Loop below ensures that a and b are reduced by some bits each, diff --git a/third_party/bearssl/i31_modpow.c b/third_party/bearssl/i31_modpow.c index 4ef3f5d5a..eaeeb9e2c 100644 --- a/third_party/bearssl/i31_modpow.c +++ b/third_party/bearssl/i31_modpow.c @@ -49,7 +49,7 @@ br_i31_modpow(uint32_t *x, * * Note that there is no need to call br_i32_from_monty(). */ - memcpy(t1, x, mlen); + br_memcpy(t1, x, mlen); br_i31_to_monty(t1, m); br_i31_zero(x, m[0]); x[1] = 1; @@ -60,6 +60,6 @@ br_i31_modpow(uint32_t *x, br_i31_montymul(t2, x, t1, m, m0i); CCOPY(ctl, x, t2, mlen); br_i31_montymul(t2, t1, t1, m, m0i); - memcpy(t1, t2, mlen); + br_memcpy(t1, t2, mlen); } } diff --git a/third_party/bearssl/i31_modpow2.c b/third_party/bearssl/i31_modpow2.c index 0b8f8cf7e..43248e395 100644 --- a/third_party/bearssl/i31_modpow2.c +++ b/third_party/bearssl/i31_modpow2.c @@ -71,9 +71,9 @@ br_i31_modpow_opt(uint32_t *x, * t2[k] is set to x^k (for k >= 1). */ if (win_len == 1) { - memcpy(t2, x, mlen); + br_memcpy(t2, x, mlen); } else { - memcpy(t2 + mwlen, x, mlen); + br_memcpy(t2 + mwlen, x, mlen); base = t2 + mwlen; for (u = 2; u < ((unsigned)1 << win_len); u ++) { br_i31_montymul(base + mwlen, base, x, m, m0i); @@ -121,7 +121,7 @@ br_i31_modpow_opt(uint32_t *x, */ for (i = 0; i < k; i ++) { br_i31_montymul(t1, x, x, m, m0i); - memcpy(x, t1, mlen); + br_memcpy(x, t1, mlen); } /* diff --git a/third_party/bearssl/i31_muladd.c b/third_party/bearssl/i31_muladd.c index eecd9e2c6..479d802ba 100644 --- a/third_party/bearssl/i31_muladd.c +++ b/third_party/bearssl/i31_muladd.c @@ -83,14 +83,14 @@ br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) hi = x[mlen]; if (mblr == 0) { a0 = x[mlen]; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + br_memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); x[1] = z; a1 = x[mlen]; b0 = m[mlen]; } else { a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & 0x7FFFFFFF; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); + br_memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); x[1] = z; a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & 0x7FFFFFFF; diff --git a/third_party/bearssl/i31_reduce.c b/third_party/bearssl/i31_reduce.c index 5c9523ed1..74bba6a9a 100644 --- a/third_party/bearssl/i31_reduce.c +++ b/third_party/bearssl/i31_reduce.c @@ -46,7 +46,7 @@ br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) a_bitlen = a[0]; alen = (a_bitlen + 31) >> 5; if (a_bitlen < m_bitlen) { - memcpy(x + 1, a + 1, alen * sizeof *a); + br_memcpy(x + 1, a + 1, alen * sizeof *a); for (u = alen; u < mlen; u ++) { x[u + 1] = 0; } @@ -58,7 +58,7 @@ br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) * We must thus copy N-1 words, and input the remaining words * one by one. */ - memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); + br_memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); x[mlen] = 0; for (u = 1 + alen - mlen; u > 0; u --) { br_i31_muladd_small(x, a[u], m); diff --git a/third_party/bearssl/i62_modpow2.c b/third_party/bearssl/i62_modpow2.c index 2db537f0a..d75e3795b 100644 --- a/third_party/bearssl/i62_modpow2.c +++ b/third_party/bearssl/i62_modpow2.c @@ -154,7 +154,7 @@ montymul(uint64_t *d, const uint64_t *x, const uint64_t *y, size_t u, num4; num4 = 1 + ((num - 1) & ~(size_t)3); - memset(d, 0, num * sizeof *d); + br_memset(d, 0, num * sizeof *d); dh = 0; for (u = 0; u < num; u ++) { size_t v; @@ -335,11 +335,11 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, * t2[k] is set to x^k (for k >= 1). */ if (win_len == 1) { - memcpy(t2, x, mw62num * sizeof *x); + br_memcpy(t2, x, mw62num * sizeof *x); } else { uint64_t *base; - memcpy(t2 + mw62num, x, mw62num * sizeof *x); + br_memcpy(t2 + mw62num, x, mw62num * sizeof *x); base = t2 + mw62num; for (u = 2; u < ((unsigned)1 << win_len); u ++) { montymul(base + mw62num, base, x, m, mw62num, m0i); @@ -401,7 +401,7 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, */ for (i = 0; i < k; i ++) { montymul(t1, x, x, m, mw62num, m0i); - memcpy(x, t1, mw62num * sizeof *x); + br_memcpy(x, t1, mw62num * sizeof *x); } /* @@ -413,7 +413,7 @@ br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, if (win_len > 1) { uint64_t *base; - memset(t2, 0, mw62num * sizeof *t2); + br_memset(t2, 0, mw62num * sizeof *t2); base = t2 + mw62num; for (u = 1; u < ((uint32_t)1 << k); u ++) { uint64_t mask; diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index 57ccd0600..872d4a78d 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -36,15 +36,7 @@ #include "bearssl.h" /* ==== BEG ClassiCube specific ==== */ -static size_t br_strlen(const char* a) { - int i = 0; - while (*a++) i++; - return i; -} - -#define br_memcpy memcpy -#define br_memset memset -#define br_memmove memmove +#include "bearssl_stdlib.h" /* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ #ifdef NXDK @@ -627,7 +619,7 @@ static inline void br_multihash_copyimpl(br_multihash_context *dst, const br_multihash_context *src) { - memcpy((void *)dst->impl, src->impl, sizeof src->impl); + br_memcpy((void *)dst->impl, src->impl, sizeof src->impl); } /* ==================================================================== */ @@ -1137,7 +1129,7 @@ static inline void br_i32_zero(uint32_t *x, uint32_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); + br_memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); } /* @@ -1285,7 +1277,7 @@ static inline void br_i31_zero(uint32_t *x, uint32_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); + br_memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); } /* @@ -1439,7 +1431,7 @@ static inline void br_i15_zero(uint16_t *x, uint16_t bit_len) { *x ++ = bit_len; - memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); + br_memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); } uint32_t br_i15_iszero(const uint16_t *x); diff --git a/third_party/bearssl/md5.c b/third_party/bearssl/md5.c index 0df7abe01..bf8a9ffd8 100644 --- a/third_party/bearssl/md5.c +++ b/third_party/bearssl/md5.c @@ -119,7 +119,7 @@ void br_md5_init(br_md5_context *cc) { cc->vtable = &br_md5_vtable; - memcpy(cc->val, br_md5_IV, sizeof cc->val); + br_memcpy(cc->val, br_md5_IV, sizeof cc->val); cc->count = 0; } @@ -139,7 +139,7 @@ br_md5_update(br_md5_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -160,15 +160,15 @@ br_md5_out(const br_md5_context *cc, void *dst) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_md5_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64le(buf + 56, cc->count << 3); br_md5_round(buf, val); diff --git a/third_party/bearssl/md5sha1.c b/third_party/bearssl/md5sha1.c index f701aeede..63767d8e2 100644 --- a/third_party/bearssl/md5sha1.c +++ b/third_party/bearssl/md5sha1.c @@ -29,8 +29,8 @@ void br_md5sha1_init(br_md5sha1_context *cc) { cc->vtable = &br_md5sha1_vtable; - memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); - memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); + br_memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); + br_memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); cc->count = 0; } @@ -50,7 +50,7 @@ br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -76,17 +76,17 @@ br_md5sha1_out(const br_md5sha1_context *cc, void *dst) count = cc->count; ptr = (size_t)count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val_md5, cc->val_md5, sizeof val_md5); - memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val_md5, cc->val_md5, sizeof val_md5); + br_memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_md5_round(buf, val_md5); br_sha1_round(buf, val_sha1); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } count <<= 3; br_enc64le(buf + 56, count); diff --git a/third_party/bearssl/multihash.c b/third_party/bearssl/multihash.c index b6df2e0ed..a91fcf11d 100644 --- a/third_party/bearssl/multihash.c +++ b/third_party/bearssl/multihash.c @@ -77,7 +77,7 @@ br_multihash_zero(br_multihash_context *ctx) * This is not standard, but yields very short and efficient code, * and it works "everywhere". */ - memset(ctx, 0, sizeof *ctx); + br_memset(ctx, 0, sizeof *ctx); } /* see bearssl_hash.h */ @@ -117,7 +117,7 @@ br_multihash_update(br_multihash_context *ctx, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(ctx->buf + ptr, buf, clen); + br_memcpy(ctx->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; diff --git a/third_party/bearssl/poly1305_ctmul.c b/third_party/bearssl/poly1305_ctmul.c index 150e610a9..1e9ef8d91 100644 --- a/third_party/bearssl/poly1305_ctmul.c +++ b/third_party/bearssl/poly1305_ctmul.c @@ -78,8 +78,8 @@ poly1305_inner(uint32_t *acc, const uint32_t *r, const void *data, size_t len) * If there is a partial block, right-pad it with zeros. */ if (len < 16) { - memset(tmp, 0, sizeof tmp); - memcpy(tmp, buf, len); + br_memset(tmp, 0, sizeof tmp); + br_memcpy(tmp, buf, len); buf = tmp; len = 16; } @@ -158,7 +158,7 @@ br_poly1305_ctmul_run(const void *key, const void *iv, * Compute the MAC key. The 'r' value is the first 16 bytes of * pkey[]. */ - memset(pkey, 0, sizeof pkey); + br_memset(pkey, 0, sizeof pkey); ichacha(key, iv, 0, pkey, sizeof pkey); /* @@ -189,7 +189,7 @@ br_poly1305_ctmul_run(const void *key, const void *iv, /* * Accumulator is 0. */ - memset(acc, 0, sizeof acc); + br_memset(acc, 0, sizeof acc); /* * Process the additional authenticated data, ciphertext, and diff --git a/third_party/bearssl/poly1305_ctmulq.c b/third_party/bearssl/poly1305_ctmulq.c index b00683a68..1c31cbb10 100644 --- a/third_party/bearssl/poly1305_ctmulq.c +++ b/third_party/bearssl/poly1305_ctmulq.c @@ -241,8 +241,8 @@ poly1305_inner_small(uint64_t *acc, uint64_t *r, const void *data, size_t len) unsigned char tmp[16]; if (len < 16) { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); + br_memcpy(tmp, buf, len); + br_memset(tmp + len, 0, (sizeof tmp) - len); buf = tmp; len = 16; } @@ -327,7 +327,7 @@ br_poly1305_ctmulq_run(const void *key, const void *iv, * Compute the MAC key. The 'r' value is the first 16 bytes of * pkey[]. */ - memset(pkey, 0, sizeof pkey); + br_memset(pkey, 0, sizeof pkey); ichacha(key, iv, 0, pkey, sizeof pkey); /* diff --git a/third_party/bearssl/prf_md5sha1.c b/third_party/bearssl/prf_md5sha1.c index 3212833ab..67839ddb4 100644 --- a/third_party/bearssl/prf_md5sha1.c +++ b/third_party/bearssl/prf_md5sha1.c @@ -35,7 +35,7 @@ br_tls10_prf(void *dst, size_t len, s1 = secret; slen = (secret_len + 1) >> 1; - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_md5_vtable, s1, slen, label, seed_num, seed); br_tls_phash(dst, len, &br_sha1_vtable, diff --git a/third_party/bearssl/prf_sha256.c b/third_party/bearssl/prf_sha256.c index 76041de87..c809f2577 100644 --- a/third_party/bearssl/prf_sha256.c +++ b/third_party/bearssl/prf_sha256.c @@ -30,7 +30,7 @@ br_tls12_sha256_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, size_t seed_num, const br_tls_prf_seed_chunk *seed) { - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_sha256_vtable, secret, secret_len, label, seed_num, seed); } diff --git a/third_party/bearssl/prf_sha384.c b/third_party/bearssl/prf_sha384.c index c20c4e65f..40b63c0ce 100644 --- a/third_party/bearssl/prf_sha384.c +++ b/third_party/bearssl/prf_sha384.c @@ -30,7 +30,7 @@ br_tls12_sha384_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, size_t seed_num, const br_tls_prf_seed_chunk *seed) { - memset(dst, 0, len); + br_memset(dst, 0, len); br_tls_phash(dst, len, &br_sha384_vtable, secret, secret_len, label, seed_num, seed); } diff --git a/third_party/bearssl/rsa_i31_pkcs1_vrfy.c b/third_party/bearssl/rsa_i31_pkcs1_vrfy.c index e79a002d7..03c01e3eb 100644 --- a/third_party/bearssl/rsa_i31_pkcs1_vrfy.c +++ b/third_party/bearssl/rsa_i31_pkcs1_vrfy.c @@ -35,7 +35,7 @@ br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, if (xlen > (sizeof sig)) { return 0; } - memcpy(sig, x, xlen); + br_memcpy(sig, x, xlen); if (!br_rsa_i31_public(sig, xlen, pk)) { return 0; } diff --git a/third_party/bearssl/rsa_i31_priv.c b/third_party/bearssl/rsa_i31_priv.c index b1e1244e2..0cb24b915 100644 --- a/third_party/bearssl/rsa_i31_priv.c +++ b/third_party/bearssl/rsa_i31_priv.c @@ -133,7 +133,7 @@ br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk) * Move the decoded p to another temporary buffer. */ mp = mq + 2 * fwlen; - memmove(mp, t1, fwlen * sizeof *t1); + br_memmove(mp, t1, fwlen * sizeof *t1); /* * Compute s2 = x^dq mod q. diff --git a/third_party/bearssl/rsa_i62_pkcs1_vrfy.c b/third_party/bearssl/rsa_i62_pkcs1_vrfy.c index 6519161b1..fb84a11ee 100644 --- a/third_party/bearssl/rsa_i62_pkcs1_vrfy.c +++ b/third_party/bearssl/rsa_i62_pkcs1_vrfy.c @@ -37,7 +37,7 @@ br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, if (xlen > (sizeof sig)) { return 0; } - memcpy(sig, x, xlen); + br_memcpy(sig, x, xlen); if (!br_rsa_i62_public(sig, xlen, pk)) { return 0; } diff --git a/third_party/bearssl/rsa_i62_priv.c b/third_party/bearssl/rsa_i62_priv.c index f0da60065..414278f01 100644 --- a/third_party/bearssl/rsa_i62_priv.c +++ b/third_party/bearssl/rsa_i62_priv.c @@ -135,7 +135,7 @@ br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk) * Move the decoded p to another temporary buffer. */ mp = (uint32_t *)(tmp + 2 * fwlen); - memmove(mp, t1, 2 * fwlen * sizeof *t1); + br_memmove(mp, t1, 2 * fwlen * sizeof *t1); /* * Compute s2 = x^dq mod q. diff --git a/third_party/bearssl/rsa_pkcs1_sig_unpad.c b/third_party/bearssl/rsa_pkcs1_sig_unpad.c index c8ae08fa8..e740ce405 100644 --- a/third_party/bearssl/rsa_pkcs1_sig_unpad.c +++ b/third_party/bearssl/rsa_pkcs1_sig_unpad.c @@ -93,7 +93,7 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, } else { x3 = hash_oid[0]; pad_len = x3 + 9; - memset(pad2, 0, pad_len); + br_memset(pad2, 0, pad_len); zlen = sig_len - u - hash_len; if (zlen == pad_len) { x2 = x3 + 2; @@ -109,13 +109,13 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, pad2[3] = 0x30; pad2[4] = x2; pad2[5] = 0x06; - memcpy(pad2 + 6, hash_oid, x3 + 1); + br_memcpy(pad2 + 6, hash_oid, x3 + 1); pad2[pad_len - 2] = 0x04; pad2[pad_len - 1] = hash_len; if (memcmp(pad2, sig + u, pad_len) != 0) { return 0; } } - memcpy(hash_out, sig + sig_len - hash_len, hash_len); + br_memcpy(hash_out, sig + sig_len - hash_len, hash_len); return 1; } diff --git a/third_party/bearssl/sha1.c b/third_party/bearssl/sha1.c index 4f65d8460..bce4baae8 100644 --- a/third_party/bearssl/sha1.c +++ b/third_party/bearssl/sha1.c @@ -101,7 +101,7 @@ void br_sha1_init(br_sha1_context *cc) { cc->vtable = &br_sha1_vtable; - memcpy(cc->val, br_sha1_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha1_IV, sizeof cc->val); cc->count = 0; } @@ -121,7 +121,7 @@ br_sha1_update(br_sha1_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -142,15 +142,15 @@ br_sha1_out(const br_sha1_context *cc, void *dst) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_sha1_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64be(buf + 56, cc->count << 3); br_sha1_round(buf, val); diff --git a/third_party/bearssl/sha2big.c b/third_party/bearssl/sha2big.c index 5be92ed56..badca0c59 100644 --- a/third_party/bearssl/sha2big.c +++ b/third_party/bearssl/sha2big.c @@ -156,7 +156,7 @@ sha2big_update(br_sha384_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -175,15 +175,15 @@ sha2big_out(const br_sha384_context *cc, void *dst, int num) size_t ptr; ptr = (size_t)cc->count & 127; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 112) { - memset(buf + ptr, 0, 128 - ptr); + br_memset(buf + ptr, 0, 128 - ptr); sha2big_round(buf, val); - memset(buf, 0, 112); + br_memset(buf, 0, 112); } else { - memset(buf + ptr, 0, 112 - ptr); + br_memset(buf + ptr, 0, 112 - ptr); } br_enc64be(buf + 112, cc->count >> 61); br_enc64be(buf + 120, cc->count << 3); @@ -196,7 +196,7 @@ void br_sha384_init(br_sha384_context *cc) { cc->vtable = &br_sha384_vtable; - memcpy(cc->val, IV384, sizeof IV384); + br_memcpy(cc->val, IV384, sizeof IV384); cc->count = 0; } @@ -235,7 +235,7 @@ void br_sha512_init(br_sha512_context *cc) { cc->vtable = &br_sha512_vtable; - memcpy(cc->val, IV512, sizeof IV512); + br_memcpy(cc->val, IV512, sizeof IV512); cc->count = 0; } diff --git a/third_party/bearssl/sha2small.c b/third_party/bearssl/sha2small.c index ca196559e..4accfb73f 100644 --- a/third_party/bearssl/sha2small.c +++ b/third_party/bearssl/sha2small.c @@ -215,7 +215,7 @@ sha2small_update(br_sha224_context *cc, const void *data, size_t len) if (clen > len) { clen = len; } - memcpy(cc->buf + ptr, buf, clen); + br_memcpy(cc->buf + ptr, buf, clen); ptr += clen; buf += clen; len -= clen; @@ -234,15 +234,15 @@ sha2small_out(const br_sha224_context *cc, void *dst, int num) size_t ptr; ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); + br_memcpy(buf, cc->buf, ptr); + br_memcpy(val, cc->val, sizeof val); buf[ptr ++] = 0x80; if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); + br_memset(buf + ptr, 0, 64 - ptr); br_sha2small_round(buf, val); - memset(buf, 0, 56); + br_memset(buf, 0, 56); } else { - memset(buf + ptr, 0, 56 - ptr); + br_memset(buf + ptr, 0, 56 - ptr); } br_enc64be(buf + 56, cc->count << 3); br_sha2small_round(buf, val); @@ -254,7 +254,7 @@ void br_sha224_init(br_sha224_context *cc) { cc->vtable = &br_sha224_vtable; - memcpy(cc->val, br_sha224_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha224_IV, sizeof cc->val); cc->count = 0; } @@ -293,7 +293,7 @@ void br_sha256_init(br_sha256_context *cc) { cc->vtable = &br_sha256_vtable; - memcpy(cc->val, br_sha256_IV, sizeof cc->val); + br_memcpy(cc->val, br_sha256_IV, sizeof cc->val); cc->count = 0; } diff --git a/third_party/bearssl/ssl_client.c b/third_party/bearssl/ssl_client.c index 7975bcace..9f5f0dcf2 100644 --- a/third_party/bearssl/ssl_client.c +++ b/third_party/bearssl/ssl_client.c @@ -31,10 +31,10 @@ br_ssl_client_zero(br_ssl_client_context *cc) /* * For really standard C, we should explicitly set to NULL all * pointers, and 0 all other fields. However, on all our target - * architectures, a direct memset() will work, be faster, and + * architectures, a direct br_memset() will work, be faster, and * use a lot less code. */ - memset(cc, 0, sizeof *cc); + br_memset(cc, 0, sizeof *cc); } /* see bearssl_ssl.h */ @@ -69,7 +69,7 @@ br_ssl_client_reset(br_ssl_client_context *cc, br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM); return 0; } - memcpy(cc->eng.server_name, server_name, n); + br_memcpy(cc->eng.server_name, server_name, n); } br_ssl_engine_hs_reset(&cc->eng, diff --git a/third_party/bearssl/ssl_engine.c b/third_party/bearssl/ssl_engine.c index 61f8c0ef4..1a52420a6 100644 --- a/third_party/bearssl/ssl_engine.c +++ b/third_party/bearssl/ssl_engine.c @@ -954,7 +954,7 @@ br_ssl_engine_set_suites(br_ssl_engine_context *cc, br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM); return; } - memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); + br_memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); cc->suites_num = suites_num; } diff --git a/third_party/bearssl/ssl_hs_client.c b/third_party/bearssl/ssl_hs_client.c index 8aeebe505..b3353a94a 100644 --- a/third_party/bearssl/ssl_hs_client.c +++ b/third_party/bearssl/ssl_hs_client.c @@ -315,7 +315,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) return -BR_ERR_INVALID_ALGORITHM; } - memcpy(point, point_src, glen); + br_memcpy(point, point_src, glen); if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { return -BR_ERR_INVALID_ALGORITHM; } @@ -327,7 +327,7 @@ make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); ctx->eng.iec->mulgen(point, key, olen, curve); - memcpy(ctx->eng.pad, point, glen); + br_memcpy(ctx->eng.pad, point, glen); return (int)glen; } @@ -355,7 +355,7 @@ make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) if (point_len > sizeof point) { return -1; } - memcpy(point, pk->key.ec.q, point_len); + br_memcpy(point, pk->key.ec.q, point_len); if (!(*ctx->client_auth_vtable)->do_keyx( ctx->client_auth_vtable, point, &point_len)) { @@ -925,7 +925,7 @@ br_ssl_hs_client_run(void *t0ctx) #define T0_ROLL(x) do { \ size_t t0len = (size_t)(x); \ uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + br_memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_SWAP() do { \ @@ -1186,7 +1186,7 @@ br_ssl_hs_client_run(void *t0ctx) size_t len = (size_t)T0_POP(); void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - memset(addr, 0, len); + br_memset(addr, 0, len); } break; @@ -1235,7 +1235,7 @@ br_ssl_hs_client_run(void *t0ctx) if (clen > sizeof ENG->pad) { clen = sizeof ENG->pad; } - memcpy(ENG->pad, ENG->cert_cur, clen); + br_memcpy(ENG->pad, ENG->cert_cur, clen); ENG->cert_cur += clen; ENG->cert_len -= clen; T0_PUSH(clen); @@ -1247,7 +1247,7 @@ br_ssl_hs_client_run(void *t0ctx) size_t idx = T0_POP(); size_t len = br_strlen(ENG->protocol_names[idx]); - memcpy(ENG->pad, ENG->protocol_names[idx], len); + br_memcpy(ENG->pad, ENG->protocol_names[idx], len); T0_PUSH(len); } @@ -1449,12 +1449,12 @@ br_ssl_hs_client_run(void *t0ctx) } break; case 49: { - /* memcpy */ + /* br_memcpy */ size_t len = (size_t)T0_POP(); void *src = (unsigned char *)ENG + (size_t)T0_POP(); void *dst = (unsigned char *)ENG + (size_t)T0_POP(); - memcpy(dst, src, len); + br_memcpy(dst, src, len); } break; @@ -1523,7 +1523,7 @@ br_ssl_hs_client_run(void *t0ctx) if ((size_t)len < clen) { clen = (size_t)len; } - memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); + br_memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); if (ENG->record_type_in == BR_SSL_HANDSHAKE) { br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); } @@ -1821,7 +1821,7 @@ br_ssl_hs_client_run(void *t0ctx) if ((size_t)len < clen) { clen = (size_t)len; } - memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); + br_memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); if (ENG->record_type_out == BR_SSL_HANDSHAKE) { br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); } diff --git a/third_party/bearssl/ssl_io.c b/third_party/bearssl/ssl_io.c index 195261595..7d4eeabe1 100644 --- a/third_party/bearssl/ssl_io.c +++ b/third_party/bearssl/ssl_io.c @@ -159,7 +159,7 @@ br_sslio_read(br_sslio_context *ctx, void *dst, size_t len) if (alen > len) { alen = len; } - memcpy(dst, buf, alen); + br_memcpy(dst, buf, alen); br_ssl_engine_recvapp_ack(ctx->engine, alen); return (int)alen; } @@ -201,7 +201,7 @@ br_sslio_write(br_sslio_context *ctx, const void *src, size_t len) if (alen > len) { alen = len; } - memcpy(buf, src, alen); + br_memcpy(buf, src, alen); br_ssl_engine_sendapp_ack(ctx->engine, alen); return (int)alen; } diff --git a/third_party/bearssl/ssl_rec_cbc.c b/third_party/bearssl/ssl_rec_cbc.c index c38cbfdfb..70615292a 100644 --- a/third_party/bearssl/ssl_rec_cbc.c +++ b/third_party/bearssl/ssl_rec_cbc.c @@ -38,10 +38,10 @@ in_cbc_init(br_sslrec_in_cbc_context *cc, br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); cc->mac_len = mac_out_len; if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); + br_memset(cc->iv, 0, sizeof cc->iv); cc->explicit_IV = 1; } else { - memcpy(cc->iv, iv, bc_impl->block_size); + br_memcpy(cc->iv, iv, bc_impl->block_size); cc->explicit_IV = 0; } } @@ -91,7 +91,7 @@ cond_rotate(uint32_t ctl, unsigned char *buf, size_t len, size_t num) v = 0; } } - memcpy(buf, tmp, len); + br_memcpy(buf, tmp, len); } static unsigned char * @@ -163,7 +163,7 @@ cbc_decrypt(br_sslrec_in_cbc_context *cc, len_nomac = len_withmac - cc->mac_len; min_len -= cc->mac_len; rot_count = 0; - memset(tmp1, 0, cc->mac_len); + br_memset(tmp1, 0, cc->mac_len); v = 0; for (u = min_len; u < max_len; u ++) { tmp1[v] |= MUX(GE(u, len_nomac) & LT(u, len_withmac), @@ -278,10 +278,10 @@ out_cbc_init(br_sslrec_out_cbc_context *cc, br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); cc->mac_len = mac_out_len; if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); + br_memset(cc->iv, 0, sizeof cc->iv); cc->explicit_IV = 1; } else { - memcpy(cc->iv, iv, bc_impl->block_size); + br_memcpy(cc->iv, iv, bc_impl->block_size); cc->explicit_IV = 0; } } @@ -391,7 +391,7 @@ cbc_encrypt(br_sslrec_out_cbc_context *cc, * Add padding. */ plen = blen - (len & (blen - 1)); - memset(buf + len, (unsigned)plen - 1, plen); + br_memset(buf + len, (unsigned)plen - 1, plen); len += plen; /* diff --git a/third_party/bearssl/ssl_rec_ccm.c b/third_party/bearssl/ssl_rec_ccm.c index 92c329521..86b1efc35 100644 --- a/third_party/bearssl/ssl_rec_ccm.c +++ b/third_party/bearssl/ssl_rec_ccm.c @@ -37,7 +37,7 @@ gen_ccm_init(br_sslrec_ccm_context *cc, { cc->seq = 0; bc_impl->init(&cc->bc.vtable, key, key_len); - memcpy(cc->iv, iv, sizeof cc->iv); + br_memcpy(cc->iv, iv, sizeof cc->iv); cc->tag_len = tag_len; } @@ -79,8 +79,8 @@ ccm_decrypt(br_sslrec_ccm_context *cc, /* * Make nonce (implicit + explicit parts). */ - memcpy(nonce, cc->iv, sizeof cc->iv); - memcpy(nonce + 4, data, 8); + br_memcpy(nonce, cc->iv, sizeof cc->iv); + br_memcpy(nonce + 4, data, 8); /* * Assemble synthetic header for the AAD. @@ -161,7 +161,7 @@ ccm_encrypt(br_sslrec_ccm_context *cc, * Make nonce; the explicit part is an encoding of the sequence * number. */ - memcpy(nonce, cc->iv, sizeof cc->iv); + br_memcpy(nonce, cc->iv, sizeof cc->iv); br_enc64be(nonce + 4, cc->seq); /* @@ -187,7 +187,7 @@ ccm_encrypt(br_sslrec_ccm_context *cc, */ len += 8 + cc->tag_len; buf -= 13; - memcpy(buf + 5, nonce + 4, 8); + br_memcpy(buf + 5, nonce + 4, 8); buf[0] = (unsigned char)record_type; br_enc16be(buf + 1, version); br_enc16be(buf + 3, len); diff --git a/third_party/bearssl/ssl_rec_chapol.c b/third_party/bearssl/ssl_rec_chapol.c index 73b3c7855..2d4abafef 100644 --- a/third_party/bearssl/ssl_rec_chapol.c +++ b/third_party/bearssl/ssl_rec_chapol.c @@ -32,8 +32,8 @@ gen_chapol_init(br_sslrec_chapol_context *cc, cc->seq = 0; cc->ichacha = ichacha; cc->ipoly = ipoly; - memcpy(cc->key, key, sizeof cc->key); - memcpy(cc->iv, iv, sizeof cc->iv); + br_memcpy(cc->key, key, sizeof cc->key); + br_memcpy(cc->iv, iv, sizeof cc->iv); } static void @@ -51,7 +51,7 @@ gen_chapol_process(br_sslrec_chapol_context *cc, header[8] = (unsigned char)record_type; br_enc16be(header + 9, version); br_enc16be(header + 11, len); - memcpy(nonce, cc->iv, 12); + br_memcpy(nonce, cc->iv, 12); for (u = 0; u < 8; u ++) { nonce[11 - u] ^= (unsigned char)seq; seq >>= 8; diff --git a/third_party/bearssl/ssl_rec_gcm.c b/third_party/bearssl/ssl_rec_gcm.c index 70df2777b..349cc2e48 100644 --- a/third_party/bearssl/ssl_rec_gcm.c +++ b/third_party/bearssl/ssl_rec_gcm.c @@ -41,9 +41,9 @@ gen_gcm_init(br_sslrec_gcm_context *cc, cc->seq = 0; bc_impl->init(&cc->bc.vtable, key, key_len); cc->gh = gh_impl; - memcpy(cc->iv, iv, sizeof cc->iv); - memset(cc->h, 0, sizeof cc->h); - memset(tmp, 0, sizeof tmp); + br_memcpy(cc->iv, iv, sizeof cc->iv); + br_memset(cc->h, 0, sizeof cc->h); + br_memset(tmp, 0, sizeof tmp); bc_impl->run(&cc->bc.vtable, tmp, 0, cc->h, sizeof cc->h); } @@ -96,7 +96,7 @@ do_tag(br_sslrec_gcm_context *cc, br_enc16be(header + 11, len); br_enc64be(footer, (uint64_t)(sizeof header) << 3); br_enc64be(footer + 8, (uint64_t)len << 3); - memset(tag, 0, 16); + br_memset(tag, 0, 16); cc->gh(tag, cc->h, header, sizeof header); cc->gh(tag, cc->h, data, len); cc->gh(tag, cc->h, footer, sizeof footer); @@ -113,8 +113,8 @@ do_ctr(br_sslrec_gcm_context *cc, const void *nonce, void *data, size_t len, { unsigned char iv[12]; - memcpy(iv, cc->iv, 4); - memcpy(iv + 4, nonce, 8); + br_memcpy(iv, cc->iv, 4); + br_memcpy(iv + 4, nonce, 8); cc->bc.vtable->run(&cc->bc.vtable, iv, 2, data, len); cc->bc.vtable->run(&cc->bc.vtable, iv, 1, xortag, 16); } @@ -201,7 +201,7 @@ gcm_encrypt(br_sslrec_gcm_context *cc, buf = (unsigned char *)data; len = *data_len; - memset(tmp, 0, sizeof tmp); + br_memset(tmp, 0, sizeof tmp); br_enc64be(buf - 8, cc->seq); do_ctr(cc, buf - 8, buf, len, tmp); do_tag(cc, record_type, version, buf, len, buf + len); diff --git a/third_party/bearssl/x509_minimal.c b/third_party/bearssl/x509_minimal.c index 9611a8e77..ad4578da9 100644 --- a/third_party/bearssl/x509_minimal.c +++ b/third_party/bearssl/x509_minimal.c @@ -214,7 +214,7 @@ br_x509_minimal_init(br_x509_minimal_context *ctx, const br_hash_class *dn_hash_impl, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) { - memset(ctx, 0, sizeof *ctx); + br_memset(ctx, 0, sizeof *ctx); ctx->vtable = &br_x509_minimal_vtable; ctx->dn_hash_impl = dn_hash_impl; ctx->trust_anchors = trust_anchors; @@ -232,7 +232,7 @@ xm_start_chain(const br_x509_class **ctx, const char *server_name) cc->name_elts[u].status = 0; cc->name_elts[u].buf[0] = 0; } - memset(&cc->pkey, 0, sizeof cc->pkey); + br_memset(&cc->pkey, 0, sizeof cc->pkey); cc->num_certs = 0; cc->err = 0; cc->cpu.dp = cc->dp_stack; @@ -885,7 +885,7 @@ br_x509_minimal_run(void *t0ctx) #define T0_ROLL(x) do { \ size_t t0len = (size_t)(x); \ uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ + br_memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ *(dp - 1) = t0tmp; \ } while (0) #define T0_SWAP() do { \ @@ -1099,7 +1099,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = T0_POP(); unsigned char *src = (unsigned char *)CTX + T0_POP(); unsigned char *dst = (unsigned char *)CTX + T0_POP(); - memcpy(dst, src, len); + br_memcpy(dst, src, len); } break; @@ -1251,7 +1251,7 @@ br_x509_minimal_run(void *t0ctx) size_t qlen = T0_POP(); uint32_t curve = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); + br_memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); CTX->pkey.key_type = BR_KEYTYPE_EC; CTX->pkey.key.ec.curve = curve; CTX->pkey.key.ec.q = CTX->ee_pkey_data; @@ -1264,7 +1264,7 @@ br_x509_minimal_run(void *t0ctx) size_t elen = T0_POP(); size_t nlen = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); + br_memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); CTX->pkey.key_type = BR_KEYTYPE_RSA; CTX->pkey.key.rsa.n = CTX->ee_pkey_data; CTX->pkey.key.rsa.nlen = nlen; @@ -1287,7 +1287,7 @@ br_x509_minimal_run(void *t0ctx) ne = &CTX->name_elts[u]; if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { if (ok && ne->len > len) { - memcpy(ne->buf, CTX->pad + 1, len); + br_memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { @@ -1312,7 +1312,7 @@ br_x509_minimal_run(void *t0ctx) if (ok) { len = CTX->pad[0]; if (len < ne->len) { - memcpy(ne->buf, CTX->pad + 1, len); + br_memcpy(ne->buf, CTX->pad + 1, len); ne->buf[len] = 0; ne->status = 1; } else { @@ -1532,7 +1532,7 @@ br_x509_minimal_run(void *t0ctx) clen = (size_t)len; } if (addr != 0) { - memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); + br_memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); } if (CTX->do_mhash) { br_multihash_update(&CTX->mhash, CTX->hbuf, clen); From 359643af24848eaaf6f0b9c433b67b595277b201 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 27 Aug 2025 18:02:39 +1000 Subject: [PATCH 050/115] And don't forget memcmp --- third_party/bearssl/bearssl_stdlib.h | 13 +++++++++++++ third_party/bearssl/rsa_pkcs1_sig_unpad.c | 4 ++-- third_party/bearssl/ssl_hs_client.c | 8 ++++---- third_party/bearssl/x509_minimal.c | 16 ++++++++-------- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/third_party/bearssl/bearssl_stdlib.h b/third_party/bearssl/bearssl_stdlib.h index 7f9f0316f..77a5998be 100644 --- a/third_party/bearssl/bearssl_stdlib.h +++ b/third_party/bearssl/bearssl_stdlib.h @@ -7,6 +7,19 @@ static size_t br_strlen(const char* a) { return i; } +static size_t br_memcmp(const void* a, const void* b, size_t len) { + unsigned char* p1 = (unsigned char*)a; + unsigned char* p2 = (unsigned char*)b; + size_t i; + + for (i = 0; i < len; i++) + { + if (p1[i] < p2[i]) return -1; + if (p1[i] > p2[i]) return 1; + } + return 0; +} + #ifdef CC_BUILD_NOSTDLIB extern void* Mem_Copy(void* dst, const void* src, unsigned size); extern void* Mem_Move(void* dst, const void* src, unsigned size); diff --git a/third_party/bearssl/rsa_pkcs1_sig_unpad.c b/third_party/bearssl/rsa_pkcs1_sig_unpad.c index e740ce405..aac4998e0 100644 --- a/third_party/bearssl/rsa_pkcs1_sig_unpad.c +++ b/third_party/bearssl/rsa_pkcs1_sig_unpad.c @@ -71,7 +71,7 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, * The comparison is valid because we made sure that the signature * is at least 11 bytes long. */ - if (memcmp(sig, pad1, sizeof pad1) != 0) { + if (br_memcmp(sig, pad1, sizeof pad1) != 0) { return 0; } for (u = sizeof pad1; u < sig_len; u ++) { @@ -112,7 +112,7 @@ br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, br_memcpy(pad2 + 6, hash_oid, x3 + 1); pad2[pad_len - 2] = 0x04; pad2[pad_len - 1] = hash_len; - if (memcmp(pad2, sig + u, pad_len) != 0) { + if (br_memcmp(pad2, sig + u, pad_len) != 0) { return 0; } } diff --git a/third_party/bearssl/ssl_hs_client.c b/third_party/bearssl/ssl_hs_client.c index b3353a94a..bd396965b 100644 --- a/third_party/bearssl/ssl_hs_client.c +++ b/third_party/bearssl/ssl_hs_client.c @@ -241,7 +241,7 @@ verify_SKE_sig(br_ssl_client_context *ctx, } if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len, hash_oid, hv_len, &pk->key.rsa, tmp) - || memcmp(tmp, hv, hv_len) != 0) + || br_memcmp(tmp, hv, hv_len) != 0) { return BR_ERR_BAD_SIGNATURE; } @@ -1438,12 +1438,12 @@ br_ssl_hs_client_run(void *t0ctx) } break; case 48: { - /* memcmp */ + /* br_memcmp */ size_t len = (size_t)T0_POP(); void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); - int x = memcmp(addr1, addr2, len); + int x = br_memcmp(addr1, addr2, len); T0_PUSH((uint32_t)-(x == 0)); } @@ -1766,7 +1766,7 @@ br_ssl_hs_client_run(void *t0ctx) const char *name; name = ENG->protocol_names[u]; - if (len == br_strlen(name) && memcmp(ENG->pad, name, len) == 0) { + if (len == br_strlen(name) && br_memcmp(ENG->pad, name, len) == 0) { T0_PUSH(u); T0_RET(); } diff --git a/third_party/bearssl/x509_minimal.c b/third_party/bearssl/x509_minimal.c index ad4578da9..78d82777b 100644 --- a/third_party/bearssl/x509_minimal.c +++ b/third_party/bearssl/x509_minimal.c @@ -372,7 +372,7 @@ eqbigint(const unsigned char *b1, size_t len1, if (len1 != len2) { return 0; } - return memcmp(b1, b2, len1) == 0; + return br_memcmp(b1, b2, len1) == 0; } /* @@ -1118,7 +1118,7 @@ br_x509_minimal_run(void *t0ctx) continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { + if (br_memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { continue; } kt = CTX->pkey.key_type; @@ -1144,7 +1144,7 @@ br_x509_minimal_run(void *t0ctx) case BR_KEYTYPE_EC: if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen - || memcmp(CTX->pkey.key.ec.q, + || br_memcmp(CTX->pkey.key.ec.q, ta->pkey.key.ec.q, ta->pkey.key.ec.qlen) != 0) { @@ -1179,7 +1179,7 @@ br_x509_minimal_run(void *t0ctx) continue; } hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { + if (br_memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { continue; } if (verify_signature(CTX, &ta->pkey) == 0) { @@ -1389,7 +1389,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = a1[0]; int x; if (len == a2[0]) { - x = -(memcmp(a1 + 1, a2 + 1, len) == 0); + x = -(br_memcmp(a1 + 1, a2 + 1, len) == 0); } else { x = 0; } @@ -1403,7 +1403,7 @@ br_x509_minimal_run(void *t0ctx) size_t len = T0_POP(); const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); - T0_PUSHi(-(memcmp(a1, a2, len) == 0)); + T0_PUSHi(-(br_memcmp(a1, a2, len) == 0)); } break; @@ -1496,7 +1496,7 @@ br_x509_minimal_run(void *t0ctx) } len = oid[off]; if (len != 0 && len == CTX->pad[0] - && memcmp(oid + off + 1, + && br_memcmp(oid + off + 1, CTX->pad + 1, len) == 0) { T0_PUSH(u); @@ -1672,7 +1672,7 @@ verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) { return BR_ERR_X509_BAD_SIGNATURE; } - if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { + if (br_memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { return BR_ERR_X509_BAD_SIGNATURE; } return 0; From 70b1d1a87abfa9435436726604b97f48169bc80e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 27 Aug 2025 22:13:23 +1000 Subject: [PATCH 051/115] Provide common null/stub platform socket and threading backends --- src/32x/Platform_32x.c | 76 +----------------------- src/Platform_MacClassic.c | 87 +-------------------------- src/Platform_N64.c | 75 +---------------------- src/_PlatformBase.h | 80 +++++++++++++++++++++++++ src/amiga/Platform_Amiga.c | 108 ++++------------------------------ src/amiga/Window_Amiga.c | 16 ++--- src/atari_st/Platform_Atari.c | 76 +----------------------- src/gba/Platform_GBA.c | 76 +----------------------- src/msdos/Platform_MSDOS.c | 75 ++--------------------- src/ps1/Platform_PS1.c | 76 +----------------------- src/saturn/Platform_Saturn.c | 76 +----------------------- 11 files changed, 116 insertions(+), 705 deletions(-) diff --git a/src/32x/Platform_32x.c b/src/32x/Platform_32x.c index 835d72b8c..24bdbdd04 100644 --- a/src/32x/Platform_32x.c +++ b/src/32x/Platform_32x.c @@ -1,6 +1,8 @@ #define OVERRIDE_MEM_FUNCTIONS #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -210,80 +212,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Hw32xDelay(1); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* diff --git a/src/Platform_MacClassic.c b/src/Platform_MacClassic.c index b3430ece5..03187ae90 100644 --- a/src/Platform_MacClassic.c +++ b/src/Platform_MacClassic.c @@ -2,6 +2,8 @@ #if defined CC_BUILD_MACCLASSIC #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "_PlatformBase.h" #include "Stream.h" @@ -364,91 +366,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Delay(delay, &final); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; - // TODO -} - -void Thread_Detach(void* handle) { - // TODO -} - -void Thread_Join(void* handle) { - // TODO -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { - // TODO -} - -void Mutex_Lock(void* handle) { - // TODO -} - -void Mutex_Unlock(void* handle) { - // TODO -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { - // TODO -} - -void Waitable_Signal(void* handle) { - // TODO -} - -void Waitable_Wait(void* handle) { - // TODO -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { - // TODO -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { - -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* diff --git a/src/Platform_N64.c b/src/Platform_N64.c index b35ac06eb..284b8baa9 100644 --- a/src/Platform_N64.c +++ b/src/Platform_N64.c @@ -2,6 +2,8 @@ #if defined CC_BUILD_N64 #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #define CC_XTEA_ENCRYPTION #include "_PlatformBase.h" @@ -201,79 +203,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { wait_ms(milliseconds); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { } - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index 9c6c5a7dc..4a170d28d 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -376,3 +376,83 @@ void* DynamicLib_Get2(void* lib, const char* name) { return NULL; } cc_bool DynamicLib_DescribeError(cc_string* dst) { return false; } #endif + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_SOCKETS +cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +void Socket_Close(cc_socket s) { } + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + return ERR_NOT_SUPPORTED; +} +#endif + + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_NO_THREADING +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + *handle = NULL; +} + +void Thread_Detach(void* handle) { +} + +void Thread_Join(void* handle) { +} + +void* Mutex_Create(const char* name) { + return NULL; +} + +void Mutex_Free(void* handle) { +} + +void Mutex_Lock(void* handle) { +} + +void Mutex_Unlock(void* handle) { +} + +void* Waitable_Create(const char* name) { + return NULL; +} + +void Waitable_Free(void* handle) { +} + +void Waitable_Signal(void* handle) { +} + +void Waitable_Wait(void* handle) { +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { +} +#endif diff --git a/src/amiga/Platform_Amiga.c b/src/amiga/Platform_Amiga.c index 6ec0d9559..6df619547 100644 --- a/src/amiga/Platform_Amiga.c +++ b/src/amiga/Platform_Amiga.c @@ -1,17 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_AMIGA #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" #include #include @@ -213,91 +213,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { Delay(ticks); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; - // TODO -} - -void Thread_Detach(void* handle) { - // TODO -} - -void Thread_Join(void* handle) { - // TODO -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { - // TODO -} - -void Mutex_Lock(void* handle) { - // TODO -} - -void Mutex_Unlock(void* handle) { - // TODO -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { - // TODO -} - -void Waitable_Signal(void* handle) { - // TODO -} - -void Waitable_Wait(void* handle) { - // TODO -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { - // TODO -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { - -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* @@ -368,4 +283,3 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { cc_result Platform_GetEntropy(void* data, int len) { return ERR_NOT_SUPPORTED; } -#endif diff --git a/src/amiga/Window_Amiga.c b/src/amiga/Window_Amiga.c index 16553c9fd..38a7806ba 100644 --- a/src/amiga/Window_Amiga.c +++ b/src/amiga/Window_Amiga.c @@ -1,12 +1,9 @@ -#include "Core.h" -#if defined CC_BUILD_AMIGA - -#include "_WindowBase.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Options.h" -#include "Errors.h" +#include "../_WindowBase.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Options.h" +#include "../Errors.h" /*########################################################################################################################* @@ -147,4 +144,3 @@ void Window_UpdateRawMouse(void) { void Window_DisableRawMouse(void) { DefaultDisableRawMouse(); } -#endif diff --git a/src/atari_st/Platform_Atari.c b/src/atari_st/Platform_Atari.c index 2a09beb03..1ddad6b12 100644 --- a/src/atari_st/Platform_Atari.c +++ b/src/atari_st/Platform_Atari.c @@ -1,5 +1,7 @@ #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -198,80 +200,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { // TODO probably wrong } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* diff --git a/src/gba/Platform_GBA.c b/src/gba/Platform_GBA.c index 6951699ba..553c4c1fb 100644 --- a/src/gba/Platform_GBA.c +++ b/src/gba/Platform_GBA.c @@ -1,5 +1,7 @@ #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -259,80 +261,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { //swiDelay(8378 * milliseconds); // TODO probably wrong } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* diff --git a/src/msdos/Platform_MSDOS.c b/src/msdos/Platform_MSDOS.c index f18d74b39..60b3c1d22 100644 --- a/src/msdos/Platform_MSDOS.c +++ b/src/msdos/Platform_MSDOS.c @@ -1,5 +1,7 @@ #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -129,9 +131,9 @@ void Process_Abort2(cc_result result, const char* raw_msg) { #define US_PER_SEC 1000000ULL cc_uint64 Stopwatch_Measure(void) { - struct timeval cur; - gettimeofday(&cur, NULL); - return (cc_uint64)cur.tv_sec * US_PER_SEC + cur.tv_usec; + struct timeval cur; + gettimeofday(&cur, NULL); + return (cc_uint64)cur.tv_sec * US_PER_SEC + cur.tv_usec; } cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { @@ -262,73 +264,6 @@ cc_result File_Length(cc_file file, cc_uint32* len) { *#########################################################################################################################*/ void Thread_Sleep(cc_uint32 milliseconds) { usleep(milliseconds * 1000); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { } - -void Thread_Join(void* handle) { } - -void* Mutex_Create(const char* name) { return NULL; } - -void Mutex_Free(void* handle) { } - -void Mutex_Lock(void* handle) { } - -void Mutex_Unlock(void* handle) { } - -void* Waitable_Create(const char* name) { return NULL; } - -void Waitable_Free(void* handle) { } - -void Waitable_Signal(void* handle) { } - -void Waitable_Wait(void* handle) { } - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { } - - -/*########################################################################################################################* -*--------------------------------------------------------Font/Text--------------------------------------------------------* -*#########################################################################################################################*/ -void Platform_LoadSysFonts(void) { } - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* diff --git a/src/ps1/Platform_PS1.c b/src/ps1/Platform_PS1.c index 6f1d999ce..0ca7d3486 100644 --- a/src/ps1/Platform_PS1.c +++ b/src/ps1/Platform_PS1.c @@ -1,6 +1,8 @@ #define CC_XTEA_ENCRYPTION #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -172,80 +174,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { ChangeClearPAD(0); } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index f8a311305..6edbb4f7a 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -1,6 +1,8 @@ #define CC_XTEA_ENCRYPTION #define CC_NO_UPDATER #define CC_NO_DYNLIB +#define CC_NO_SOCKETS +#define CC_NO_THREADING #include "../_PlatformBase.h" #include "../Stream.h" @@ -204,80 +206,6 @@ void Thread_Sleep(cc_uint32 milliseconds) { } } -void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { - *handle = NULL; -} - -void Thread_Detach(void* handle) { -} - -void Thread_Join(void* handle) { -} - -void* Mutex_Create(const char* name) { - return NULL; -} - -void Mutex_Free(void* handle) { -} - -void Mutex_Lock(void* handle) { -} - -void Mutex_Unlock(void* handle) { -} - -void* Waitable_Create(const char* name) { - return NULL; -} - -void Waitable_Free(void* handle) { -} - -void Waitable_Signal(void* handle) { -} - -void Waitable_Wait(void* handle) { -} - -void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { -} - - -/*########################################################################################################################* -*---------------------------------------------------------Socket----------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { - return ERR_NOT_SUPPORTED; -} - -void Socket_Close(cc_socket s) { -} - -cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { - return ERR_NOT_SUPPORTED; -} - -cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { - return ERR_NOT_SUPPORTED; -} - /*########################################################################################################################* *--------------------------------------------------------Platform---------------------------------------------------------* From 53973d3505fdddb169e3373db987352da335691c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 29 Aug 2025 16:30:35 +1000 Subject: [PATCH 052/115] Add missing UWP port files --- .gitignore | 7 +- misc/UWP/ClassiCube-UWP.sln | 51 +++ misc/UWP/ClassiCube-UWP.vcxproj | 432 +++++++++++++++++++++++ misc/UWP/ClassiCube-UWP.vcxproj.filters | 445 ++++++++++++++++++++++++ src/Core.h | 1 + {misc => src}/UWP/Platform_UWP.cpp | 103 +++--- {misc => src}/UWP/Window_UWP.cpp | 8 +- 7 files changed, 990 insertions(+), 57 deletions(-) create mode 100644 misc/UWP/ClassiCube-UWP.sln create mode 100644 misc/UWP/ClassiCube-UWP.vcxproj create mode 100644 misc/UWP/ClassiCube-UWP.vcxproj.filters rename {misc => src}/UWP/Platform_UWP.cpp (91%) rename {misc => src}/UWP/Window_UWP.cpp (94%) diff --git a/.gitignore b/.gitignore index 7e03f9bf7..66f30214f 100644 --- a/.gitignore +++ b/.gitignore @@ -111,9 +111,14 @@ OPTIONS.TXT # Android source files need to be included !android/app/src/main/java/com/classicube -# Flatpak wrapper which needs to be included +# Flatpak wrapper needs to be included !misc/flatpak/ClassiCubeLauncher +# UWP files needs to be included +!misc/UWP/ClassiCube-UWP.sln +!misc/UWP/ClassiCube-UWP.vcxproj +!misc/UWP/ClassiCube-UWP.vcxproj.filters + # CMake files CMakeFiles/ CMakeCache.txt diff --git a/misc/UWP/ClassiCube-UWP.sln b/misc/UWP/ClassiCube-UWP.sln new file mode 100644 index 000000000..080a57bff --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32002.261 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassiCube-UWP", "ClassiCube-UWP.vcxproj", "{A901236D-C8EF-4041-966F-46F17511E342}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.ActiveCfg = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.Build.0 = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM.Deploy.0 = Debug|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.Build.0 = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.ActiveCfg = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.Build.0 = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x64.Deploy.0 = Debug|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.ActiveCfg = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.Build.0 = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Debug|x86.Deploy.0 = Debug|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.ActiveCfg = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.Build.0 = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM.Deploy.0 = Release|ARM + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.ActiveCfg = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.Build.0 = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|ARM64.Deploy.0 = Release|ARM64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.ActiveCfg = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.Build.0 = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x64.Deploy.0 = Release|x64 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.ActiveCfg = Release|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.Build.0 = Release|Win32 + {A901236D-C8EF-4041-966F-46F17511E342}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AB4A9C28-F91F-439E-8D2E-E54273138ADC} + EndGlobalSection +EndGlobal diff --git a/misc/UWP/ClassiCube-UWP.vcxproj b/misc/UWP/ClassiCube-UWP.vcxproj new file mode 100644 index 000000000..eee893422 --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.vcxproj @@ -0,0 +1,432 @@ + + + + {a901236d-c8ef-4041-966f-46f17511e342} + ClassiCube_UWP + en-US + 14.0 + true + Windows Store + 10.0.20348.0 + 10.0.10240.0 + 10.0 + false + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + Application + false + true + v142 + true + + + + + + + + + + + + + + + + + + + + + + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + /bigobj %(AdditionalOptions) + 4453;28204 + NotUsing + stdcpp17 + Default + false + + + %(AdditionalDependencies) + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + + + + \ No newline at end of file diff --git a/misc/UWP/ClassiCube-UWP.vcxproj.filters b/misc/UWP/ClassiCube-UWP.vcxproj.filters new file mode 100644 index 000000000..5656b770d --- /dev/null +++ b/misc/UWP/ClassiCube-UWP.vcxproj.filters @@ -0,0 +1,445 @@ + + + + + a901236d-c8ef-4041-966f-46f17511e342 + + + {93fa4266-80e4-4bbf-a7fa-c47e07da5098} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + BearSSL + + + + + + + \ No newline at end of file diff --git a/src/Core.h b/src/Core.h index 8922a03a1..34f2b7db0 100644 --- a/src/Core.h +++ b/src/Core.h @@ -211,6 +211,7 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_D3D11 #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_OPENAL + #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #elif defined _WIN32 && !defined __WINSCW__ #define CC_BUILD_WIN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN diff --git a/misc/UWP/Platform_UWP.cpp b/src/UWP/Platform_UWP.cpp similarity index 91% rename from misc/UWP/Platform_UWP.cpp rename to src/UWP/Platform_UWP.cpp index c42713b99..e109c3a58 100644 --- a/misc/UWP/Platform_UWP.cpp +++ b/src/UWP/Platform_UWP.cpp @@ -40,6 +40,25 @@ cc_bool Platform_ReadonlyFilesystem; cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; #define UWP_STRING(str) ((wchar_t*)(str)->uni) +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "../main_impl.h" + +// TODO integrate better with Window_UWP.cpp instead of hardcoding like this... +int main(int argc, char** argv) { + cc_result res; + SetupProgram(argc, argv); + + do { + res = RunProgram(argc, argv); + } while (Window_Main.Exists); + + Window_Free(); + Process_Exit(res); + return res; +} + /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ @@ -387,7 +406,37 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { /* Sanity check to ensure cc_sockaddr struct is large enough to contain all socket addresses supported by this platform */ static char sockaddr_size_check[sizeof(SOCKADDR_STORAGE) < CC_SOCKETADDR_MAXSIZE ? 1 : -1]; -static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { +static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst->data; + cc_uint32 ip_addr; + if (!ParseIPv4Address(ip, &ip_addr)) return false; + + addr4->sin_addr.S_un.S_addr = ip_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + + dst->size = sizeof(*addr4); + return true; +} + +static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)dst->data; + cc_winstring str; + INT size = sizeof(*addr6); + + cc_string address = String_FromReadonly(ip); + Platform_EncodeString(&str, &address); + + if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET6, NULL, (SOCKADDR*)addr6, &size)) { + addr6->sin6_port = htons(port); + + dst->size = size; + return true; + } + return false; +} + +static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { char portRaw[32]; cc_string portStr; struct addrinfo hints = { 0 }; struct addrinfo* result; @@ -423,36 +472,6 @@ static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* num return i == 0 ? ERR_INVALID_ARGUMENT : 0; } -cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { - SOCKADDR_IN* addr4 = (SOCKADDR_IN* )addrs[0].data; - SOCKADDR_IN6* addr6 = (SOCKADDR_IN6*)addrs[0].data; - cc_winstring str; - INT size; - - *numValidAddrs = 0; - Platform_EncodeString(&str, address); - - size = sizeof(*addr4); - if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET, NULL, (SOCKADDR*)addr4, &size)) { - addr4->sin_port = htons(port); - - addrs[0].size = size; - *numValidAddrs = 1; - return 0; - } - - size = sizeof(*addr6); - if (!WSAStringToAddressW(UWP_STRING(&str), AF_INET6, NULL, (SOCKADDR*)addr6, &size)) { - addr6->sin6_port = htons(port); - - addrs[0].size = size; - *numValidAddrs = 1; - return 0; - } - - return ParseHostNew(str.ansi, port, addrs, numValidAddrs); -} - cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { SOCKADDR* raw_addr = (SOCKADDR*)addr->data; @@ -599,29 +618,7 @@ cc_result Process_StartOpen(const cc_string* args) { #define UPDATE_SRC TEXT(UPDATE_FILE) cc_bool Updater_Supported = true; -#if defined _M_IX86 -const struct UpdaterInfo Updater_Info = { - "&eDirect3D 9 is recommended", 2, - { - { "Direct3D9", "ClassiCube.exe" }, - { "OpenGL", "ClassiCube.opengl.exe" } - } -}; -#elif defined _M_X64 -const struct UpdaterInfo Updater_Info = { - "&eDirect3D 9 is recommended", 2, - { - { "Direct3D9", "ClassiCube.64.exe" }, - { "OpenGL", "ClassiCube.64-opengl.exe" } - } -}; -#elif defined _M_ARM64 -const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm64-d3d11.exe" } } }; -#elif defined _M_ARM -const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm32-d3d11.exe" } } }; -#else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; -#endif cc_bool Updater_Clean(void) { return DeleteFile(UPDATE_TMP) || GetLastError() == ERROR_FILE_NOT_FOUND; diff --git a/misc/UWP/Window_UWP.cpp b/src/UWP/Window_UWP.cpp similarity index 94% rename from misc/UWP/Window_UWP.cpp rename to src/UWP/Window_UWP.cpp index 6fe90de4f..7b434ae62 100644 --- a/misc/UWP/Window_UWP.cpp +++ b/src/UWP/Window_UWP.cpp @@ -199,8 +199,11 @@ cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { static GfxResourceID fb_tex, fb_vb; static void AllocateVB(void) { - struct VertexTextured* data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&fb_vb, - VERTEX_FORMAT_TEXTURED, 4); + Gfx_DeleteVb(&fb_vb); + fb_vb = Gfx_CreateVb(VERTEX_FORMAT_TEXTURED, 4); + + struct VertexTextured* data = (struct VertexTextured*)Gfx_LockVb(fb_vb, VERTEX_FORMAT_TEXTURED, 4); + data[0].x = -1.0f; data[0].y = -1.0f; data[0].z = 0.0f; data[0].Col = PACKEDCOL_WHITE; data[0].U = 0.0f; data[0].V = 1.0f; data[1].x = 1.0f; data[1].y = -1.0f; data[1].z = 0.0f; data[1].Col = PACKEDCOL_WHITE; data[1].U = 1.0f; data[1].V = 1.0f; data[2].x = 1.0f; data[2].y = 1.0f; data[2].z = 0.0f; data[2].Col = PACKEDCOL_WHITE; data[2].U = 1.0f; data[2].V = 0.0f; @@ -285,7 +288,6 @@ void Window_DisableRawMouse(void) { struct CCApp : implements { - // IFrameworkViewSource interface IFrameworkView CreateView() { From d82646157368574dcf29e76eff7e9b7a9b0559ef Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 29 Aug 2025 19:51:13 +1000 Subject: [PATCH 053/115] PS4: Bring makefile up to date --- misc/ps4/Makefile | 117 +++++++++++++++++++++++------------ src/UWP/Platform_UWP.cpp | 52 +++------------- src/UWP/Window_UWP.cpp | 19 +++--- src/{ => ps4}/Platform_PS4.c | 71 +++++---------------- src/{ => ps4}/Window_PS4.c | 27 ++++---- 5 files changed, 123 insertions(+), 163 deletions(-) rename src/{ => ps4}/Platform_PS4.c (88%) rename src/{ => ps4}/Window_PS4.c (91%) diff --git a/misc/ps4/Makefile b/misc/ps4/Makefile index bf4983917..9ffbc51ad 100644 --- a/misc/ps4/Makefile +++ b/misc/ps4/Makefile @@ -1,53 +1,76 @@ -# Package metadata. -TITLE := OpenOrbis Hello World Sample +ifeq ($(strip $(OO_PS4_TOOLCHAIN)),) +$(error "Please set OO_PS4_TOOLCHAIN in your environment. export OO_PS4_TOOLCHAIN=") +endif +TOOLCHAIN := $(OO_PS4_TOOLCHAIN) + +.SUFFIXES: + +#--------------------------------------------------------------------------------- +# Configurable options +#--------------------------------------------------------------------------------- +BUILD_DIR = build/ps4 +SOURCE_DIRS = src src/ps4 third_party/bearssl + +TARGET = ClassiCube-PS4 +TITLE := ClassiCube VERSION := 1.00 TITLE_ID := BREW00083 CONTENT_ID := IV0000-BREW00083_00-HELLOWORLD000000 -# Libraries linked into the ELF. +#--------------------------------------------------------------------------------- +# Compilable files +#--------------------------------------------------------------------------------- +CPP_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.cpp)) +C_FILES = $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(CPP_FILES:%.cpp=%.o))) + +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(OBJS:%.o=%.d) + +#--------------------------------------------------------------------------------- +# Code generation +#-------------------------------------------------------------------------------- LIBS := -lc -lkernel -lc++ -lSceVideoOut -lSceNet -# Additional compile flags. -#EXTRAFLAGS := - -# Asset and module directories. -LIBMODULES := $(wildcard sce_module/*) - -# You likely won't need to touch anything below this point. - -# Root vars -TOOLCHAIN := $(OO_PS4_TOOLCHAIN) -PROJDIR := src -INTDIR := build-ps4 - -# Define objects to build -CFILES := $(wildcard $(PROJDIR)/*.c) -CPPFILES := $(wildcard $(PROJDIR)/*.cpp) -OBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.o, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.o, $(CPPFILES)) - -# Define final C/C++ flags CFLAGS := --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -c $(EXTRAFLAGS) -isysroot $(TOOLCHAIN) -isystem $(TOOLCHAIN)/include -isystem $(TOOLCHAIN)/include/orbis -DPLAT_PS4 CXXFLAGS := $(CFLAGS) -isystem $(TOOLCHAIN)/include/c++/v1 LDFLAGS := -m elf_x86_64 -pie --script $(TOOLCHAIN)/link.x --eh-frame-hdr -L$(TOOLCHAIN)/lib $(LIBS) $(TOOLCHAIN)/lib/crt1.o -# Create the intermediate directory incase it doesn't already exist. -_unused := $(shell mkdir -p $(INTDIR)) +#--------------------------------------------------------------------------------- +# Compiler tools +#--------------------------------------------------------------------------------- CC := clang CCX := clang++ LD := ld.lld CDIR := linux -all: $(CONTENT_ID).pkg +#--------------------------------------------------------------------------------- +# Main targets +#--------------------------------------------------------------------------------- +all: $(BUILD_DIR) $(CONTENT_ID).pkg + +clean: + rm -f $(CONTENT_ID).pkg pkg.gp4 pkg/sce_sys/param.sfo eboot.bin \ + $(BUILD_DIR)/$(PROJDIR).elf $(BUILD_DIR)/$(PROJDIR).oelf $(OBJS) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# Executable generation +#--------------------------------------------------------------------------------- $(CONTENT_ID).pkg: pkg.gp4 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core pkg_build $< . -pkg.gp4: eboot.bin - cd misc/ps4 - $(TOOLCHAIN)/bin/$(CDIR)/create-gp4 -out $@ --content-id=$(CONTENT_ID) --files "sce_sys/about/right.sprx sce_sys/param.sfo sce_sys/icon0.png" +pkg.gp4: eboot.bin $(BUILD_DIR)/sce_sys/param.sfo + $(TOOLCHAIN)/bin/$(CDIR)/create-gp4 -out $@ --content-id=$(CONTENT_ID) --files "eboot.bin sce_sys/about/right.sprx sce_sys/param.sfo sce_sys/icon0.png" -misc/ps4/sce_sys/param.sfo: Makefile +$(BUILD_DIR)/sce_sys/param.sfo: + mkdir -p $(BUILD_DIR)/sce_sys $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_new $@ $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_TYPE --type Integer --maxsize 4 --value 1 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_VER --type Utf8 --maxsize 8 --value '$(VERSION)' @@ -60,16 +83,32 @@ misc/ps4/sce_sys/param.sfo: Makefile $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ TITLE_ID --type Utf8 --maxsize 12 --value '$(TITLE_ID)' $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ VERSION --type Utf8 --maxsize 8 --value '$(VERSION)' -eboot.bin: $(INTDIR) $(OBJS) - $(LD) $(INTDIR)/*.o -o $(INTDIR)/$(PROJDIR).elf $(LDFLAGS) - $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --eboot "eboot.bin" --paid 0x3800000000000011 +$(BUILD_DIR)/$(TARGET).elf: $(OBJS) + $(LD) $(OBJS) -o $(BUILD_DIR)/$(TARGET).elf $(LDFLAGS) -$(INTDIR)/%.o: $(PROJDIR)/%.c - $(CC) $(CFLAGS) -o $@ $< +eboot.bin: $(BUILD_DIR)/$(TARGET).elf + $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(BUILD_DIR)/$(TARGET).elf -out=$(BUILD_DIR)/$(TARGET).oelf --eboot "eboot.bin" --paid 0x3800000000000011 -$(INTDIR)/%.o: $(PROJDIR)/%.cpp - $(CCX) $(CXXFLAGS) -o $@ $< -clean: - rm -f $(CONTENT_ID).pkg pkg.gp4 pkg/sce_sys/param.sfo eboot.bin \ - $(INTDIR)/$(PROJDIR).elf $(INTDIR)/$(PROJDIR).oelf $(OBJS) +#--------------------------------------------------------------------------------- +# Object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o: src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: src/%.cpp + $(CCX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: src/ps4/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: third_party/bearssl/%.c + $(CC) $(CFLAGS) -c $< -o $@ + + +#--------------------------------------------------------------------------------- +# Dependency tracking +#--------------------------------------------------------------------------------- +$(DEPFILES): + +include $(wildcard $(DEPFILES)) diff --git a/src/UWP/Platform_UWP.cpp b/src/UWP/Platform_UWP.cpp index e109c3a58..30760feb3 100644 --- a/src/UWP/Platform_UWP.cpp +++ b/src/UWP/Platform_UWP.cpp @@ -1,10 +1,9 @@ -#include "../../src/Core.h" -#include "../../src/_PlatformBase.h" -#include "../../src/Stream.h" -#include "../../src/SystemFonts.h" -#include "../../src/Funcs.h" -#include "../../src/Utils.h" -#include "../../src/Errors.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Utils.h" +#include "../Errors.h" #define WIN32_LEAN_AND_MEAN #define NOSERVICE @@ -14,6 +13,7 @@ #define UNICODE #define _UNICODE #endif + #include #include #include @@ -557,43 +557,7 @@ static cc_result Process_RawGetExePath(cc_winstring* path, int* len) { } cc_result Process_StartGame2(const cc_string* args, int numArgs) { - union STARTUPINFO_union { - STARTUPINFOW wide; - STARTUPINFOA ansi; - } si = { 0 }; // less compiler warnings this way - - cc_winstring path; - cc_string argv; char argvBuffer[NATIVE_STR_LEN]; - PROCESS_INFORMATION pi = { 0 }; - cc_winstring raw; - cc_result res; - int len, i; - - if (Platform_IsSingleProcess()) return SetGameArgs(args, numArgs); - - if ((res = Process_RawGetExePath(&path, &len))) return res; - si.wide.cb = sizeof(STARTUPINFOW); - - String_InitArray(argv, argvBuffer); - /* Game doesn't actually care about argv[0] */ - String_AppendConst(&argv, "cc"); - for (i = 0; i < numArgs; i++) - { - if (String_IndexOf(&args[i], ' ') >= 0) { - String_Format1(&argv, " \"%s\"", &args[i]); - } else { - String_Format1(&argv, " %s", &args[i]); - } - } - Platform_EncodeString(&raw, &argv); - - if (!CreateProcessW(UWP_STRING(&path), UWP_STRING(&raw), NULL, NULL, - false, 0, NULL, NULL, &si.wide, &pi)) return GetLastError(); - - /* Don't leak memory for process return code */ - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return 0; + return SetGameArgs(args, numArgs); } void Process_Exit(cc_result code) { ExitProcess(code); } diff --git a/src/UWP/Window_UWP.cpp b/src/UWP/Window_UWP.cpp index 7b434ae62..71d942edb 100644 --- a/src/UWP/Window_UWP.cpp +++ b/src/UWP/Window_UWP.cpp @@ -1,4 +1,11 @@ -#include "../../src/Core.h" +#include "../_WindowBase.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Options.h" +#include "../Errors.h" +#include "../Graphics.h" +#include "../Game.h" #include #include @@ -23,14 +30,6 @@ using namespace Windows::System; using namespace Windows::UI::Core; using namespace Windows::UI::Input; -#include "../../src/_WindowBase.h" -#include "../../src/String.h" -#include "../../src/Funcs.h" -#include "../../src/Bitmap.h" -#include "../../src/Options.h" -#include "../../src/Errors.h" -#include "../../src/Graphics.h" -#include "../../src/Game.h" #define UWP_STRING(str) ((wchar_t*)(str)->uni) @@ -326,4 +325,4 @@ int __stdcall wWinMain(void*, void*, wchar_t** argv, int argc) { auto app = make(); CoreApplication::Run(app); -} \ No newline at end of file +} diff --git a/src/Platform_PS4.c b/src/ps4/Platform_PS4.c similarity index 88% rename from src/Platform_PS4.c rename to src/ps4/Platform_PS4.c index 30aa77ab1..e34734db9 100644 --- a/src/Platform_PS4.c +++ b/src/ps4/Platform_PS4.c @@ -1,16 +1,17 @@ -#include "Core.h" -#if defined CC_BUILD_PS4 - #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "SystemFonts.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "PackedCol.h" +#define CC_NO_UPDATER +#define CC_NO_DYNLIB + +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../SystemFonts.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../PackedCol.h" + #include #include #include @@ -31,7 +32,7 @@ #include #include #include -#include "_PlatformConsole.h" +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const cc_result ReturnCode_FileNotFound = ENOENT; @@ -39,7 +40,6 @@ const cc_result ReturnCode_DirectoryExists = EEXIST; const cc_result ReturnCode_SocketInProgess = EINPROGRESS; const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; const cc_result ReturnCode_SocketDropped = EPIPE; -#define SUPPORTS_GETADDRINFO 1 const char* Platform_AppNameSuffix = " PS4"; cc_bool Platform_ReadonlyFilesystem; @@ -182,25 +182,15 @@ static cc_result File_Do(cc_file* file, const char* path, int mode) { } cc_result File_Open(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDONLY); -#else - return File_Do(file, path->buffer, O_RDONLY | O_BINARY); -#endif } + cc_result File_Create(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_TRUNC); -#else - return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_TRUNC | O_BINARY); -#endif } + cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { -#if !defined CC_BUILD_OS2 return File_Do(file, path->buffer, O_RDWR | O_CREAT); -#else - return File_Do(file, path->buffer, O_RDWR | O_CREAT | O_BINARY); -#endif } cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { @@ -377,12 +367,6 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { } -/*########################################################################################################################* -*--------------------------------------------------------Font/Text--------------------------------------------------------* -*#########################################################################################################################*/ -void Platform_LoadSysFonts(void) { } - - /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ @@ -492,27 +476,6 @@ void Socket_Close(cc_socket s) { close(s); } -#if defined CC_BUILD_DARWIN || defined CC_BUILD_BEOS -/* poll is broken on old OSX apparently https://daniel.haxx.se/docs/poll-vs-select.html */ -/* BeOS lacks support for poll */ -static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { - fd_set set; - struct timeval time = { 0 }; - int selectCount; - - FD_ZERO(&set); - FD_SET(s, &set); - - if (mode == SOCKET_POLL_READ) { - selectCount = select(s + 1, &set, NULL, NULL, &time); - } else { - selectCount = select(s + 1, NULL, &set, NULL, &time); - } - - if (selectCount == -1) { *success = false; return errno; } - *success = FD_ISSET(s, &set) != 0; return 0; -} -#else #include static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { struct pollfd pfd; @@ -527,7 +490,6 @@ static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { *success = (pfd.revents & flags) != 0; return 0; } -#endif cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { return Socket_Poll(s, SOCKET_POLL_READ, readable); @@ -589,4 +551,3 @@ static cc_result GetMachineID(cc_uint32* key) { cc_result Platform_GetEntropy(void* data, int len) { return ERR_NOT_SUPPORTED; } -#endif diff --git a/src/Window_PS4.c b/src/ps4/Window_PS4.c similarity index 91% rename from src/Window_PS4.c rename to src/ps4/Window_PS4.c index e11de6415..a19792b1b 100644 --- a/src/Window_PS4.c +++ b/src/ps4/Window_PS4.c @@ -1,17 +1,15 @@ -#include "Core.h" -#if defined CC_BUILD_PS4 -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "Graphics.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Logger.h" -#include "VirtualKeyboard.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Logger.h" +#include "../VirtualKeyboard.h" #include static cc_bool launcherMode; @@ -152,4 +150,3 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { return ERR_NOT_SUPPORTED; } -#endif From 8a8df0bfa429455831f9923ad1b613381b0b89dd Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 31 Aug 2025 07:50:26 +1000 Subject: [PATCH 054/115] Convert unicode to code page 437 for JSON output, partially addresses #1428 --- src/LWeb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LWeb.c b/src/LWeb.c index e5d600a3f..4101bf4f6 100644 --- a/src/LWeb.c +++ b/src/LWeb.c @@ -99,8 +99,7 @@ static void Json_ConsumeString(struct JsonContext* ctx, cc_string* str) { codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3]; /* don't want control characters in names/software */ - /* TODO: Convert to CP437.. */ - if (codepoint >= 32) String_Append(str, codepoint); + if (codepoint >= 32) String_Append(str, Convert_CodepointToCP437(codepoint)); JsonContext_Consume(ctx, 4); } From 5cd4d7854a0e990af6304eec0b7596929c7d7e9f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 1 Sep 2025 19:02:48 +1000 Subject: [PATCH 055/115] Make sapling physics more accurate (thanks Beyond5D) --- misc/3ds/Makefile | 2 +- misc/dreamcast/Makefile | 2 +- misc/gc/Makefile | 2 +- misc/n64/Makefile | 2 +- misc/psp/Makefile | 2 +- misc/switch/Makefile | 2 +- misc/vita/Makefile | 2 +- misc/wii/Makefile | 2 +- misc/wiiu/Makefile | 2 +- src/BlockPhysics.c | 15 +++++++++------ src/Core.h | 16 ++++++++-------- 11 files changed, 26 insertions(+), 23 deletions(-) diff --git a/misc/3ds/Makefile b/misc/3ds/Makefile index 717530b0f..9b3005e47 100644 --- a/misc/3ds/Makefile +++ b/misc/3ds/Makefile @@ -46,7 +46,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- ARCH = -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS = -g -Wall -O2 -mword-relocations -ffunction-sections $(ARCH) $(INCLUDE) -D__3DS__ +CFLAGS = -g -Wall -O2 -mword-relocations -ffunction-sections $(ARCH) $(INCLUDE) -D__3DS__ -DPLAT_3DS ASFLAGS = -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) diff --git a/misc/dreamcast/Makefile b/misc/dreamcast/Makefile index 93ec9566e..b2c135503 100644 --- a/misc/dreamcast/Makefile +++ b/misc/dreamcast/Makefile @@ -31,7 +31,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -DNDEBUG -O3 -fipa-pta -fno-pie -flto=auto -fomit-frame-pointer -fbuiltin -ffast-math -ffp-contract=fast -mfsrra -mfsca -pipe -fno-math-errno +CFLAGS = -g -DNDEBUG -O3 -fipa-pta -fno-pie -flto=auto -fomit-frame-pointer -fbuiltin -ffast-math -ffp-contract=fast -mfsrra -mfsca -pipe -fno-math-errno -DPLAT_DREAMCAST LDFLAGS = -g # Additional libraries to link against diff --git a/misc/gc/Makefile b/misc/gc/Makefile index 3d5179f72..f1d1d03bc 100644 --- a/misc/gc/Makefile +++ b/misc/gc/Makefile @@ -33,7 +33,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- MACHDEP = -DGEKKO -mogc -mcpu=750 -meabi -mhard-float -CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include +CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include -DPLAT_GCWII LDFLAGS = -g $(MACHDEP) -L$(DEVKITPRO)/libogc/lib/cube # Additional libraries to link against diff --git a/misc/n64/Makefile b/misc/n64/Makefile index 341bc1163..ee958fc66 100644 --- a/misc/n64/Makefile +++ b/misc/n64/Makefile @@ -9,7 +9,7 @@ SRC_DIRS = CFILES := $(notdir $(wildcard src/*.c)) OFILES := $(CFILES:.c=.o) rsp_gpu.o OBJS := $(addprefix $(BUILD_DIR)/,$(OFILES)) -CFLAGS := -Wno-error=missing-braces -Wno-error=strict-aliasing -Wno-error=incompatible-pointer-types +CFLAGS := -Wno-error=missing-braces -Wno-error=strict-aliasing -Wno-error=incompatible-pointer-types -DPLAT_N64 default: $(BUILD_DIR) $(TARGET).z64 diff --git a/misc/psp/Makefile b/misc/psp/Makefile index edd61fa5b..0295f3422 100644 --- a/misc/psp/Makefile +++ b/misc/psp/Makefile @@ -36,7 +36,7 @@ S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) -CFLAGS := -I$(PSPSDK)/include -g -O1 -fno-math-errno -D_PSP_FW_VERSION=600 +CFLAGS := -I$(PSPSDK)/include -g -O1 -fno-math-errno -D_PSP_FW_VERSION=600 -DPLAT_PSP ASFLAGS := -I$(PSPSDK)/include -g LDFLAGS := -L$(PSPSDK)/lib -specs=$(PSPSDK)/lib/prxspecs -Wl,-q,-T$(PSPSDK)/lib/linkfile.prx -Wl,-zmax-page-size=128 diff --git a/misc/switch/Makefile b/misc/switch/Makefile index 05fc33a4e..9845d025c 100644 --- a/misc/switch/Makefile +++ b/misc/switch/Makefile @@ -37,7 +37,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- ARCH = -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -CFLAGS = -g -Wall -O2 -ffunction-sections $(ARCH) -D__SWITCH__ +CFLAGS = -g -Wall -O2 -ffunction-sections $(ARCH) -D__SWITCH__ -DPLAT_SWITCH ASFLAGS = -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) diff --git a/misc/vita/Makefile b/misc/vita/Makefile index afbcbfac1..aad057883 100644 --- a/misc/vita/Makefile +++ b/misc/vita/Makefile @@ -35,7 +35,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- -CFLAGS = -O1 +CFLAGS = -O1 -DPLAT_VITA LDFLAGS = -Wl,-q LIBS = -lm -lSceDisplay_stub -lSceCtrl_stub -lSceTouch_stub -lSceGxm_stub -lSceCommonDialog_stub -lSceAppUtil_stub diff --git a/misc/wii/Makefile b/misc/wii/Makefile index 79ba6a1d6..b7b585c9a 100644 --- a/misc/wii/Makefile +++ b/misc/wii/Makefile @@ -32,7 +32,7 @@ DEPFILES := $(OBJS:%.o=%.d) # Code generation #--------------------------------------------------------------------------------- MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float -CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include +CFLAGS = -g -O2 -Wall $(MACHDEP) -I$(DEVKITPRO)/libogc/include -DPLAT_GCWII LDFLAGS = -g $(MACHDEP) -L$(DEVKITPRO)/libogc/lib/wii # Additional libraries to link against diff --git a/misc/wiiu/Makefile b/misc/wiiu/Makefile index 9ec2f0cf9..5e1967036 100644 --- a/misc/wiiu/Makefile +++ b/misc/wiiu/Makefile @@ -50,7 +50,7 @@ DEPFILES := $(OBJS:%.o=%.d) MACHDEP = -DESPRESSO -mcpu=750 -meabi -mhard-float CFLAGS = -g -Wall -O2 -ffunction-sections -fno-math-errno $(MACHDEP) \ -I $(DEVKITPRO)/wut/include \ - -D__WIIU__ -D__WUT__ + -D__WIIU__ -D__WUT__ -DPLAT_WIIU LDFLAGS = -g $(MACHDEP) -specs=$(DEVKITPRO)/wut/share/wut.specs \ -L $(DEVKITPRO)/wut/lib diff --git a/src/BlockPhysics.c b/src/BlockPhysics.c index 626cde467..9cc206889 100644 --- a/src/BlockPhysics.c +++ b/src/BlockPhysics.c @@ -249,19 +249,22 @@ static void Physics_HandleSapling(int index, BlockID block) { below = BLOCK_AIR; if (y > 0) below = World.Blocks[index - World.OneY]; - if (below != BLOCK_GRASS) return; + /* Saplings stay alive on dirt */ + if (below == BLOCK_DIRT) return; + + /* Saplings grow if on grass in light, otherwise turn to air */ + Game_UpdateBlock(x, y, z, BLOCK_AIR); + if (below != BLOCK_GRASS || !Lighting.IsLit(x, y, z)) return; height = 5 + Random_Next(&physics_rnd, 3); - Game_UpdateBlock(x, y, z, BLOCK_AIR); - if (TreeGen_CanGrow(x, y, z, height)) { + if (TreeGen_CanGrow(x, y, z, height)) { count = TreeGen_Grow(x, y, z, height, coords, blocks); - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) + { Game_UpdateBlock(coords[i].x, coords[i].y, coords[i].z, blocks[i]); } - } else { - Game_UpdateBlock(x, y, z, BLOCK_SAPLING); } } diff --git a/src/Core.h b/src/Core.h index 34f2b7db0..4e5226f3f 100644 --- a/src/Core.h +++ b/src/Core.h @@ -441,7 +441,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_PLUGINS #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #define CC_DISABLE_LAUNCHER -#elif defined __psp__ +#elif defined PLAT_PSP #define CC_BUILD_PSP #define CC_BUILD_CONSOLE #define CC_BUILD_LOWMEM @@ -449,14 +449,14 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined __3DS__ +#elif defined PLAT_3DS #define CC_BUILD_3DS #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH #define CC_BUILD_DUALSCREEN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined GEKKO +#elif defined PLAT_GCWII #define CC_BUILD_GCWII #define CC_BUILD_CONSOLE #ifndef HW_RVL @@ -466,14 +466,14 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_SPLITSCREEN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined __vita__ +#elif defined PLAT_VITA #define CC_BUILD_PSVITA #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined _arch_dreamcast +#elif defined PLAT_DREAMCAST #define CC_BUILD_DREAMCAST #define CC_BUILD_CONSOLE #define CC_BUILD_LOWMEM @@ -489,7 +489,7 @@ typedef cc_uint8 cc_bool; #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined N64 +#elif defined PLAT_N64 #define CC_BIG_ENDIAN #define CC_BUILD_N64 #define CC_BUILD_CONSOLE @@ -553,7 +553,7 @@ typedef cc_uint8 cc_bool; #endif #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL -#elif defined __WIIU__ +#elif defined PLAT_WIIU #define CC_BUILD_WIIU #define CC_BUILD_CONSOLE #define CC_BUILD_COOPTHREADED @@ -561,7 +561,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_TOUCH #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined __SWITCH__ +#elif defined PLAT_SWITCH #define CC_BUILD_SWITCH #define CC_BUILD_CONSOLE #define CC_BUILD_TOUCH From f701f9a9cbc81d06a151a1c9e13ea4ded79acb3f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 2 Sep 2025 19:50:50 +1000 Subject: [PATCH 056/115] Xbox: Start tidying up NV2A code --- src/xbox/Graphics_Xbox.c | 98 +++++++++++++--------------------------- src/xbox/nv2a_gpu.h | 80 ++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 66 deletions(-) create mode 100644 src/xbox/nv2a_gpu.h diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index eed41320f..3454ee4c6 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -4,11 +4,12 @@ #include "../Window.h" #include +#define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) +#include "nv2a_gpu.h" #define _NV_ALPHAKILL_EN (1 << 2) #define MAX_RAM_ADDR 0x03FFAFFF -#define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) // https://github.com/XboxDev/nxdk/blob/master/samples/triangle/main.c // https://xboxdevwiki.net/NV2A/Vertex_Shader#Output_registers @@ -77,9 +78,6 @@ static void SetupShaders(void) { p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); - - // resets "z perspective" flag - //p = pb_push1(p, NV097_SET_CONTROL0, 0); pb_end(p); } @@ -97,12 +95,7 @@ static void ResetState(void) { p = pb_push1(p, NV097_SET_CULL_FACE, NV097_SET_CULL_FACE_V_FRONT); // the order ClassiCube specifies quad vertices in are in the wrong order // compared to what the GPU expects for front and back facing quads - - /*pb_push(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT, 16); p++; - for (int i = 0; i < 16; i++) - { - *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; - }*/ + pb_end(p); } @@ -335,14 +328,8 @@ void Gfx_SetDepthTest(cc_bool enabled) { static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - unsigned mask = 0; - if (r) mask |= NV097_SET_COLOR_MASK_RED_WRITE_ENABLE; - if (g) mask |= NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE; - if (b) mask |= NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; - if (a) mask |= NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; - uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_COLOR_MASK, mask); + p = NV2A_set_color_write_mask(p, r, g, b, a); pb_end(p); } @@ -478,17 +465,13 @@ void Gfx_SetFog(cc_bool enabled) { } void Gfx_SetFogCol(PackedCol color) { - int R = PackedCol_R(color); - int G = PackedCol_G(color); - int B = PackedCol_B(color); - int A = PackedCol_A(color); - uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_FOG_COLOR, - MASK(NV097_SET_FOG_COLOR_RED, R) | - MASK(NV097_SET_FOG_COLOR_GREEN, G) | - MASK(NV097_SET_FOG_COLOR_BLUE, B) | - MASK(NV097_SET_FOG_COLOR_ALPHA, A)); + + p = NV2A_set_fog_colour(p, + PackedCol_R(color), + PackedCol_G(color), + PackedCol_B(color), + PackedCol_A(color)); pb_end(p); } @@ -557,16 +540,16 @@ static struct Matrix _view, _proj, _mvp; static void UpdateVSConstants(void) { uint32_t* p; p = pb_begin(); - - // resets "z perspective" flag - p = pb_push1(p, NV097_SET_CONTROL0, 0); - // set shader constants cursor to C0 - p = pb_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96); + // TODO: Have to call this to avoid graphical artifacts. Figure out why + p = NV2A_reset_control0(p); + + p = NV2A_set_constant_upload_offset(p, 0); // upload transformation matrix - pb_push(p++, NV097_SET_TRANSFORM_CONSTANT, 4*4); + p = NV2A_start_constants_upload(p, 16); Mem_Copy(p, &_mvp, 16 * 4); p += 16; + // Upload constants too //struct Vec4 v = { 1, 1, 1, 1 }; //Mem_Copy(p, &v, 4 * 4); p += 4; @@ -613,10 +596,8 @@ void Gfx_SetViewport(int x, int y, int w, int h) { } void Gfx_SetScissor(int x, int y, int w, int h) { - uint32_t* p; - p = pb_begin(); - // NV097_SET_SURFACE_CLIP_HORIZONTAL followed by NV097_SET_SURFACE_CLIP_VERTICAL - p = pb_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, x | (w << 16), y | (h << 16)); + uint32_t* p = pb_begin(); + p = NV2A_set_clip_rect(p, x, y, w, h); pb_end(p); } @@ -627,42 +608,27 @@ void Gfx_SetScissor(int x, int y, int w, int h) { cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -static uint32_t* PushAttrib(uint32_t* p, int index, int format, int size, int stride) { - return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride)); -} - void Gfx_SetVertexFormat(VertexFormat fmt) { if (fmt == gfx_format) return; gfx_format = fmt; gfx_stride = strideSizes[fmt]; uint32_t* p = pb_begin(); - // Clear all attributes TODO optimise - pb_push(p++, NV097_SET_VERTEX_DATA_ARRAY_FORMAT,16); - for (int i = 0; i < 16; i++) - { - *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; - } - - // resets "z perspective" flag - //p = pb_push1(p, NV097_SET_CONTROL0, 0); + // TODO not always call this. But trying to just clear TEXTURE_ATTR_INDEX breaks on XEMU + p = NV2A_reset_all_vertex_attribs(p); - // TODO cache these.. if (fmt == VERTEX_FORMAT_TEXTURED) { - p = PushAttrib(p, VERTEX_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 3, SIZEOF_VERTEX_TEXTURED); - p = PushAttrib(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, - 4, SIZEOF_VERTEX_TEXTURED); - p = PushAttrib(p, TEXTURE_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 2, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, VERTEX_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 3, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_TEXTURED); + p = NV2A_set_vertex_attrib_format(p, TEXTURE_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 2, SIZEOF_VERTEX_TEXTURED); } else { - p = PushAttrib(p, VERTEX_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, - 3, SIZEOF_VERTEX_COLOURED); - p = PushAttrib(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, - 4, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, VERTEX_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 3, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_COLOURED); } pb_end(p); @@ -683,8 +649,8 @@ static void DrawArrays(int mode, int start, int count) { while (count > 0) { int batch_count = min(count, 256); - - p = pb_push1(p, 0x40000000 | NV097_DRAW_ARRAYS, + + p = pb_push1(p, NV2A_WRITE_SAME_REGISTER | NV097_DRAW_ARRAYS, MASK(NV097_DRAW_ARRAYS_COUNT, (batch_count-1)) | MASK(NV097_DRAW_ARRAYS_START_INDEX, start)); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h new file mode 100644 index 000000000..b22496cd9 --- /dev/null +++ b/src/xbox/nv2a_gpu.h @@ -0,0 +1,80 @@ +// disables the default increment behaviour when writing multiple registers +// E.g. with pb_push4(p, REG, v1, v2, v3, v4): +// - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 +// - disable: REG = v1, REG = v2, REG = v3, REG = v4 +#define NV2A_WRITE_SAME_REGISTER 0x40000000 + +static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { + // resets "z perspective" flag + return pb_push1(p, NV097_SET_CONTROL0, 0); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Raster control------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_clip_rect(uint32_t* p, int x, int y, int w, int h) { + // NV097_SET_SURFACE_CLIP_HORIZONTAL, then NV097_SET_SURFACE_CLIP_VERTICAL + return pb_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, x | (w << 16), y | (h << 16)); +} + +static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, int b, int a) { + unsigned mask = 0; + if (r) mask |= NV097_SET_COLOR_MASK_RED_WRITE_ENABLE; + if (g) mask |= NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE; + if (b) mask |= NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; + if (a) mask |= NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; + + return pb_push1(p, NV097_SET_COLOR_MASK, mask); +} + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, int A) { + return 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)); +} + + +/*########################################################################################################################* +*--------------------------------------------------Vertex shader constants------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_constant_upload_offset(uint32_t* p, int offset) { + // set shader constants cursor to: C0 + offset + return pb_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96 + offset); +} + +static CC_INLINE uint32_t* NV2A_start_constants_upload(uint32_t* p, int num_dwords) { + pb_push(p++, NV097_SET_TRANSFORM_CONSTANT, num_dwords); + return p; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex attributes---------------------------------------------------* +*#########################################################################################################################*/ +// https://xboxdevwiki.net/NV2A/Vertex_Shader#Input_registers +// 16 input vertex attribute registers +#define NV2A_MAX_INPUT_ATTRIBS 16 + +static uint32_t* NV2A_reset_all_vertex_attribs(uint32_t* p) { + pb_push(p++, NV097_SET_VERTEX_DATA_ARRAY_FORMAT, NV2A_MAX_INPUT_ATTRIBS); + + for (int i = 0; i < NV2A_MAX_INPUT_ATTRIBS; i++) + { + *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; + } + return p; +} + +static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int format, int size, int stride) { + return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride)); +} From f5541e751875654bc27e1cec6aa3116e7b52d777 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 2 Sep 2025 20:51:26 +1000 Subject: [PATCH 057/115] Xbox: Simplify clearing slightly --- src/xbox/Graphics_Xbox.c | 28 ++++++++++++++-------------- src/xbox/nv2a_gpu.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 3454ee4c6..0f687085a 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -96,6 +96,10 @@ static void ResetState(void) { // the order ClassiCube specifies quad vertices in are in the wrong order // compared to what the GPU expects for front and back facing quads + int width = pb_back_buffer_width(); + int height = pb_back_buffer_height(); + p = NV2A_set_clear_rect(p, 0, 0, width, height); + pb_end(p); } @@ -281,10 +285,10 @@ void Gfx_BindTexture(GfxResourceID texId) { /*########################################################################################################################* *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ -static PackedCol clearColor; - void Gfx_ClearColor(PackedCol color) { - clearColor = color; + uint32_t* p = pb_begin(); + p = NV2A_set_clear_colour(p, color); + pb_end(p); } void Gfx_SetFaceCulling(cc_bool enabled) { @@ -360,17 +364,16 @@ void Gfx_BeginFrame(void) { pb_wait_for_vbl(); pb_reset(); pb_target_back_buffer(); + + uint32_t* p = pb_begin(); + p = NV2A_reset_control0(p); + pb_end(p); } void Gfx_ClearBuffers(GfxBuffers buffers) { - int width = pb_back_buffer_width(); - int height = pb_back_buffer_height(); - - // TODO do ourselves - if (buffers & GFX_BUFFER_DEPTH) - pb_erase_depth_stencil_buffer(0, 0, width, height); - if (buffers & GFX_BUFFER_COLOR) - pb_fill(0, 0, width, height, clearColor); + uint32_t* p = pb_begin(); + p = NV2A_start_clear(p, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); + pb_end(p); //pb_erase_text_screen(); while (pb_busy()) { } // Wait for completion TODO: necessary?? @@ -540,9 +543,6 @@ static struct Matrix _view, _proj, _mvp; static void UpdateVSConstants(void) { uint32_t* p; p = pb_begin(); - - // TODO: Have to call this to avoid graphical artifacts. Figure out why - p = NV2A_reset_control0(p); p = NV2A_set_constant_upload_offset(p, 0); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index b22496cd9..a881faddc 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -78,3 +78,31 @@ static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int forma MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride)); } + + +/*########################################################################################################################* +*------------------------------------------------------Buffer clearing----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_clear_rect(uint32_t* p, int x, int y, int w, int h) { + // Sets NV097_SET_CLEAR_RECT_HORIZONTAL then NV097_SET_CLEAR_RECT_VERTICAL + return pb_push2(p, NV097_SET_CLEAR_RECT_HORIZONTAL, + ((x + w - 1) << 16) | x, + ((y + h - 1) << 16) | y); +} + +static CC_INLINE uint32_t* NV2A_set_clear_colour(uint32_t* p, uint32_t colour) { + // Sets NV097_SET_ZSTENCIL_CLEAR_VALUE then NV097_SET_COLOR_CLEAR_VALUE + return pb_push2(p, NV097_SET_ZSTENCIL_CLEAR_VALUE, + 0xFFFFFF00, // (depth << 8) | stencil + colour); +} + +static CC_INLINE uint32_t* NV2A_start_clear(uint32_t* p, int color, int depth) { + uint32_t mask = 0; + if (color) mask |= NV097_CLEAR_SURFACE_COLOR; + if (depth) mask |= NV097_CLEAR_SURFACE_Z; + if (depth) mask |= NV097_CLEAR_SURFACE_STENCIL; + + return pb_push1(p, NV097_CLEAR_SURFACE, mask); +} + From 04df26a5748676b457944be86edfb052486f706e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 2 Sep 2025 21:15:52 +1000 Subject: [PATCH 058/115] Xbox: Avoid uploading shader repeatedly, just change run address --- src/xbox/Graphics_Xbox.c | 74 +++++++++++++++++----------------------- src/xbox/nv2a_gpu.h | 25 +++++++++++++- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 0f687085a..2e02156e7 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -20,23 +20,16 @@ // A lot of figuring out which GPU registers to use came from: // - comparing against pbgl and pbkit -static void LoadVertexShader(uint32_t* program, int programSize) { - uint32_t* p; - - // Set cursor for program upload - p = pb_begin(); - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, 0); - pb_end(p); +// Room for 136 vertex shader instructions +// Only need 3, so give 40 instructions to each +#define VS_COLOURED_OFFSET 0 +#define VS_TEXTURED_OFFSET 40 - // Copy program instructions (16 bytes each) - for (int i = 0; i < programSize / 16; i++) - { - p = pb_begin(); - pb_push(p++, NV097_SET_TRANSFORM_PROGRAM, 4); - Mem_Copy(p, &program[i * 4], 4 * 4); - p += 4; - pb_end(p); - } +static void LoadVertexShader(int offset, uint32_t* program, int programSize) { + uint32_t* p = pb_begin(); + p = NV2A_set_program_upload_offset(p, offset); + p = NV2A_upload_program(p, program, programSize); + pb_end(p); } static uint32_t vs_coloured_program[] = { @@ -68,8 +61,7 @@ static void SetupShaders(void) { uint32_t *p; p = pb_begin(); - // Set run address of shader - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, 0); + p = NV2A_set_program_run_offset(p, 0); // Set execution mode p = pb_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, @@ -117,6 +109,9 @@ void Gfx_Create(void) { Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); ResetState(); Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; + + LoadVertexShader(VS_COLOURED_OFFSET, vs_textured_program, sizeof(vs_textured_program)); + LoadVertexShader(VS_TEXTURED_OFFSET, vs_coloured_program, sizeof(vs_coloured_program)); // 1x1 dummy white texture struct Bitmap bmp; @@ -539,31 +534,15 @@ void Gfx_OnWindowResize(void) { } static struct Vec4 vp_scale = { 320, -240, 8388608, 1 }; static struct Vec4 vp_offset = { 320, 240, 8388608, 1 }; static struct Matrix _view, _proj, _mvp; - -static void UpdateVSConstants(void) { - uint32_t* p; - p = pb_begin(); - - p = NV2A_set_constant_upload_offset(p, 0); - - // upload transformation matrix - p = NV2A_start_constants_upload(p, 16); - Mem_Copy(p, &_mvp, 16 * 4); p += 16; - - // Upload constants too - //struct Vec4 v = { 1, 1, 1, 1 }; - //Mem_Copy(p, &v, 4 * 4); p += 4; - // if necessary, look at vs.inl output for 'c[5]' etc.. - - pb_end(p); -} +// TODO Upload constants too +// if necessary, look at vs.inl output for 'c[5]' etc.. void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { struct Matrix* dst = type == MATRIX_PROJ ? &_proj : &_view; *dst = *matrix; - Matrix_Mul(&_mvp, &_view, &_proj); + struct Matrix final; struct Matrix vp = Matrix_Identity; vp.row1.x = vp_scale.x; vp.row2.y = vp_scale.y; @@ -572,14 +551,19 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { vp.row4.y = vp_offset.y; vp.row4.z = 8388608; - Matrix_Mul(&_mvp, &_mvp, &vp); - UpdateVSConstants(); + Matrix_Mul(&final, &_mvp, &vp); + + uint32_t* p; + p = pb_begin(); + p = NV2A_set_constant_upload_offset(p, 0); + p = NV2A_upload_constants(p, &final, 16); + pb_end(p); } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { Gfx_LoadMatrix(MATRIX_VIEW, view); Gfx_LoadMatrix(MATRIX_PROJ, proj); - Matrix_Mul(mvp, view, proj); + Mem_Copy(mvp, &_mvp, sizeof(struct Matrix)); } void Gfx_EnableTextureOffset(float x, float y) { @@ -630,13 +614,17 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_COLOURED); } + + if (fmt == VERTEX_FORMAT_TEXTURED) { + p = NV2A_set_program_run_offset(p, VS_COLOURED_OFFSET); + } else { + p = NV2A_set_program_run_offset(p, VS_TEXTURED_OFFSET); + } pb_end(p); if (fmt == VERTEX_FORMAT_TEXTURED) { - LoadVertexShader(vs_textured_program, sizeof(vs_textured_program)); LoadFragmentShader_Textured(); - } else { - LoadVertexShader(vs_coloured_program, sizeof(vs_coloured_program)); + } else { LoadFragmentShader_Coloured(); } } diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index a881faddc..e60f5e54a 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -49,12 +49,35 @@ static CC_INLINE uint32_t* NV2A_set_constant_upload_offset(uint32_t* p, int offs return pb_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96 + offset); } -static CC_INLINE uint32_t* NV2A_start_constants_upload(uint32_t* p, int num_dwords) { +static CC_INLINE uint32_t* NV2A_upload_constants(uint32_t* p, void* src, int num_dwords) { pb_push(p++, NV097_SET_TRANSFORM_CONSTANT, num_dwords); + Mem_Copy(p, src, num_dwords * 4); p += num_dwords; return p; } +/*########################################################################################################################* +*---------------------------------------------------Vertex shader programs-------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* NV2A_set_program_upload_offset(uint32_t* p, int offset) { + return pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, offset); +} + +static CC_INLINE uint32_t* NV2A_upload_program(uint32_t* p, uint32_t* program, int size) { + // Copy program instructions (16 bytes each) + for (int i = 0; i < size / 16; i++, program += 4) + { + pb_push(p++, NV097_SET_TRANSFORM_PROGRAM, 4); + Mem_Copy(p, program, 16); p += 4; + } + return p; +} + +static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) { + return pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, offset); +} + + /*########################################################################################################################* *-----------------------------------------------------Vertex attributes---------------------------------------------------* *#########################################################################################################################*/ From 26dc506d53dfed949d0852027128dd6ef7a4b6be Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 2 Sep 2025 21:28:36 +1000 Subject: [PATCH 059/115] Xbox: Clouds now move --- misc/xbox/Makefile | 2 +- misc/xbox/vs_coloured.vs.cg | 8 ++++---- misc/xbox/vs_offset.inl | 27 +++++++++++++++++++++++++ misc/xbox/vs_offset.vs.cg | 30 ++++++++++++++++++++++++++++ misc/xbox/vs_textured.vs.cg | 10 +++++----- src/xbox/Graphics_Xbox.c | 39 ++++++++++++++++++++++++++++++------- 6 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 misc/xbox/vs_offset.inl create mode 100644 misc/xbox/vs_offset.vs.cg diff --git a/misc/xbox/Makefile b/misc/xbox/Makefile index 3c696494b..3f006f719 100644 --- a/misc/xbox/Makefile +++ b/misc/xbox/Makefile @@ -15,7 +15,7 @@ XBE_TITLE = ClassiCube # List of directories containing source code SOURCE_DIRS = src src/xbox third_party/bearssl # Shader objects -SHADER_OBJS = misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl misc/xbox/ps_coloured.inl misc/xbox/ps_textured.inl +SHADER_OBJS = misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl misc/xbox/vs_offset.inl misc/xbox/ps_coloured.inl misc/xbox/ps_textured.inl # Directory where object files are placed BUILD_DIR = build/xbox diff --git a/misc/xbox/vs_coloured.vs.cg b/misc/xbox/vs_coloured.vs.cg index 44394436a..f2ceeb356 100644 --- a/misc/xbox/vs_coloured.vs.cg +++ b/misc/xbox/vs_coloured.vs.cg @@ -1,6 +1,6 @@ struct vIn { - float4 color : DIFFUSE; - float4 position : POSITION; + float4 col : DIFFUSE; + float4 pos : POSITION; }; struct vOut { @@ -16,11 +16,11 @@ vOut main( vOut result; float4 position; - position = float4(input.position.xyz, 1.0f); + position = float4(input.pos.xyz, 1.0f); position = mul(position, mvp); position.xyz = position.xyz / position.w; result.pos = position; - result.col = input.color; + result.col = input.col; return result; } diff --git a/misc/xbox/vs_offset.inl b/misc/xbox/vs_offset.inl new file mode 100644 index 000000000..a2395317b --- /dev/null +++ b/misc/xbox/vs_offset.inl @@ -0,0 +1,27 @@ +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile vp20 +// source file: misc/xbox/vs_offset.vs.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile vp20 +//program main +//semantic main.mvp +//semantic main.tex_offset +//var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +//var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +//var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +//var float4x4 mvp : : c[0], 4 : 1 : 1 +//var float4 tex_offset : : c[4] : 2 : 1 +//var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +//var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +//var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +// 9 instructions, 0 R-regs +0x00000000, 0x004c2055, 0x0836186c, 0x2f0007f8, +0x00000000, 0x008c0000, 0x0836186c, 0x1f0007f8, +0x00000000, 0x008c40aa, 0x0836186c, 0x1f0007f8, +0x00000000, 0x006c601b, 0x0436106c, 0x3f0007f8, +0x00000000, 0x0400001b, 0x08361300, 0x101807f8, +0x00000000, 0x0040001b, 0x0400286c, 0x2070e800, +0x00000000, 0x0020001b, 0x0436106c, 0x20701800, +0x00000000, 0x0020061b, 0x0836106c, 0x2070f818, +0x00000000, 0x006c921b, 0x0836106c, 0x3070f849, diff --git a/misc/xbox/vs_offset.vs.cg b/misc/xbox/vs_offset.vs.cg new file mode 100644 index 000000000..5eca8588a --- /dev/null +++ b/misc/xbox/vs_offset.vs.cg @@ -0,0 +1,30 @@ +struct vIn { + float4 tex : TEXCOORD; + float4 col : DIFFUSE; + float4 pos : POSITION; +}; + +struct vOut { + float4 pos : POSITION; + float4 col : COLOR; + float4 tex : TEXCOORD0; +}; + +vOut main( + vIn input, + uniform float4x4 mvp, + uniform float4 tex_offset + ) +{ + vOut result; + float4 position; + + position = float4(input.pos.xyz, 1.0f); + position = mul(position, mvp); + position.xyz = position.xyz / position.w; + + result.pos = position; + result.col = input.col; + result.tex = input.tex + tex_offset; + return result; +} diff --git a/misc/xbox/vs_textured.vs.cg b/misc/xbox/vs_textured.vs.cg index a439d1c52..b4e3742d7 100644 --- a/misc/xbox/vs_textured.vs.cg +++ b/misc/xbox/vs_textured.vs.cg @@ -1,7 +1,7 @@ struct vIn { - float4 tex : TEXCOORD; - float4 color : DIFFUSE; - float4 position : POSITION; + float4 tex : TEXCOORD; + float4 col : DIFFUSE; + float4 pos : POSITION; }; struct vOut { @@ -18,12 +18,12 @@ vOut main( vOut result; float4 position; - position = float4(input.position.xyz, 1.0f); + position = float4(input.pos.xyz, 1.0f); position = mul(position, mvp); position.xyz = position.xyz / position.w; result.pos = position; - result.col = input.color; + result.col = input.col; result.tex = input.tex; return result; } diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 2e02156e7..46035fd70 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -24,6 +24,7 @@ // Only need 3, so give 40 instructions to each #define VS_COLOURED_OFFSET 0 #define VS_TEXTURED_OFFSET 40 +#define VS_OFFSET_OFFSET 80 static void LoadVertexShader(int offset, uint32_t* program, int programSize) { uint32_t* p = pb_begin(); @@ -38,6 +39,9 @@ static uint32_t vs_coloured_program[] = { static uint32_t vs_textured_program[] = { #include "../../misc/xbox/vs_textured.inl" }; +static uint32_t vs_offset_program[] = { + #include "../../misc/xbox/vs_offset.inl" +}; static void LoadFragmentShader_Coloured(void) { @@ -110,8 +114,9 @@ void Gfx_Create(void) { ResetState(); Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; - LoadVertexShader(VS_COLOURED_OFFSET, vs_textured_program, sizeof(vs_textured_program)); - LoadVertexShader(VS_TEXTURED_OFFSET, vs_coloured_program, sizeof(vs_coloured_program)); + LoadVertexShader(VS_COLOURED_OFFSET, vs_coloured_program, sizeof(vs_coloured_program)); + LoadVertexShader(VS_TEXTURED_OFFSET, vs_textured_program, sizeof(vs_textured_program)); + LoadVertexShader(VS_OFFSET_OFFSET, vs_offset_program, sizeof(vs_offset_program)); // 1x1 dummy white texture struct Bitmap bmp; @@ -566,10 +571,34 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma Mem_Copy(mvp, &_mvp, sizeof(struct Matrix)); } +static int tex_offset; + +static int CalcProgramOffset(void) { + if (tex_offset) + return VS_OFFSET_OFFSET; + if (gfx_format == VERTEX_FORMAT_TEXTURED) + return VS_TEXTURED_OFFSET; + + return VS_COLOURED_OFFSET; +} + void Gfx_EnableTextureOffset(float x, float y) { + struct Vec4 offset = { x, y, 0, 0 }; + uint32_t* p = pb_begin(); + tex_offset = true; + + p = NV2A_set_constant_upload_offset(p, 4); + p = NV2A_upload_constants(p, &offset, 4); + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); + pb_end(p); } void Gfx_DisableTextureOffset(void) { + uint32_t* p = pb_begin(); + tex_offset = false; + + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); + pb_end(p); } void Gfx_SetViewport(int x, int y, int w, int h) { @@ -615,11 +644,7 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_COLOURED); } - if (fmt == VERTEX_FORMAT_TEXTURED) { - p = NV2A_set_program_run_offset(p, VS_COLOURED_OFFSET); - } else { - p = NV2A_set_program_run_offset(p, VS_TEXTURED_OFFSET); - } + p = NV2A_set_program_run_offset(p, CalcProgramOffset()); pb_end(p); if (fmt == VERTEX_FORMAT_TEXTURED) { From e88058ed37fe22176182a1e6934a1e438cbdcff0 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 3 Sep 2025 18:49:12 +1000 Subject: [PATCH 060/115] Xbox: Prefer writing raw GPU commands directly --- src/xbox/Graphics_Xbox.c | 28 ++++++-------- src/xbox/nv2a_gpu.h | 82 +++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 46035fd70..0e36b30d3 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -97,6 +97,10 @@ static void ResetState(void) { p = NV2A_set_clear_rect(p, 0, 0, width, height); pb_end(p); + + p = pb_begin(); + p = NV2A_reset_all_vertex_attribs(p); + pb_end(p); } static GfxResourceID white_square; @@ -418,24 +422,14 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return AllocBuffer(count, strideSizes[fmt]); } -static uint32_t* PushAttribOffset(uint32_t* p, int index, cc_uint8* data) { - return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + index * 4, - (uint32_t)data & 0x03ffffff); -} - void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; uint32_t* p = pb_begin(); - - // TODO: Avoid the same code twice.. - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - p = PushAttribOffset(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); - p = PushAttribOffset(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); - p = PushAttribOffset(p, TEXTURE_ATTR_INDEX, gfx_vertices + 16); - } else { - p = PushAttribOffset(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); - p = PushAttribOffset(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); - } + + p = NV2A_set_vertex_attrib_pointer(p, VERTEX_ATTR_INDEX, gfx_vertices + 0); + p = NV2A_set_vertex_attrib_pointer(p, COLOUR_ATTR_INDEX, gfx_vertices + 12); + p = NV2A_set_vertex_attrib_pointer(p, TEXTURE_ATTR_INDEX, gfx_vertices + 16); + // Harmless to set TEXTURE_ATTR_INDEX, even when vertex format is coloured only pb_end(p); } @@ -627,8 +621,6 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_stride = strideSizes[fmt]; uint32_t* p = pb_begin(); - // TODO not always call this. But trying to just clear TEXTURE_ATTR_INDEX breaks on XEMU - p = NV2A_reset_all_vertex_attribs(p); if (fmt == VERTEX_FORMAT_TEXTURED) { p = NV2A_set_vertex_attrib_format(p, VERTEX_ATTR_INDEX, @@ -642,6 +634,8 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 3, SIZEOF_VERTEX_COLOURED); p = NV2A_set_vertex_attrib_format(p, COLOUR_ATTR_INDEX, NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D, 4, SIZEOF_VERTEX_COLOURED); + p = NV2A_set_vertex_attrib_format(p, TEXTURE_ATTR_INDEX, + NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F, 0, 0); } p = NV2A_set_program_run_offset(p, CalcProgramOffset()); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index e60f5e54a..70f6d8213 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -1,12 +1,32 @@ // disables the default increment behaviour when writing multiple registers -// E.g. with pb_push4(p, REG, v1, v2, v3, v4): +// E.g. with NV2A_3D_COMMAND(cmd, 4): // - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 // - disable: REG = v1, REG = v2, REG = v3, REG = v4 #define NV2A_WRITE_SAME_REGISTER 0x40000000 +#define NV2A_COMMAND(subchan, cmd, num_params) (((num_params) << 18) | ((subchan) << 13) | (cmd)) +#define NV2A_3D_COMMAND(cmd, num_params) NV2A_COMMAND(SUBCH_3D, cmd, num_params) + +static CC_INLINE uint32_t* NV2A_push1(uint32_t* p, int cmd, uint32_t value) { + *p++ = NV2A_3D_COMMAND(cmd, 1); + *p++ = value; + return p; +} + +static CC_INLINE uint32_t* NV2A_push2(uint32_t* p, int cmd, uint32_t val1, uint32_t val2) { + *p++ = NV2A_3D_COMMAND(cmd, 2); + *p++ = val1; + *p++ = val2; + return p; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Misc commands-------------------------------------------------------* +*#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { // resets "z perspective" flag - return pb_push1(p, NV097_SET_CONTROL0, 0); + return NV2A_push1(p, NV097_SET_CONTROL0, 0); } @@ -15,7 +35,8 @@ static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_clip_rect(uint32_t* p, int x, int y, int w, int h) { // NV097_SET_SURFACE_CLIP_HORIZONTAL, then NV097_SET_SURFACE_CLIP_VERTICAL - return pb_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, x | (w << 16), y | (h << 16)); + return NV2A_push2(p, NV097_SET_SURFACE_CLIP_HORIZONTAL, + x | (w << 16), y | (h << 16)); } static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, int b, int a) { @@ -25,7 +46,7 @@ static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, if (b) mask |= NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; if (a) mask |= NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; - return pb_push1(p, NV097_SET_COLOR_MASK, mask); + return NV2A_push1(p, NV097_SET_COLOR_MASK, mask); } @@ -33,11 +54,13 @@ static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, int A) { - return 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)); + uint32_t mask = + 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); + + return NV2A_push1(p, NV097_SET_FOG_COLOR, mask); } @@ -46,11 +69,11 @@ static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_constant_upload_offset(uint32_t* p, int offset) { // set shader constants cursor to: C0 + offset - return pb_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96 + offset); + return NV2A_push1(p, NV097_SET_TRANSFORM_CONSTANT_LOAD, 96 + offset); } static CC_INLINE uint32_t* NV2A_upload_constants(uint32_t* p, void* src, int num_dwords) { - pb_push(p++, NV097_SET_TRANSFORM_CONSTANT, num_dwords); + *p++ = NV2A_3D_COMMAND(NV097_SET_TRANSFORM_CONSTANT, num_dwords); Mem_Copy(p, src, num_dwords * 4); p += num_dwords; return p; } @@ -60,21 +83,21 @@ static CC_INLINE uint32_t* NV2A_upload_constants(uint32_t* p, void* src, int num *---------------------------------------------------Vertex shader programs-------------------------------------------------* *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_program_upload_offset(uint32_t* p, int offset) { - return pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, offset); + return NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_LOAD, offset); } static CC_INLINE uint32_t* NV2A_upload_program(uint32_t* p, uint32_t* program, int size) { // Copy program instructions (16 bytes each) for (int i = 0; i < size / 16; i++, program += 4) { - pb_push(p++, NV097_SET_TRANSFORM_PROGRAM, 4); + *p++ = NV2A_3D_COMMAND(NV097_SET_TRANSFORM_PROGRAM, 4); Mem_Copy(p, program, 16); p += 4; } return p; } static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) { - return pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, offset); + return NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, offset); } @@ -86,20 +109,27 @@ static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) #define NV2A_MAX_INPUT_ATTRIBS 16 static uint32_t* NV2A_reset_all_vertex_attribs(uint32_t* p) { - pb_push(p++, NV097_SET_VERTEX_DATA_ARRAY_FORMAT, NV2A_MAX_INPUT_ATTRIBS); + *p++ = NV2A_3D_COMMAND(NV097_SET_VERTEX_DATA_ARRAY_FORMAT, NV2A_MAX_INPUT_ATTRIBS); for (int i = 0; i < NV2A_MAX_INPUT_ATTRIBS; i++) { - *(p++) = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; + *p++ = NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F; } return p; } static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int format, int size, int stride) { - return pb_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride)); + uint32_t mask = + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | + MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride); + + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, mask); +} + +static uint32_t* NV2A_set_vertex_attrib_pointer(uint32_t* p, int index, cc_uint8* data) { + uint32_t offset = (uint32_t)data & 0x03ffffff; + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + index * 4, offset); } @@ -108,16 +138,16 @@ static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int forma *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_clear_rect(uint32_t* p, int x, int y, int w, int h) { // Sets NV097_SET_CLEAR_RECT_HORIZONTAL then NV097_SET_CLEAR_RECT_VERTICAL - return pb_push2(p, NV097_SET_CLEAR_RECT_HORIZONTAL, + return NV2A_push2(p, NV097_SET_CLEAR_RECT_HORIZONTAL, ((x + w - 1) << 16) | x, - ((y + h - 1) << 16) | y); + ((y + h - 1) << 16) | y); } static CC_INLINE uint32_t* NV2A_set_clear_colour(uint32_t* p, uint32_t colour) { // Sets NV097_SET_ZSTENCIL_CLEAR_VALUE then NV097_SET_COLOR_CLEAR_VALUE - return pb_push2(p, NV097_SET_ZSTENCIL_CLEAR_VALUE, - 0xFFFFFF00, // (depth << 8) | stencil - colour); + return NV2A_push2(p, NV097_SET_ZSTENCIL_CLEAR_VALUE, + 0xFFFFFF00, // (depth << 8) | stencil, + colour); } static CC_INLINE uint32_t* NV2A_start_clear(uint32_t* p, int color, int depth) { @@ -126,6 +156,6 @@ static CC_INLINE uint32_t* NV2A_start_clear(uint32_t* p, int color, int depth) { if (depth) mask |= NV097_CLEAR_SURFACE_Z; if (depth) mask |= NV097_CLEAR_SURFACE_STENCIL; - return pb_push1(p, NV097_CLEAR_SURFACE, mask); + return NV2A_push1(p, NV097_CLEAR_SURFACE, mask); } From 06da3877dbe0f8b9223782f5d9a5602f09d2e45f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 4 Sep 2025 07:09:11 +1000 Subject: [PATCH 061/115] Xbox: Fix going in-game with splitscreen, going back, then going in-game with singleplayer, leaving draw region messed up --- src/xbox/Graphics_Xbox.c | 86 +++++++++++------------------- src/xbox/nv2a_gpu.h | 110 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 57 deletions(-) diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 0e36b30d3..a66b496f3 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -7,7 +7,6 @@ #define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) #include "nv2a_gpu.h" -#define _NV_ALPHAKILL_EN (1 << 2) #define MAX_RAM_ADDR 0x03FFAFFF @@ -66,13 +65,7 @@ static void SetupShaders(void) { p = pb_begin(); p = NV2A_set_program_run_offset(p, 0); - - // Set execution mode - p = pb_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, - MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) - | MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); - - p = pb_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); + p = NV2A_set_execution_mode_shaders(p); pb_end(p); } @@ -80,15 +73,15 @@ static void SetupShaders(void) { static void ResetState(void) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_ALPHA_FUNC, 0x04); // GL_GREATER & 0x0F - p = pb_push1(p, NV097_SET_ALPHA_REF, 0x7F); - p = pb_push1(p, NV097_SET_DEPTH_FUNC, 0x03); // GL_LEQUAL & 0x0F + p = NV2A_set_alpha_test_func(p, 0x04); // GL_GREATER & 0x0F + p = NV2A_set_alpha_test_ref(p, 0x7F); + p = NV2A_set_depth_func(p, 0x03); // GL_LEQUAL & 0x0F - p = pb_push1(p, NV097_SET_BLEND_FUNC_SFACTOR, NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA); - p = pb_push1(p, NV097_SET_BLEND_FUNC_DFACTOR, NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA); - p = pb_push1(p, NV097_SET_BLEND_EQUATION, NV097_SET_BLEND_EQUATION_V_FUNC_ADD); // TODO not needed? + p = NV2A_set_alpha_blend_src(p, NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA); + p = NV2A_set_alpha_blend_dst(p, NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA); + p = NV2A_set_alpha_blend_eq( p, NV097_SET_BLEND_EQUATION_V_FUNC_ADD); // TODO not needed? - p = pb_push1(p, NV097_SET_CULL_FACE, NV097_SET_CULL_FACE_V_FRONT); + p = NV2A_set_cull_face_mode(p, NV097_SET_CULL_FACE_V_FRONT); // the order ClassiCube specifies quad vertices in are in the wrong order // compared to what the GPU expects for front and back facing quads @@ -100,6 +93,7 @@ static void ResetState(void) { p = pb_begin(); p = NV2A_reset_all_vertex_attribs(p); + p = NV2A_set_texture0_matrix(p, false); pb_end(p); } @@ -257,31 +251,11 @@ void Gfx_BindTexture(GfxResourceID texId) { uint32_t* p; p = pb_begin(); - // set texture stage 0 state - p = pb_push1(p, NV097_SET_TEXTURE_OFFSET, (DWORD)tex->pixels & 0x03ffffff); - p = pb_push1(p, NV097_SET_TEXTURE_FORMAT, - MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | - MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | - MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | - MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V - MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 - p = pb_push1(p, NV097_SET_TEXTURE_CONTROL0, - NV097_SET_TEXTURE_CONTROL0_ENABLE | - (gfx_alphaTest ? _NV_ALPHAKILL_EN : 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); - p = pb_push1(p, NV097_SET_TEXTURE_ADDRESS, - 0x00010101); // modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) - p = pb_push1(p, NV097_SET_TEXTURE_FILTER, - 0x2000 | - MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | - MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter - - // set texture matrix state - p = pb_push1(p, NV097_SET_TEXTURE_MATRIX_ENABLE, 0); + p = NV2A_set_texture0_pointer(p, tex->pixels); + p = NV2A_set_texture0_format(p, tex->log2_w, tex->log2_h); + p = NV2A_set_texture0_control0(p, gfx_alphaTest); + p = NV2A_set_texture0_wrapmode(p); + p = NV2A_set_texture0_filter(p); pb_end(p); } @@ -297,7 +271,7 @@ void Gfx_ClearColor(PackedCol color) { void Gfx_SetFaceCulling(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_CULL_FACE_ENABLE, enabled); + p = NV2A_set_cull_face(p, enabled); pb_end(p); } @@ -305,32 +279,26 @@ void Gfx_SetAlphaArgBlend(cc_bool enabled) { } static void SetAlphaBlend(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_BLEND_ENABLE, enabled); + p = NV2A_set_alpha_blend(p, enabled); pb_end(p); } static void SetAlphaTest(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); - - // TODO not duplicate with Gfx_BindTexture - p = pb_push1(p, NV097_SET_TEXTURE_CONTROL0, - NV097_SET_TEXTURE_CONTROL0_ENABLE | - (gfx_alphaTest ? _NV_ALPHAKILL_EN : 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); + p = NV2A_set_alpha_test(p, enabled); + p = NV2A_set_texture0_control0(p, gfx_alphaTest); pb_end(p); } void Gfx_SetDepthWrite(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_DEPTH_MASK, enabled); + p = NV2A_set_depth_write(p, enabled); pb_end(p); } void Gfx_SetDepthTest(cc_bool enabled) { uint32_t* p = pb_begin(); - p = pb_push1(p, NV097_SET_DEPTH_TEST_ENABLE, enabled); + p = NV2A_set_depth_test(p, enabled); pb_end(p); } @@ -528,10 +496,14 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f matrix->row4.w = 0.0f;*/ } -void Gfx_OnWindowResize(void) { } +void Gfx_OnWindowResize(void) { + Gfx_SetScissor( 0, 0, Game.Width, Game.Height); + Gfx_SetViewport(0, 0, Game.Width, Game.Height); +} -static struct Vec4 vp_scale = { 320, -240, 8388608, 1 }; -static struct Vec4 vp_offset = { 320, 240, 8388608, 1 }; +//static struct Vec4 vp_scale = { 320, -240, 8388608, 1 }; +//static struct Vec4 vp_offset = { 320, 240, 8388608, 1 }; +static struct Vec4 vp_scale, vp_offset; static struct Matrix _view, _proj, _mvp; // TODO Upload constants too // if necessary, look at vs.inl output for 'c[5]' etc.. @@ -545,10 +517,10 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { struct Matrix vp = Matrix_Identity; vp.row1.x = vp_scale.x; vp.row2.y = vp_scale.y; - vp.row3.z = 8388608; + vp.row3.z = 8388608; // 2^24 / 2 vp.row4.x = vp_offset.x; vp.row4.y = vp_offset.y; - vp.row4.z = 8388608; + vp.row4.z = 8388608; // 2^24 / 2 Matrix_Mul(&final, &_mvp, &vp); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index 70f6d8213..c148dd1de 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -7,6 +7,8 @@ #define NV2A_COMMAND(subchan, cmd, num_params) (((num_params) << 18) | ((subchan) << 13) | (cmd)) #define NV2A_3D_COMMAND(cmd, num_params) NV2A_COMMAND(SUBCH_3D, cmd, num_params) +#define _NV_ALPHAKILL_EN (1 << 2) + static CC_INLINE uint32_t* NV2A_push1(uint32_t* p, int cmd, uint32_t value) { *p++ = NV2A_3D_COMMAND(cmd, 1); *p++ = value; @@ -64,6 +66,58 @@ static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, } +static CC_INLINE uint32_t* NV2A_set_depth_write(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_DEPTH_MASK, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_depth_test(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_DEPTH_TEST_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_depth_func(uint32_t* p, int func) { + return NV2A_push1(p, NV097_SET_DEPTH_FUNC, func); +} + + +static CC_INLINE uint32_t* NV2A_set_alpha_test(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_test_func(uint32_t* p, int func) { + return NV2A_push1(p, NV097_SET_ALPHA_FUNC, func); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_test_ref(uint32_t* p, int ref) { + return NV2A_push1(p, NV097_SET_ALPHA_REF, ref); +} + + +static CC_INLINE uint32_t* NV2A_set_alpha_blend(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_BLEND_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_src(uint32_t* p, int factor) { + return NV2A_push1(p, NV097_SET_BLEND_FUNC_SFACTOR, factor); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_dst(uint32_t* p, int factor) { + return NV2A_push1(p, NV097_SET_BLEND_FUNC_DFACTOR, factor); +} + +static CC_INLINE uint32_t* NV2A_set_alpha_blend_eq(uint32_t* p, int equation) { + return NV2A_push1(p, NV097_SET_BLEND_EQUATION, equation); +} + + +static CC_INLINE uint32_t* NV2A_set_cull_face(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_CULL_FACE_ENABLE, enabled); +} + +static CC_INLINE uint32_t* NV2A_set_cull_face_mode(uint32_t* p, int mode) { + return NV2A_push1(p, NV097_SET_CULL_FACE, mode); +} + + /*########################################################################################################################* *--------------------------------------------------Vertex shader constants------------------------------------------------* *#########################################################################################################################*/ @@ -100,6 +154,15 @@ static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) return NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_START, offset); } +static CC_INLINE uint32_t* NV2A_set_execution_mode_shaders(uint32_t* p) { + p = NV2A_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, + MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) | + MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); + + p = NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); + return p; +} + /*########################################################################################################################* *-----------------------------------------------------Vertex attributes---------------------------------------------------* @@ -159,3 +222,50 @@ static CC_INLINE uint32_t* NV2A_start_clear(uint32_t* p, int color, int depth) { return NV2A_push1(p, NV097_CLEAR_SURFACE, mask); } + +/*########################################################################################################################* +*--------------------------------------------------------Texturing--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: API is hardcoded for one texture only, even though hardware supports multiple textures + +static CC_INLINE uint32_t* NV2A_set_texture0_control0(uint32_t* p, int texkill) { + return NV2A_push1(p, NV097_SET_TEXTURE_CONTROL0, + NV097_SET_TEXTURE_CONTROL0_ENABLE | + (texkill ? _NV_ALPHAKILL_EN : 0) | + MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | + MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); +} + +static uint32_t* NV2A_set_texture0_pointer(uint32_t* p, void* pixels) { + uint32_t offset = (uint32_t)pixels & 0x03ffffff; + return NV2A_push1(p, NV097_SET_TEXTURE_OFFSET, offset); +} + +static uint32_t* NV2A_set_texture0_format(uint32_t* p, unsigned log_u, unsigned log_v) { + return NV2A_push1(p, NV097_SET_TEXTURE_FORMAT, + MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | + MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | + MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | + MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V + MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | + MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | + MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | + MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 +} + +static uint32_t* NV2A_set_texture0_wrapmode(uint32_t* p) { + return NV2A_push1(p, NV097_SET_TEXTURE_ADDRESS, + 0x00010101); // modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) +} + +static uint32_t* NV2A_set_texture0_filter(uint32_t* p) { + return NV2A_push1(p, NV097_SET_TEXTURE_FILTER, + 0x2000 | + MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | + MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter +} + +static uint32_t* NV2A_set_texture0_matrix(uint32_t* p, int enabled) { + return NV2A_push1(p, NV097_SET_TEXTURE_MATRIX_ENABLE, enabled); +} + From df692aeaba1c7f0d21ecacf0b86748e9454b158f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 4 Sep 2025 07:54:05 +1000 Subject: [PATCH 062/115] Xbox: Use slightly more memory efficient way of performing draw calls --- src/xbox/Graphics_Xbox.c | 31 +++++-------------------------- src/xbox/nv2a_gpu.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index a66b496f3..f9bd2ab6a 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -620,44 +620,23 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { } } -static void DrawArrays(int mode, int start, int count) { - uint32_t *p = pb_begin(); - p = pb_push1(p, NV097_SET_BEGIN_END, mode); - - // NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so must be <= 256 - while (count > 0) - { - int batch_count = min(count, 256); - - p = pb_push1(p, NV2A_WRITE_SAME_REGISTER | NV097_DRAW_ARRAYS, - MASK(NV097_DRAW_ARRAYS_COUNT, (batch_count-1)) | - MASK(NV097_DRAW_ARRAYS_START_INDEX, start)); - - start += batch_count; - count -= batch_count; - } - - p = pb_push1(p, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END); - pb_end(p); -} - void Gfx_DrawVb_Lines(int verticesCount) { - DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount); } static void DrawIndexedVertices(int verticesCount, int startVertex) { - DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { - DrawIndexedVertices(verticesCount, startVertex); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } void Gfx_DrawVb_IndexedTris(int verticesCount) { - DrawIndexedVertices(verticesCount, 0); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, 0, verticesCount); } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - DrawIndexedVertices(verticesCount, startVertex); + NV2A_DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index c148dd1de..189725c64 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -118,6 +118,36 @@ static CC_INLINE uint32_t* NV2A_set_cull_face_mode(uint32_t* p, int mode) { } +/*########################################################################################################################* +*-----------------------------------------------------Primitive drawing---------------------------------------------------* +*#########################################################################################################################*/ +// NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so each draw call count must be <= 256 +#define DA_BATCH_SIZE 256 + +static void NV2A_DrawArrays(int mode, unsigned start, unsigned count) { + uint32_t *p = pb_begin(); + p = NV2A_push1(p, NV097_SET_BEGIN_END, mode); + + // Ceiling division by DA_BATCH_SIZE + unsigned num_batches = (count + DA_BATCH_SIZE - 1) / DA_BATCH_SIZE; + *p++ = NV2A_3D_COMMAND(NV2A_WRITE_SAME_REGISTER | NV097_DRAW_ARRAYS, num_batches); + + while (count > 0) + { + int batch_count = min(count, DA_BATCH_SIZE); + + *p++ = MASK(NV097_DRAW_ARRAYS_COUNT, batch_count-1) | + MASK(NV097_DRAW_ARRAYS_START_INDEX, start); + + start += batch_count; + count -= batch_count; + } + + p = NV2A_push1(p, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END); + pb_end(p); +} + + /*########################################################################################################################* *--------------------------------------------------Vertex shader constants------------------------------------------------* *#########################################################################################################################*/ From 8c4d2db9d18471f441b8a708d7fa59e09ccfaa51 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 6 Sep 2025 22:28:39 +1000 Subject: [PATCH 063/115] Alter dos makefile so that windows and dos executables can exist side by side --- .github/workflows/build_msdos.yml | 4 +-- .gitignore | 18 +----------- Makefile | 19 ++---------- misc/amiga/Makefile_68k | 2 +- misc/msdos/Makefile | 49 +++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 36 deletions(-) create mode 100644 misc/msdos/Makefile diff --git a/.github/workflows/build_msdos.yml b/.github/workflows/build_msdos.yml index a6a80e141..fec5377c6 100644 --- a/.github/workflows/build_msdos.yml +++ b/.github/workflows/build_msdos.yml @@ -27,7 +27,7 @@ jobs: - name: Compile MS dos build id: compile run: | - make CC=gcc dos RELEASE=1 + make CC=gcc dos - uses: ./.github/actions/notify_failure @@ -40,7 +40,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'ClassiCube.exe' + SOURCE_FILE: 'CCDOS.EXE' DEST_NAME: 'ClassiCube.exe' diff --git a/.gitignore b/.gitignore index 66f30214f..43116c055 100644 --- a/.gitignore +++ b/.gitignore @@ -26,23 +26,14 @@ project.xcworkspace/ xcuserdata/ # Nintendo Console build results -build-3ds/ build-nds/ build-dsi/ build-n64/ -build-gc/ -build-wii/ -build-wiiu/ -build-switch/ classicube.nds # SEGA console build results -build-32x/ -build-saturn/ -build-dc/ IP.BIN ISO_FILES/ -third_party/gldc/libGLdc.a cd/ # Microsoft console build results @@ -55,20 +46,12 @@ misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl # Sony console build results -build-ps2/ -build-ps3/ -build-ps4/ -build-psp/ -build-vita/ EBOOT.PBP PARAM.SFO param.sfo eboot.bin pkg.gp4 -# Desktop build results -build-amiga-68k/ - # Build results [Dd]ebug/ [Rr]elease/ @@ -107,6 +90,7 @@ fontscache.txt CWSDPMI.EXE CWSDPMI.SWP OPTIONS.TXT +CCDOS.EXE # Android source files need to be included !android/app/src/main/java/com/classicube diff --git a/Makefile b/Makefile index 49754220a..289f58b4d 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ LDFLAGS = -g -rdynamic ENAME = ClassiCube # Name of the final target file # (usually this is the executable, but e.g. is the app bundle on macOS) -TARGET := $(ENAME) +TARGET := $(ENAME) # Enables dependency tracking (https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/) # This ensures that changing a .h file automatically results in the .c files using it being auto recompiled when next running make @@ -172,19 +172,6 @@ ifeq ($(PLAT),riscos) BUILD_DIR = build/riscos endif -ifeq ($(PLAT),dos) - CC = i586-pc-msdosdjgpp-gcc - LIBS = - LDFLAGS = -g - OEXT = .exe - BUILD_DIR = build/dos - BEARSSL = 0 - - BUILD_DIRS += $(BUILD_DIR)/src/msdos - C_SOURCES += $(wildcard src/msdos/*.c) -endif - - ifdef BUILD_SDL2 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 LIBS += -lSDL2 @@ -242,8 +229,6 @@ irix: $(MAKE) $(TARGET) PLAT=irix riscos: $(MAKE) $(TARGET) PLAT=riscos -dos: - $(MAKE) $(TARGET) PLAT=dos # Default overrides sdl2: $(MAKE) $(TARGET) BUILD_SDL2=1 @@ -296,6 +281,8 @@ switch: $(MAKE) -f misc/switch/Makefile os/2: $(MAKE) -f misc/os2/Makefile +dos: + $(MAKE) -f misc/msdos/Makefile macclassic_68k: $(MAKE) -f misc/macclassic/Makefile_68k macclassic_ppc: diff --git a/misc/amiga/Makefile_68k b/misc/amiga/Makefile_68k index 498fff892..207b76f71 100644 --- a/misc/amiga/Makefile_68k +++ b/misc/amiga/Makefile_68k @@ -41,7 +41,7 @@ $(BUILD_DIR)/%.o : src/amiga/%.S $(BUILD_DIR)/%.o : src/%.c $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ -$(BUILD_DIR)/%.S : src/amiga/%.c +$(BUILD_DIR)/%.o : src/amiga/%.c $(CC) $(CFLAGS) $(DEPFLAGS) -S -c $< -o $@ # Dependency tracking diff --git a/misc/msdos/Makefile b/misc/msdos/Makefile new file mode 100644 index 000000000..d4f5fb978 --- /dev/null +++ b/misc/msdos/Makefile @@ -0,0 +1,49 @@ +CC=i586-pc-msdosdjgpp-gcc + +CFLAGS =-O1 -fno-math-errno -Werror -Wno-error=missing-braces -Wno-error=strict-aliasing +LDFLAGS=-g + +TARGET := CCDOS +BUILD_DIR := build/msdos +SOURCE_DIRS := src src/msdos + +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o))) + +# Dependency tracking +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d +DEPFILES := $(C_OBJECTS:%.o=%.d) + + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +default: $(BUILD_DIR) $(TARGET).EXE + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# executable generation +#--------------------------------------------------------------------------------- +$(TARGET).EXE: $(OBJS) + $(CC) $(OBJS) -o $@ $(LDFLAGS) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + + +#--------------------------------------------------------------------------------- +# object generation +#--------------------------------------------------------------------------------- +$(BUILD_DIR)/%.o : src/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o : src/msdos/%.c + $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ + +# Dependency tracking +$(DEPFILES): + +include $(wildcard $(DEPFILES)) From f68f7ffaf07ada52eeb85a20274fa047e6ef35d7 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 7 Sep 2025 12:15:57 +1000 Subject: [PATCH 064/115] PS3: WIP on writing GPU commands directly --- src/ps3/Graphics_PS3.c | 11 +++----- src/ps3/rsx_gpu.h | 58 ++++++++++++++++++++++++++++++++++++++++++ src/xbox/nv2a_gpu.h | 9 +++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 src/ps3/rsx_gpu.h diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index 174b3d100..20017a224 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -6,6 +6,7 @@ #include #include #include +#include "rsx_gpu.h" static gcmContextData* context; static u32 cur_fb; @@ -335,13 +336,7 @@ static void SetAlphaTest(cc_bool enabled) { } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - unsigned mask = 0; - if (r) mask |= GCM_COLOR_MASK_R; - if (g) mask |= GCM_COLOR_MASK_G; - if (b) mask |= GCM_COLOR_MASK_B; - if (a) mask |= GCM_COLOR_MASK_A; - - rsxSetColorMask(context, mask); + RSX_set_color_write_mask(context, r, g, b, a); } void Gfx_DepthOnlyRendering(cc_bool depthOnly) { @@ -487,7 +482,7 @@ void Gfx_SetViewport(int x, int y, int w, int h) { } void Gfx_SetScissor(int x, int y, int w, int h) { - rsxSetScissor(context, x, y, w, h); + RSX_set_scissor_rect(context, x, y, w, h); } diff --git a/src/ps3/rsx_gpu.h b/src/ps3/rsx_gpu.h new file mode 100644 index 000000000..eabad5ed5 --- /dev/null +++ b/src/ps3/rsx_gpu.h @@ -0,0 +1,58 @@ +/*########################################################################################################################* +*-----------------------------------------------------GPU commands--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: shared with nv2a (Xbox) GPU + +// disables the default increment behaviour when writing multiple registers +// E.g. with RSX_3D_COMMAND(cmd, 4): +// - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 +// - disable: REG = v1, REG = v2, REG = v3, REG = v4 +#define RSX_WRITE_SAME_REGISTER 0x40000000 + +#define RSX_COMMAND(subchan, cmd, num_params) (((num_params) << 18) | ((subchan) << 13) | (cmd)) +#define RSX_3D_COMMAND(cmd, num_params) RSX_COMMAND(0, cmd, num_params) + +#include + + +/*########################################################################################################################* +*---------------------------------------------------GPU command buffer----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE uint32_t* RSX_reserve(gcmContextData* ctx, int count) { + if (ctx->current + count > ctx->end) { + // TODO handle command buffer overflow properly + Process_Abort("Command buffer overflow"); + } + + uint32_t* p = ctx->current; + ctx->current += count; + return p; +} + +static CC_INLINE uint32_t* RSX_reserve_command(gcmContextData* context, uint32_t cmd, int num_params) { + uint32_t* p = RSX_reserve(context, num_params + 1); + *p++ = RSX_3D_COMMAND(cmd, num_params); + return p; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Raster control------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_set_scissor_rect(gcmContextData* ctx, int x, int y, int w, int h) { + // NV40TCL_SCISSOR_HORIZ, then NV40TCL_SCISSOR_VERTI + uint32_t* p = RSX_reserve_command(ctx, NV40TCL_SCISSOR_HORIZ, 2); + *p++ = x | (w << 16); + *p++ = y | (h << 16); +} + +static CC_INLINE void RSX_set_color_write_mask(gcmContextData* ctx, int r, int g, int b, int a) { + uint32_t mask = 0; + if (r) mask |= GCM_COLOR_MASK_R; + if (g) mask |= GCM_COLOR_MASK_G; + if (b) mask |= GCM_COLOR_MASK_B; + if (a) mask |= GCM_COLOR_MASK_A; + + uint32_t* p = RSX_reserve_command(ctx, NV40TCL_COLOR_MASK, 1); + *p++ = mask; +} diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index 189725c64..01bd42998 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -1,3 +1,8 @@ +/*########################################################################################################################* +*-----------------------------------------------------GPU commands--------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: shared with RSX (PS3) GPU + // disables the default increment behaviour when writing multiple registers // E.g. with NV2A_3D_COMMAND(cmd, 4): // - default: REG+0 = v1, REG+4 = v2, REG+8 = v3, REG+12= v4 @@ -9,6 +14,10 @@ #define _NV_ALPHAKILL_EN (1 << 2) + +/*########################################################################################################################* +*-----------------------------------------------------GPU pushbuffer------------------------------------------------------* +*#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_push1(uint32_t* p, int cmd, uint32_t value) { *p++ = NV2A_3D_COMMAND(cmd, 1); *p++ = value; From da0b7c8484c855e7fb026b303d075976f04e7fa0 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 7 Sep 2025 12:40:09 +1000 Subject: [PATCH 065/115] NDS: Fix compiling and use own folder --- Makefile | 2 +- misc/{ds => nds}/Makefile | 0 misc/{ds => nds}/Makefile.arm7 | 0 misc/{ds => nds}/Makefile.arm9 | 2 +- misc/{ds => nds}/icon.bmp | Bin misc/{ds => nds}/main_arm7.c | 0 src/{ => nds}/Graphics_NDS.c | 0 src/{ => nds}/Platform_NDS.c | 5 ----- src/{ => nds}/Window_NDS.c | 0 9 files changed, 2 insertions(+), 7 deletions(-) rename misc/{ds => nds}/Makefile (100%) rename misc/{ds => nds}/Makefile.arm7 (100%) rename misc/{ds => nds}/Makefile.arm9 (99%) rename misc/{ds => nds}/icon.bmp (100%) rename misc/{ds => nds}/main_arm7.c (100%) rename src/{ => nds}/Graphics_NDS.c (100%) rename src/{ => nds}/Platform_NDS.c (96%) rename src/{ => nds}/Window_NDS.c (100%) diff --git a/Makefile b/Makefile index 289f58b4d..d3bdfb065 100644 --- a/Makefile +++ b/Makefile @@ -268,7 +268,7 @@ n64: gba: $(MAKE) -f misc/gba/Makefile ds: - $(MAKE) -f misc/ds/Makefile + $(MAKE) -f misc/nds/Makefile 3ds: $(MAKE) -f misc/3ds/Makefile gamecube: diff --git a/misc/ds/Makefile b/misc/nds/Makefile similarity index 100% rename from misc/ds/Makefile rename to misc/nds/Makefile diff --git a/misc/ds/Makefile.arm7 b/misc/nds/Makefile.arm7 similarity index 100% rename from misc/ds/Makefile.arm7 rename to misc/nds/Makefile.arm7 diff --git a/misc/ds/Makefile.arm9 b/misc/nds/Makefile.arm9 similarity index 99% rename from misc/ds/Makefile.arm9 rename to misc/nds/Makefile.arm9 index 4a5dd7403..4fef37065 100644 --- a/misc/ds/Makefile.arm9 +++ b/misc/nds/Makefile.arm9 @@ -6,7 +6,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external export WONDERFUL_TOOLCHAIN ?= /opt/wonderful ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/ -SOURCEDIRS := src +SOURCEDIRS := src src/nds INCLUDEDIRS := DSIWIFI := third_party/dsiwifi diff --git a/misc/ds/icon.bmp b/misc/nds/icon.bmp similarity index 100% rename from misc/ds/icon.bmp rename to misc/nds/icon.bmp diff --git a/misc/ds/main_arm7.c b/misc/nds/main_arm7.c similarity index 100% rename from misc/ds/main_arm7.c rename to misc/nds/main_arm7.c diff --git a/src/Graphics_NDS.c b/src/nds/Graphics_NDS.c similarity index 100% rename from src/Graphics_NDS.c rename to src/nds/Graphics_NDS.c diff --git a/src/Platform_NDS.c b/src/nds/Platform_NDS.c similarity index 96% rename from src/Platform_NDS.c rename to src/nds/Platform_NDS.c index 24ccdadaf..cde2cb6b5 100644 --- a/src/Platform_NDS.c +++ b/src/nds/Platform_NDS.c @@ -546,13 +546,8 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { if (res || *writable) return res; /* https://stackoverflow.com/questions/29479953/so-error-value-after-successful-socket-operation */ -#ifdef BUILD_DSI socklen_t resultSize = sizeof(socklen_t); getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize); -#else - int resultSize = sizeof(int); - getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize); -#endif return res; } diff --git a/src/Window_NDS.c b/src/nds/Window_NDS.c similarity index 100% rename from src/Window_NDS.c rename to src/nds/Window_NDS.c From f4cf292899c9823e01640cc4bc73182537932255 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 7 Sep 2025 13:41:28 +1000 Subject: [PATCH 066/115] Disable processor specific enhancements when compiling BearSSL with win9x build --- third_party/bearssl/chacha20_sse2.c | 11 +++++++++-- third_party/bearssl/inner.h | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/third_party/bearssl/chacha20_sse2.c b/third_party/bearssl/chacha20_sse2.c index 2e16bdf31..32d4f0d11 100644 --- a/third_party/bearssl/chacha20_sse2.c +++ b/third_party/bearssl/chacha20_sse2.c @@ -40,13 +40,20 @@ br_chacha20_sse2_get(void) * If using 64-bit mode, then SSE2 opcodes should be automatically * available, since they are part of the ABI. * - * In 32-bit mode, not used due anymore to hitting an obscure possible compiler bug. + * In 32-bit mode, we use CPUID to detect the SSE2 feature. */ #if BR_amd64 return &br_chacha20_sse2_run; #else - return 0; + /* + * SSE2 support is indicated by bit 26 in EDX. + */ + if (br_cpuid(0, 0, 0, 0x04000000)) { + return &br_chacha20_sse2_run; + } else { + return 0; + } #endif } diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index 872d4a78d..b0927daa1 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -39,7 +39,8 @@ #include "bearssl_stdlib.h" /* The x86 intrinsics seem to be incomplete compared to what aes_x86ni expects when compiling with NXDK */ -#ifdef NXDK +/* Also disable when compiling the legacy windows 9x build */ +#if defined NXDK || defined CC_BUILD_NOSTDLIB #define BR_AES_X86NI 0 #define BR_ENABLE_INTRINSICS 0 #define BR_SSE2 0 From 0d4b271fedd1b13047ac567d8239167a6952db2d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 7 Sep 2025 19:40:47 +1000 Subject: [PATCH 067/115] Fix crashing on some 32 bit x86 systems --- third_party/bearssl/aes_x86ni.c | 4 ++-- third_party/bearssl/aes_x86ni_cbcdec.c | 2 +- third_party/bearssl/aes_x86ni_cbcenc.c | 2 +- third_party/bearssl/aes_x86ni_ctr.c | 2 +- third_party/bearssl/aes_x86ni_ctrcbc.c | 8 ++++---- third_party/bearssl/chacha20_sse2.c | 2 +- third_party/bearssl/ghash_pclmul.c | 2 +- third_party/bearssl/inner.h | 12 ++++++++++++ 8 files changed, 23 insertions(+), 11 deletions(-) diff --git a/third_party/bearssl/aes_x86ni.c b/third_party/bearssl/aes_x86ni.c index d2fd25d0d..54c51efd7 100644 --- a/third_party/bearssl/aes_x86ni.c +++ b/third_party/bearssl/aes_x86ni.c @@ -205,7 +205,7 @@ x86ni_keysched(__m128i *sk, const void *key, size_t len) } /* see inner.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION unsigned br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) { @@ -218,7 +218,7 @@ br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) } /* see inner.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION unsigned br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len) { diff --git a/third_party/bearssl/aes_x86ni_cbcdec.c b/third_party/bearssl/aes_x86ni_cbcdec.c index 862b1b5bd..903eb7916 100644 --- a/third_party/bearssl/aes_x86ni_cbcdec.c +++ b/third_party/bearssl/aes_x86ni_cbcdec.c @@ -46,7 +46,7 @@ br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, void *data, size_t len) diff --git a/third_party/bearssl/aes_x86ni_cbcenc.c b/third_party/bearssl/aes_x86ni_cbcenc.c index 85feecdb0..410ed36ee 100644 --- a/third_party/bearssl/aes_x86ni_cbcenc.c +++ b/third_party/bearssl/aes_x86ni_cbcenc.c @@ -46,7 +46,7 @@ br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,aes") +BR_TARGET("sse2,aes") BR_SSE_FUNCTION void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, void *data, size_t len) diff --git a/third_party/bearssl/aes_x86ni_ctr.c b/third_party/bearssl/aes_x86ni_ctr.c index 42f1ed2b8..6223eb816 100644 --- a/third_party/bearssl/aes_x86ni_ctr.c +++ b/third_party/bearssl/aes_x86ni_ctr.c @@ -46,7 +46,7 @@ br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len) diff --git a/third_party/bearssl/aes_x86ni_ctrcbc.c b/third_party/bearssl/aes_x86ni_ctrcbc.c index f57fead68..1f211da2f 100644 --- a/third_party/bearssl/aes_x86ni_ctrcbc.c +++ b/third_party/bearssl/aes_x86ni_ctrcbc.c @@ -46,7 +46,7 @@ br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *data, size_t len) @@ -252,7 +252,7 @@ br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len) @@ -303,7 +303,7 @@ br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len) @@ -452,7 +452,7 @@ br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, } /* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") +BR_TARGET("sse2,sse4.1,aes") BR_SSE_FUNCTION void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len) diff --git a/third_party/bearssl/chacha20_sse2.c b/third_party/bearssl/chacha20_sse2.c index 32d4f0d11..79e442af3 100644 --- a/third_party/bearssl/chacha20_sse2.c +++ b/third_party/bearssl/chacha20_sse2.c @@ -60,7 +60,7 @@ br_chacha20_sse2_get(void) BR_TARGETS_X86_UP /* see bearssl_block.h */ -BR_TARGET("sse2") +BR_TARGET("sse2") BR_SSE_FUNCTION uint32_t br_chacha20_sse2_run(const void *key, const void *iv, uint32_t cc, void *data, size_t len) diff --git a/third_party/bearssl/ghash_pclmul.c b/third_party/bearssl/ghash_pclmul.c index 81d61c25f..87da300d0 100644 --- a/third_party/bearssl/ghash_pclmul.c +++ b/third_party/bearssl/ghash_pclmul.c @@ -228,7 +228,7 @@ pclmulqdq11(__m128i x, __m128i y) } while (0) /* see bearssl_hash.h */ -BR_TARGET("ssse3,pclmul") +BR_TARGET("ssse3,pclmul") BR_SSE_FUNCTION void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) { diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index b0927daa1..40e059c3e 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -2400,6 +2400,18 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, #endif +/* BEG classicube specific */ +/* Fix issue where 32 bit GCC aligns stack to 4 bytes, but will still +/* generate instructions expecting the stack to be _16_ byte aligned */ +/* https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html */ +/* TODO is this needed for MSVC ? */ +#if (BR_GCC || BR_CLANG) && BR_i386 && !BR_amd64 + #define BR_SSE_FUNCTION __attribute__((force_align_arg_pointer)) +#else + #define BR_SSE_FUNCTION +#endif +/* END classicube specific + /* ==================================================================== */ #endif From d6e7c9b41dbe1a1eb80b0526a1d63fdb1734617d Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Sun, 7 Sep 2025 03:36:43 -0700 Subject: [PATCH 068/115] hpux 11iv3 fixes, use mesa --- Makefile | 5 +++-- readme.md | 1 + src/Logger.c | 11 +++++++++++ src/Platform_Posix.c | 7 +++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 289f58b4d..3b8f1e243 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ BUILD_DIRS = $(BUILD_DIR) $(BUILD_DIR)/src # Configurable flags and names ############################## # Flags passed to the C compiler -CFLAGS = -pipe -fno-math-errno -Werror -Wno-error=missing-braces -Wno-error=strict-aliasing +CFLAGS = -pipe -fno-math-errno # Flags passed to the linker LDFLAGS = -g -rdynamic # Name of the main executable @@ -88,8 +88,9 @@ endif ifeq ($(PLAT),hp-ux) CC = gcc + CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_DEFAULT_SOURCE -D_BSD_SOURCE LDFLAGS = - LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib -lGL -lpthread + LIBS = -lm -lX11 -lXi -lXext -L/usr/local/lib/hpux32 -lGL -lpthread BUILD_DIR = build/hpux endif diff --git a/readme.md b/readme.md index f90a13443..6a0980317 100644 --- a/readme.md +++ b/readme.md @@ -74,6 +74,7 @@ And also runs on: * Haiku - needs openal package (if you have a GitHub account, can [download from here](https://github.com/ClassiCube/ClassiCube/actions/workflows/build_haiku.yml)) * BeOS - untested on actual hardware * IRIX - needs openal packages +* HP-UX - needs Mesa package, tried building with HP OpenGL and `-DCC_BUILD_GL11` still not working * SerenityOS - needs SDL2 * Classic Mac OS (System 7 and later) * Dreamcast - unfinished, but usable (can [download from here](https://www.classicube.net/download/dreamcast)) diff --git a/src/Logger.c b/src/Logger.c index c1ffd251a..b614179b5 100644 --- a/src/Logger.c +++ b/src/Logger.c @@ -280,6 +280,12 @@ static void DumpFrame(cc_string* trace, void* addr) { cc_uintptr addr_ = (cc_uintptr)addr; String_Format1(trace, "%x", &addr_); } +#elif defined CC_BUILD_HPUX +/* HP-UX doesn't expose a nice interface for dladdr */ +static void DumpFrame(cc_string* trace, void* addr) { + cc_uintptr addr_ = (cc_uintptr)addr; + String_Format1(trace, "%x", &addr_); +} #elif defined CC_BUILD_POSIX && !defined CC_BUILD_OS2 /* need to define __USE_GNU for dladdr */ #ifndef __USE_GNU @@ -455,6 +461,11 @@ void Logger_Backtrace(cc_string* trace, void* ctx) { String_AppendConst(trace, "-- backtrace unimplemented --"); /* There is no dladdr on Symbian */ } +#elif defined CC_BUILD_HPUX +/* HP-UX doesn't have unwind support */ +void Logger_Backtrace(cc_string* trace, void* ctx) { + String_AppendConst(trace, "-- backtrace unimplemented --"); +} #elif defined CC_BUILD_POSIX /* musl etc - rely on unwind from GCC instead */ #define CC_BACKTRACE_UNWIND diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 1f5c0dfa9..b07d14b8e 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -800,9 +800,16 @@ cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { if (*s == -1) return errno; if (nonblocking) { +#ifdef CC_BUILD_HPUX + int flags = fcntl(*s, F_GETFL, 0); + if (flags == -1) return errno; + int err = fcntl(*s, F_SETFL, flags | O_NONBLOCK); + if (err == -1) return errno; +#else int blocking_raw = -1; /* non-blocking mode */ int err = ioctl(*s, FIONBIO, &blocking_raw); if (err == -1) return errno; +#endif } return 0; } From cefb338e023b0002f054bcdc084880f7ad72e78a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 8 Sep 2025 06:48:14 +1000 Subject: [PATCH 069/115] PS3: Write more GPU commands directly --- src/ps3/Graphics_PS3.c | 39 +++++++++++++-------- src/ps3/rsx_gpu.h | 51 +++++++++++++++++++++++++--- src/xbox/Graphics_Xbox.c | 2 -- src/xbox/nv2a_gpu.h | 47 ++++++++++++------------- third_party/bearssl/bearssl_stdlib.h | 4 +-- third_party/bearssl/inner.h | 2 +- 6 files changed, 99 insertions(+), 46 deletions(-) diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index 20017a224..f93b595aa 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -11,9 +11,6 @@ static gcmContextData* context; static u32 cur_fb; -#define CB_SIZE 0x100000 // TODO: smaller command buffer? -#define HOST_SIZE (32 * 1024 * 1024) - /*########################################################################################################################* *----------------------------------------------------- Vertex Shaders ----------------------------------------------------* @@ -135,9 +132,23 @@ static u32* depth_buffer; #define GCM_LABEL_INDEX 255 static u32 labelID = 1; +#define CB_SIZE (1024 * 1024) // TODO: smaller command buffer? +#define HOST_SIZE (32 * 1024 * 1024) + +#define uint_to_ptr(raw) ((void*)((uintptr_t)(raw))) +#define ptr_to_uint(raw) ((uint32_t)((uintptr_t)(raw))) +extern s32 gcmInitBodyEx(uint32_t ctx, uint32_t cbSize, uint32_t ioSize, uint32_t ioBuf); + static void CreateContext(void) { - void* host_addr = memalign(1024 * 1024, HOST_SIZE); - rsxInit(&context, CB_SIZE, HOST_SIZE, host_addr); + void* host_buf = memalign(1024 * 1024, HOST_SIZE); + + // PS3 pointers are 32 bits in size, but our pointers are 64 bits + uint32_t ctx_ptr = 0; + int res = gcmInitBodyEx(ptr_to_uint(&ctx_ptr), CB_SIZE, HOST_SIZE, ptr_to_uint(host_buf)); + if (res) Process_Abort2(res, "gcmInitBody failed"); + + context = uint_to_ptr(ctx_ptr); + rsxHeapInit(); } static void WaitRSXFinish(void) { @@ -307,11 +318,11 @@ void Gfx_TransferImage(u32 offset, s32 w, s32 h) { static cc_uint32 clearColor; void Gfx_SetFaceCulling(cc_bool enabled) { - rsxSetCullFaceEnable(context, enabled); + RSX_set_cull_face(context, enabled); } static void SetAlphaBlend(cc_bool enabled) { - rsxSetBlendEnable(context, enabled); + RSX_set_alpha_blend(context, enabled); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } @@ -324,15 +335,15 @@ void Gfx_ClearColor(PackedCol color) { } void Gfx_SetDepthWrite(cc_bool enabled) { - rsxSetDepthWriteEnable(context, enabled); + RSX_set_depth_write(context, enabled); } void Gfx_SetDepthTest(cc_bool enabled) { - rsxSetDepthTestEnable(context, enabled); + RSX_set_depth_test(context, enabled); } static void SetAlphaTest(cc_bool enabled) { - rsxSetAlphaTestEnable(context, enabled); + RSX_set_alpha_test(context, enabled); } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { @@ -410,9 +421,9 @@ static void ResetFrameState(void) { rsxSetClearColor(context, clearColor); rsxSetClearDepthStencil(context, 0xFFFFFFFF); - rsxSetDepthFunc(context, GCM_LEQUAL); - rsxSetDepthWriteEnable(context, true); - rsxSetDepthTestEnable(context, true); + RSX_set_depth_func(context, GCM_LEQUAL); + RSX_set_depth_write(context, true); + RSX_set_depth_test(context, true); rsxSetUserClipPlaneControl(context, GCM_USER_CLIP_PLANE_DISABLE, GCM_USER_CLIP_PLANE_DISABLE, @@ -492,7 +503,7 @@ void Gfx_SetScissor(int x, int y, int w, int h) { static int vb_size; GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - return 1;/* TODO */ + return (void*)1; } void Gfx_BindIb(GfxResourceID ib) { } diff --git a/src/ps3/rsx_gpu.h b/src/ps3/rsx_gpu.h index eabad5ed5..1f80a0a38 100644 --- a/src/ps3/rsx_gpu.h +++ b/src/ps3/rsx_gpu.h @@ -2,6 +2,7 @@ *-----------------------------------------------------GPU commands--------------------------------------------------------* *#########################################################################################################################*/ // NOTE: shared with nv2a (Xbox) GPU +#define RSX_MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) // disables the default increment behaviour when writing multiple registers // E.g. with RSX_3D_COMMAND(cmd, 4): @@ -20,8 +21,9 @@ *#########################################################################################################################*/ static CC_INLINE uint32_t* RSX_reserve(gcmContextData* ctx, int count) { if (ctx->current + count > ctx->end) { - // TODO handle command buffer overflow properly - Process_Abort("Command buffer overflow"); + // This flushes the command buffer to GPU via DMA + // TODO: returns 0 if fails, but not checked for?? + rsxContextCallback(ctx, count); } uint32_t* p = ctx->current; @@ -35,6 +37,9 @@ static CC_INLINE uint32_t* RSX_reserve_command(gcmContextData* context, uint32_t return p; } +#define RSX_append_single_command(context, cmd, value) \ + uint32_t* p = RSX_reserve_command(ctx, cmd, 1); \ + *p++ = value; /*########################################################################################################################* *-----------------------------------------------------Raster control------------------------------------------------------* @@ -53,6 +58,44 @@ static CC_INLINE void RSX_set_color_write_mask(gcmContextData* ctx, int r, int g if (b) mask |= GCM_COLOR_MASK_B; if (a) mask |= GCM_COLOR_MASK_A; - uint32_t* p = RSX_reserve_command(ctx, NV40TCL_COLOR_MASK, 1); - *p++ = mask; + RSX_append_single_command(ctx, NV40TCL_COLOR_MASK, mask); +} + + +/*########################################################################################################################* +*-----------------------------------------------------State management----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_set_depth_write(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_WRITE_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_depth_test(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_TEST_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_depth_func(gcmContextData* ctx, int func) { + RSX_append_single_command(ctx, NV40TCL_DEPTH_FUNC, func); +} + + +static CC_INLINE void RSX_set_alpha_test(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_ENABLE, enabled); +} + +static CC_INLINE void RSX_set_alpha_test_func(gcmContextData* ctx, int func) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_FUNC, func); +} + +static CC_INLINE void RSX_set_alpha_test_ref(gcmContextData* ctx, int ref) { + RSX_append_single_command(ctx, NV40TCL_ALPHA_TEST_REF, ref); +} + + +static CC_INLINE void RSX_set_alpha_blend(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_BLEND_ENABLE, enabled); +} + + +static CC_INLINE void RSX_set_cull_face(gcmContextData* ctx, int enabled) { + RSX_append_single_command(ctx, NV40TCL_CULL_FACE_ENABLE, enabled); } diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index f9bd2ab6a..001a12b98 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -4,8 +4,6 @@ #include "../Window.h" #include -#define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) - #include "nv2a_gpu.h" #define MAX_RAM_ADDR 0x03FFAFFF diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index 01bd42998..c9783f4c5 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -2,6 +2,7 @@ *-----------------------------------------------------GPU commands--------------------------------------------------------* *#########################################################################################################################*/ // NOTE: shared with RSX (PS3) GPU +#define NV2A_MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) // disables the default increment behaviour when writing multiple registers // E.g. with NV2A_3D_COMMAND(cmd, 4): @@ -66,10 +67,10 @@ static CC_INLINE uint32_t* NV2A_set_color_write_mask(uint32_t* p, int r, int g, *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_set_fog_colour(uint32_t* p, int R, int G, int B, int A) { uint32_t mask = - 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); + NV2A_MASK(NV097_SET_FOG_COLOR_RED, R) | + NV2A_MASK(NV097_SET_FOG_COLOR_GREEN, G) | + NV2A_MASK(NV097_SET_FOG_COLOR_BLUE, B) | + NV2A_MASK(NV097_SET_FOG_COLOR_ALPHA, A); return NV2A_push1(p, NV097_SET_FOG_COLOR, mask); } @@ -145,8 +146,8 @@ static void NV2A_DrawArrays(int mode, unsigned start, unsigned count) { { int batch_count = min(count, DA_BATCH_SIZE); - *p++ = MASK(NV097_DRAW_ARRAYS_COUNT, batch_count-1) | - MASK(NV097_DRAW_ARRAYS_START_INDEX, start); + *p++ = NV2A_MASK(NV097_DRAW_ARRAYS_COUNT, batch_count-1) | + NV2A_MASK(NV097_DRAW_ARRAYS_START_INDEX, start); start += batch_count; count -= batch_count; @@ -195,8 +196,8 @@ static CC_INLINE uint32_t* NV2A_set_program_run_offset(uint32_t* p, int offset) static CC_INLINE uint32_t* NV2A_set_execution_mode_shaders(uint32_t* p) { p = NV2A_push1(p, NV097_SET_TRANSFORM_EXECUTION_MODE, - MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) | - MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); + NV2A_MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_MODE_PROGRAM) | + NV2A_MASK(NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE, NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE_PRIV)); p = NV2A_push1(p, NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN, 0); return p; @@ -222,9 +223,9 @@ static uint32_t* NV2A_reset_all_vertex_attribs(uint32_t* p) { static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int format, int size, int stride) { uint32_t mask = - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | - MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride); + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | + NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride); return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, mask); } @@ -271,8 +272,8 @@ static CC_INLINE uint32_t* NV2A_set_texture0_control0(uint32_t* p, int texkill) return NV2A_push1(p, NV097_SET_TEXTURE_CONTROL0, NV097_SET_TEXTURE_CONTROL0_ENABLE | (texkill ? _NV_ALPHAKILL_EN : 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | - MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); + NV2A_MASK(NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP, 0) | + NV2A_MASK(NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP, 1)); } static uint32_t* NV2A_set_texture0_pointer(uint32_t* p, void* pixels) { @@ -282,14 +283,14 @@ static uint32_t* NV2A_set_texture0_pointer(uint32_t* p, void* pixels) { static uint32_t* NV2A_set_texture0_format(uint32_t* p, unsigned log_u, unsigned log_v) { return NV2A_push1(p, NV097_SET_TEXTURE_FORMAT, - MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | - MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | - MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | - MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V - MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | - MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA, 2) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE, NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_COLOR, NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY, 2) | // textures have U and V + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS, 1) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U, log_u) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V, log_v) | + NV2A_MASK(NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P, 0)); // log2(1) slice = 0 } static uint32_t* NV2A_set_texture0_wrapmode(uint32_t* p) { @@ -300,8 +301,8 @@ static uint32_t* NV2A_set_texture0_wrapmode(uint32_t* p) { static uint32_t* NV2A_set_texture0_filter(uint32_t* p) { return NV2A_push1(p, NV097_SET_TEXTURE_FILTER, 0x2000 | - MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | - MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter + NV2A_MASK(NV097_SET_TEXTURE_FILTER_MIN, 1) | + NV2A_MASK(NV097_SET_TEXTURE_FILTER_MAG, 1)); // 1 = nearest filter } static uint32_t* NV2A_set_texture0_matrix(uint32_t* p, int enabled) { diff --git a/third_party/bearssl/bearssl_stdlib.h b/third_party/bearssl/bearssl_stdlib.h index 77a5998be..5fb35c2c0 100644 --- a/third_party/bearssl/bearssl_stdlib.h +++ b/third_party/bearssl/bearssl_stdlib.h @@ -1,13 +1,13 @@ #ifndef BR_BEARSSL_STDLIB_H__ #define BR_BEARSSL_STDLIB_H__ /* ==== BEG ClassiCube specific ==== */ -static size_t br_strlen(const char* a) { +static inline size_t br_strlen(const char* a) { int i = 0; while (*a++) i++; return i; } -static size_t br_memcmp(const void* a, const void* b, size_t len) { +static inline size_t br_memcmp(const void* a, const void* b, size_t len) { unsigned char* p1 = (unsigned char*)a; unsigned char* p2 = (unsigned char*)b; size_t i; diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index 40e059c3e..c21f616be 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -2401,7 +2401,7 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, #endif /* BEG classicube specific */ -/* Fix issue where 32 bit GCC aligns stack to 4 bytes, but will still +/* Fix issue where 32 bit GCC aligns stack to 4 bytes, but will still */ /* generate instructions expecting the stack to be _16_ byte aligned */ /* https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html */ /* TODO is this needed for MSVC ? */ From 60c7da3cfb7c589d4c82fed938a4af01eaed3afb Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Mon, 8 Sep 2025 02:18:17 -0700 Subject: [PATCH 070/115] add CC_BUILD_GL11_FALLBACK for hpux --- src/Core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core.h b/src/Core.h index 4e5226f3f..3848f3954 100644 --- a/src/Core.h +++ b/src/Core.h @@ -362,6 +362,7 @@ typedef cc_uint8 cc_bool; #define CC_BIG_ENDIAN #define CC_BUILD_NOMUSIC #define CC_BUILD_NOSOUNDS + #define CC_BUILD_GL11_FALLBACK #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 From f7dbe579669bbe3eba85a22c39eb18a274491acc Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 8 Sep 2025 20:37:39 +1000 Subject: [PATCH 071/115] PS3: More manual GPU commands --- src/ps3/Graphics_PS3.c | 6 +----- src/ps3/rsx_gpu.h | 31 +++++++++++++++++++++++++++++++ src/xbox/Graphics_Xbox.c | 2 +- src/xbox/nv2a_gpu.h | 10 +++++----- third_party/bearssl/inner.h | 2 +- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/ps3/Graphics_PS3.c b/src/ps3/Graphics_PS3.c index f93b595aa..bfecf1303 100644 --- a/src/ps3/Graphics_PS3.c +++ b/src/ps3/Graphics_PS3.c @@ -454,11 +454,7 @@ void Gfx_BeginFrame(void) { } void Gfx_ClearBuffers(GfxBuffers buffers) { - int targets = 0; - if (buffers & GFX_BUFFER_COLOR) targets |= (GCM_CLEAR_R | GCM_CLEAR_G | GCM_CLEAR_B | GCM_CLEAR_A); - if (buffers & GFX_BUFFER_DEPTH) targets |= (GCM_CLEAR_S | GCM_CLEAR_Z); - - rsxClearSurface(context, targets); + RSX_clear_buffers(context, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); } void Gfx_EndFrame(void) { diff --git a/src/ps3/rsx_gpu.h b/src/ps3/rsx_gpu.h index 1f80a0a38..acea10951 100644 --- a/src/ps3/rsx_gpu.h +++ b/src/ps3/rsx_gpu.h @@ -41,6 +41,7 @@ static CC_INLINE uint32_t* RSX_reserve_command(gcmContextData* context, uint32_t uint32_t* p = RSX_reserve_command(ctx, cmd, 1); \ *p++ = value; + /*########################################################################################################################* *-----------------------------------------------------Raster control------------------------------------------------------* *#########################################################################################################################*/ @@ -99,3 +100,33 @@ static CC_INLINE void RSX_set_alpha_blend(gcmContextData* ctx, int enabled) { static CC_INLINE void RSX_set_cull_face(gcmContextData* ctx, int enabled) { RSX_append_single_command(ctx, NV40TCL_CULL_FACE_ENABLE, enabled); } + + +/*########################################################################################################################* +*-----------------------------------------------------Vertex attributes---------------------------------------------------* +*#########################################################################################################################*/ +/*static CC_INLINE void RSX_set_vertex_attrib_format(gcmContextData* ctx, int attrib, int format, int size, int stride) { + uint32_t mask = + RSX_MASK(NV40TCL_VTXFMT_TYPE_MASK, format) | + RSX_MASK(NV40TCL_VTXFMT_SIZE_MASK, size) | + RSX_MASK(NV40TCL_VTXFMT_STRIDE_MASK, stride); + + RSX_append_single_command(ctx, NV40TCL_VTXFMT(attrib), mask); +} + +// NOTE: GCM_LOCATION_RSX implicitly assumed for location +static CC_INLINE void RSX_set_vertex_attrib_pointer(gcmContextData* ctx, int attrib, uint32_t addr) { + RSX_append_single_command(ctx, NV40TCL_VTXBUF_ADDRESS(attrib), addr); +}*/ + + +/*########################################################################################################################* +*------------------------------------------------------Buffer clearing----------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void RSX_clear_buffers(gcmContextData* ctx, int color, int depth) { + uint32_t targets = 0; + if (color) targets |= (GCM_CLEAR_R | GCM_CLEAR_G | GCM_CLEAR_B | GCM_CLEAR_A); + if (depth) targets |= (GCM_CLEAR_S | GCM_CLEAR_Z); + + RSX_append_single_command(ctx, NV40TCL_CLEAR_BUFFERS, targets); +} diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 001a12b98..158d2ce36 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -342,7 +342,7 @@ void Gfx_BeginFrame(void) { void Gfx_ClearBuffers(GfxBuffers buffers) { uint32_t* p = pb_begin(); - p = NV2A_start_clear(p, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); + p = NV2A_clear_buffers(p, buffers & GFX_BUFFER_COLOR, buffers & GFX_BUFFER_DEPTH); pb_end(p); //pb_erase_text_screen(); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index c9783f4c5..4313ec826 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -221,18 +221,18 @@ static uint32_t* NV2A_reset_all_vertex_attribs(uint32_t* p) { return p; } -static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int index, int format, int size, int stride) { +static uint32_t* NV2A_set_vertex_attrib_format(uint32_t* p, int attrib, int format, int size, int stride) { uint32_t mask = NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE, format) | NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE, size) | NV2A_MASK(NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE, stride); - return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + index * 4, mask); + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_FORMAT + attrib * 4, mask); } -static uint32_t* NV2A_set_vertex_attrib_pointer(uint32_t* p, int index, cc_uint8* data) { +static uint32_t* NV2A_set_vertex_attrib_pointer(uint32_t* p, int attrib, cc_uint8* data) { uint32_t offset = (uint32_t)data & 0x03ffffff; - return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + index * 4, offset); + return NV2A_push1(p, NV097_SET_VERTEX_DATA_ARRAY_OFFSET + attrib * 4, offset); } @@ -253,7 +253,7 @@ static CC_INLINE uint32_t* NV2A_set_clear_colour(uint32_t* p, uint32_t colour) { colour); } -static CC_INLINE uint32_t* NV2A_start_clear(uint32_t* p, int color, int depth) { +static CC_INLINE uint32_t* NV2A_clear_buffers(uint32_t* p, int color, int depth) { uint32_t mask = 0; if (color) mask |= NV097_CLEAR_SURFACE_COLOR; if (depth) mask |= NV097_CLEAR_SURFACE_Z; diff --git a/third_party/bearssl/inner.h b/third_party/bearssl/inner.h index c21f616be..e17ea7bae 100644 --- a/third_party/bearssl/inner.h +++ b/third_party/bearssl/inner.h @@ -2410,7 +2410,7 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, #else #define BR_SSE_FUNCTION #endif -/* END classicube specific +/* END classicube specific */ /* ==================================================================== */ From 5918ad85e625bb0e96df16f5bc7af2534c42d183 Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:15:56 -0700 Subject: [PATCH 072/115] restore compiler warnings --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3b8f1e243..e86b9f4f0 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ BUILD_DIRS = $(BUILD_DIR) $(BUILD_DIR)/src # Configurable flags and names ############################## # Flags passed to the C compiler -CFLAGS = -pipe -fno-math-errno +CFLAGS = -pipe -fno-math-errno -Werror -Wno-error=missing-braces -Wno-error=strict-aliasing # Flags passed to the linker LDFLAGS = -g -rdynamic # Name of the main executable From 873cc1ca6720625ea7182c6e05cb4a130dd8b4ba Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:17:31 -0700 Subject: [PATCH 073/115] update readme for hpux --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 6a0980317..3cf7637b0 100644 --- a/readme.md +++ b/readme.md @@ -74,7 +74,7 @@ And also runs on: * Haiku - needs openal package (if you have a GitHub account, can [download from here](https://github.com/ClassiCube/ClassiCube/actions/workflows/build_haiku.yml)) * BeOS - untested on actual hardware * IRIX - needs openal packages -* HP-UX - needs Mesa package, tried building with HP OpenGL and `-DCC_BUILD_GL11` still not working +* HPUX - tested on 11v3 IA64 * SerenityOS - needs SDL2 * Classic Mac OS (System 7 and later) * Dreamcast - unfinished, but usable (can [download from here](https://www.classicube.net/download/dreamcast)) From d84ad841f1d3e8cbc49393a8242bb89f5797f99f Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:38:03 -0700 Subject: [PATCH 074/115] use hp opengl --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e86b9f4f0..833eb0314 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ ifeq ($(PLAT),hp-ux) CC = gcc CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_DEFAULT_SOURCE -D_BSD_SOURCE LDFLAGS = - LIBS = -lm -lX11 -lXi -lXext -L/usr/local/lib/hpux32 -lGL -lpthread + LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib/hpux32 -lGL -lXhp11 -lpthread BUILD_DIR = build/hpux endif From 5774e290c570e137ce157d63ed0213da248d8be3 Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:39:54 -0700 Subject: [PATCH 075/115] add casts to Graphics_GL1.c to make -Werror happy --- src/Graphics_GL1.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index 01b3e6e7e..a8d5fc9bf 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -207,27 +207,27 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { #define IB_PTR NULL static void GL_SetupVbColoured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, VB_PTR + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, VB_PTR + 12); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + 12)); } static void GL_SetupVbTextured(void) { - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + 16)); } static void GL_SetupVbColoured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, VB_PTR + offset + 12); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (GLpointer)(VB_PTR + offset + 12)); } static void GL_SetupVbTextured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 16)); } void Gfx_SetVertexFormat(VertexFormat fmt) { @@ -267,9 +267,9 @@ void Gfx_DrawVb_IndexedTris(int verticesCount) { void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 0); - _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 12); - _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, VB_PTR + offset + 16); + _glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 0)); + _glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 12)); + _glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (GLpointer)(VB_PTR + offset + 16)); _glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); } @@ -585,7 +585,7 @@ static void APIENTRY gl10_colorPointer(GLint size, GLenum type, GLsizei stride, static void APIENTRY gl10_texCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { } static void APIENTRY gl10_vertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { - gl10_vb = cur_vb->data + offset; + gl10_vb = cur_vb->data + (cc_uintptr)offset; } From fc9f9c011b808a0c88221d952db14eee3a30ab29 Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:41:45 -0700 Subject: [PATCH 076/115] fix hpux colormap --- src/_GLShared.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/_GLShared.h b/src/_GLShared.h index 40c2afa65..8eec7ec8d 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -80,6 +80,12 @@ static void ConvertRGBA(void* dst, const void* src, int numPixels) { d[1] = s[2]; d[2] = s[3]; d[3] = s[0]; +#elif defined CC_BUILD_HPUX + /* HP-UX specific color channel mapping - try IRIX style G,B,A,R */ + d[0] = s[1]; /* R = G */ + d[1] = s[2]; /* G = B */ + d[2] = s[3]; /* B = A */ + d[3] = s[0]; /* A = R */ #else d[0] = s[2]; d[1] = s[1]; From 3a762a531171e03608a826a717071bf0f6787a37 Mon Sep 17 00:00:00 2001 From: Antoni Sawicki Date: Tue, 9 Sep 2025 02:55:28 -0700 Subject: [PATCH 077/115] -lXhp11 not needed --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 833eb0314..46d934852 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ ifeq ($(PLAT),hp-ux) CC = gcc CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_DEFAULT_SOURCE -D_BSD_SOURCE LDFLAGS = - LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib/hpux32 -lGL -lXhp11 -lpthread + LIBS = -lm -lX11 -lXi -lXext -L/opt/graphics/OpenGL/lib/hpux32 -lGL -lpthread BUILD_DIR = build/hpux endif From 39c266af1b31f479cb1746ab531e56a29dce8405 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 9 Sep 2025 20:28:35 +1000 Subject: [PATCH 078/115] Xbox: Fix log output on Xemu --- misc/3ds/PORT_INFO.md | 15 +++++++++++++++ misc/gba/PORT_INFO.md | 3 +++ misc/gc/PORT_INFO.md | 5 +++++ misc/wii/PORT_INFO.md | 5 +++++ misc/xbox/PORT_INFO.md | 7 +++++++ src/3ds/Platform_3DS.c | 1 - src/Graphics_GL11.c | 12 ++++++++++++ src/gcwii/Platform_GCWii.c | 4 ---- src/xbox/Platform_Xbox.c | 8 +++----- 9 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 misc/3ds/PORT_INFO.md create mode 100644 misc/gba/PORT_INFO.md create mode 100644 misc/gc/PORT_INFO.md create mode 100644 misc/wii/PORT_INFO.md create mode 100644 misc/xbox/PORT_INFO.md diff --git a/misc/3ds/PORT_INFO.md b/misc/3ds/PORT_INFO.md new file mode 100644 index 000000000..e3bd113ad --- /dev/null +++ b/misc/3ds/PORT_INFO.md @@ -0,0 +1,15 @@ +To see debug log messages in Citra: + +1) Make sure log level set to "Debug.Emulated:Debug" + +--- + +Commands used to generate the .bin files: + +`bannertool makebanner -i banner.png -a audio.wav -o banner.bin` + +`bannertool makesmdh -s ClassiCube -l ClassiCube -p UnknownShadow200 -i icon.png -o icon.bin` + +---- + +Debug log messages output to debug service, so may be possible to see from console via remote gdb diff --git a/misc/gba/PORT_INFO.md b/misc/gba/PORT_INFO.md new file mode 100644 index 000000000..64b04c9c5 --- /dev/null +++ b/misc/gba/PORT_INFO.md @@ -0,0 +1,3 @@ +To see debug log messages in mGBA: + +1) In the UI, make sure in Tools > Logging, that Debugger is enabled diff --git a/misc/gc/PORT_INFO.md b/misc/gc/PORT_INFO.md new file mode 100644 index 000000000..ba317114e --- /dev/null +++ b/misc/gc/PORT_INFO.md @@ -0,0 +1,5 @@ +To see debug log messages in Dolphin: + +1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu +2) Make sure "OSReport EXI (OSREPORT)" log type is enabled +3) In the UI, make sure 'Show log' checkbox is checked in View menu diff --git a/misc/wii/PORT_INFO.md b/misc/wii/PORT_INFO.md new file mode 100644 index 000000000..ba317114e --- /dev/null +++ b/misc/wii/PORT_INFO.md @@ -0,0 +1,5 @@ +To see debug log messages in Dolphin: + +1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu +2) Make sure "OSReport EXI (OSREPORT)" log type is enabled +3) In the UI, make sure 'Show log' checkbox is checked in View menu diff --git a/misc/xbox/PORT_INFO.md b/misc/xbox/PORT_INFO.md new file mode 100644 index 000000000..f5da3eb2f --- /dev/null +++ b/misc/xbox/PORT_INFO.md @@ -0,0 +1,7 @@ +To see debug log messages in Xemu: + +1) Launch Xemu as `xemu -device lpc47m157 -serial stdio` + +---- + +To launch directly, `-dvd_path cc-xbox.iso` diff --git a/src/3ds/Platform_3DS.c b/src/3ds/Platform_3DS.c index 00be4e84a..43c801100 100644 --- a/src/3ds/Platform_3DS.c +++ b/src/3ds/Platform_3DS.c @@ -53,7 +53,6 @@ unsigned int __stacksize__ = 256 * 1024; *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ void Platform_Log(const char* msg, int len) { - // output to debug service (visible in Citra with log level set to "Debug.Emulated:Debug", or on console via remote gdb) svcOutputDebugString(msg, len); } diff --git a/src/Graphics_GL11.c b/src/Graphics_GL11.c index 60a75cc58..5c84fe433 100644 --- a/src/Graphics_GL11.c +++ b/src/Graphics_GL11.c @@ -30,6 +30,17 @@ typedef void (*GL_SetupVBRangeFunc)(int startVertex); static GL_SetupVBFunc gfx_setupVBFunc; static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; +static void CheckSupport(void) { + static const cc_string bgraExt = String_FromConst("GL_EXT_bgra"); + cc_string extensions = String_FromReadonly((const char*)_glGetString(GL_EXTENSIONS)); + const GLubyte* ver = _glGetString(GL_VERSION); + + /* Version string is always: x.y. (and whatever afterwards) */ + int major = ver[0] - '0', minor = ver[2] - '0'; + /* Some old IRIX cards don't support BGRA */ + convert_rgba = major == 1 && minor <= 1 && !String_CaselessContains(&extensions, &bgraExt); +} + void Gfx_Create(void) { GLContext_Create(); GL_InitCommon(); @@ -37,6 +48,7 @@ void Gfx_Create(void) { MakeIndices(gl_indices, GFX_MAX_INDICES, NULL); Gfx_RestoreState(); GLContext_SetVSync(gfx_vsync); + CheckSupport(); } diff --git a/src/gcwii/Platform_GCWii.c b/src/gcwii/Platform_GCWii.c index 974ec2cec..807733b6e 100644 --- a/src/gcwii/Platform_GCWii.c +++ b/src/gcwii/Platform_GCWii.c @@ -48,10 +48,6 @@ cc_bool Platform_ReadonlyFilesystem; /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ -// To see these log messages: -// 1) In the UI, make sure 'Show log configuration' checkbox is checked in View menu -// 2) Make sure "OSReport EXI (OSREPORT)" log type is enabled -// 3) In the UI, make sure 'Show log' checkbox is checked in View menu static void LogOverEXI(char* msg, int len) { u32 cmd = 0x80000000 | (0x800400 << 6); // write flag, UART base address diff --git a/src/xbox/Platform_Xbox.c b/src/xbox/Platform_Xbox.c index 1338750e5..d61358b83 100644 --- a/src/xbox/Platform_Xbox.c +++ b/src/xbox/Platform_Xbox.c @@ -34,13 +34,11 @@ cc_bool Platform_ReadonlyFilesystem; *------------------------------------------------------Logging/Time-------------------------------------------------------* *#########################################################################################################################*/ void Platform_Log(const char* msg, int len) { - char tmp[2048 + 1]; + char tmp[2048 + 2]; len = min(len, 2048); - Mem_Copy(tmp, msg, len); tmp[len] = '\0'; + Mem_Copy(tmp, msg, len); tmp[len] = '\n'; tmp[len + 1] = '\0'; - // log to on-screen display - debugPrint("%s\n", tmp); - // log to cxbx-reloaded console + // log to cxbx-reloaded console or Xemu serial output OutputDebugStringA(tmp); } From 18a1f45ee48c3c77bbb5e3e6e1323a5859f7f5c1 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 9 Sep 2025 21:29:14 +1000 Subject: [PATCH 079/115] Xbox: Try to fix texture warping --- misc/3ds/{PORT_INFO.md => README.md} | 0 misc/3ds/readme.md | 5 ----- misc/gba/{PORT_INFO.md => README.md} | 0 misc/gc/{PORT_INFO.md => README.md} | 0 misc/wii/{PORT_INFO.md => README.md} | 0 misc/xbox/{PORT_INFO.md => README.md} | 0 src/xbox/nv2a_gpu.h | 5 ++++- 7 files changed, 4 insertions(+), 6 deletions(-) rename misc/3ds/{PORT_INFO.md => README.md} (100%) delete mode 100644 misc/3ds/readme.md rename misc/gba/{PORT_INFO.md => README.md} (100%) rename misc/gc/{PORT_INFO.md => README.md} (100%) rename misc/wii/{PORT_INFO.md => README.md} (100%) rename misc/xbox/{PORT_INFO.md => README.md} (100%) diff --git a/misc/3ds/PORT_INFO.md b/misc/3ds/README.md similarity index 100% rename from misc/3ds/PORT_INFO.md rename to misc/3ds/README.md diff --git a/misc/3ds/readme.md b/misc/3ds/readme.md deleted file mode 100644 index 85bc067e0..000000000 --- a/misc/3ds/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -Commands used to generate the .bin files: - -`bannertool makebanner -i banner.png -a audio.wav -o banner.bin` - -`bannertool makesmdh -s ClassiCube -l ClassiCube -p UnknownShadow200 -i icon.png -o icon.bin` \ No newline at end of file diff --git a/misc/gba/PORT_INFO.md b/misc/gba/README.md similarity index 100% rename from misc/gba/PORT_INFO.md rename to misc/gba/README.md diff --git a/misc/gc/PORT_INFO.md b/misc/gc/README.md similarity index 100% rename from misc/gc/PORT_INFO.md rename to misc/gc/README.md diff --git a/misc/wii/PORT_INFO.md b/misc/wii/README.md similarity index 100% rename from misc/wii/PORT_INFO.md rename to misc/wii/README.md diff --git a/misc/xbox/PORT_INFO.md b/misc/xbox/README.md similarity index 100% rename from misc/xbox/PORT_INFO.md rename to misc/xbox/README.md diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index 4313ec826..cecfc5d65 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -15,6 +15,9 @@ #define _NV_ALPHAKILL_EN (1 << 2) +// Enables perspective correct texture interpolation +#define _NV_CONTROL0_TEX_PERSPECTIVE_ENABLE (1 << 20) + /*########################################################################################################################* *-----------------------------------------------------GPU pushbuffer------------------------------------------------------* @@ -38,7 +41,7 @@ static CC_INLINE uint32_t* NV2A_push2(uint32_t* p, int cmd, uint32_t val1, uint3 *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { // resets "z perspective" flag - return NV2A_push1(p, NV097_SET_CONTROL0, 0); + return NV2A_push1(p, NV097_SET_CONTROL0, _NV_CONTROL0_TEX_PERSPECTIVE_ENABLE); } From d2a0a597b9f8e5468f0dbc5e693178c7b808c257 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 10 Sep 2025 07:51:30 +1000 Subject: [PATCH 080/115] GameCube/Wii: For gamecube controller, make B+Dpad L/R to hotbar L/R --- src/gcwii/Window_GCWii.c | 23 ++++++++++++++++++++++- src/xbox/nv2a_gpu.h | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/gcwii/Window_GCWii.c b/src/gcwii/Window_GCWii.c index 2fe333169..2561ce606 100644 --- a/src/gcwii/Window_GCWii.c +++ b/src/gcwii/Window_GCWii.c @@ -111,6 +111,27 @@ void Window_RequestClose(void) { *#########################################################################################################################*/ static PADStatus gc_pads[PAD_CHANMAX]; +static const BindMapping gcpad_defaults[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP, 0 }, + [BIND_BACK] = { CCPAD_DOWN, 0 }, + [BIND_LEFT] = { CCPAD_LEFT, 0 }, + [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, + [BIND_JUMP] = { CCPAD_1, 0 }, + [BIND_SET_SPAWN] = { CCPAD_START, 0 }, + [BIND_CHAT] = { CCPAD_4, 0 }, + [BIND_INVENTORY] = { CCPAD_3, 0 }, + [BIND_SEND_CHAT] = { CCPAD_START, 0 }, + [BIND_DELETE_BLOCK] = { CCPAD_L, 0 }, + [BIND_PLACE_BLOCK] = { CCPAD_R, 0 }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT } +}; + #define PAD_AXIS_SCALE 8.0f static void ProcessPAD_Joystick(int port, int axis, int x, int y, float delta) { // May not be exactly 0 on actual hardware @@ -149,7 +170,7 @@ static void ProcessPADInput(PADStatus* pad, int i, float delta) { return; // not connected, still busy, etc } - int port = Gamepad_Connect(0x5C + i, PadBind_Defaults); + int port = Gamepad_Connect(0x5C + i, gcpad_defaults); ProcessPAD_Buttons(port, gc_pads[i].button); ProcessPAD_Joystick(port, PAD_AXIS_LEFT, gc_pads[i].stickX, gc_pads[i].stickY, delta); ProcessPAD_Joystick(port, PAD_AXIS_RIGHT, gc_pads[i].substickX, gc_pads[i].substickY, delta); diff --git a/src/xbox/nv2a_gpu.h b/src/xbox/nv2a_gpu.h index cecfc5d65..750342c28 100644 --- a/src/xbox/nv2a_gpu.h +++ b/src/xbox/nv2a_gpu.h @@ -40,7 +40,7 @@ static CC_INLINE uint32_t* NV2A_push2(uint32_t* p, int cmd, uint32_t val1, uint3 *-----------------------------------------------------Misc commands-------------------------------------------------------* *#########################################################################################################################*/ static CC_INLINE uint32_t* NV2A_reset_control0(uint32_t* p) { - // resets "z perspective" flag + // resets "z perspective" flag, set "texture perspective flag" return NV2A_push1(p, NV097_SET_CONTROL0, _NV_CONTROL0_TEX_PERSPECTIVE_ENABLE); } From 71991c2275bcbc1f4c7d59bd92c45000584d89b0 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 10 Sep 2025 21:43:33 +1000 Subject: [PATCH 081/115] Gamecube: Change dpad to just be fly up/down hotbar left/right Also make it possible for other platforms to override --- src/3ds/Window_3DS.c | 23 ++++++++++++++++++++++- src/Window_N64.c | 32 ++++++++++++++++---------------- src/dreamcast/Window_Dreamcast.c | 25 +++++++++++++++++++++++-- src/gcwii/Window_GCWii.c | 30 +++++++++++++----------------- src/nds/Graphics_NDS.c | 3 --- src/nds/Platform_NDS.c | 4 +--- src/nds/Window_NDS.c | 29 ++++++++++++++++++++++++----- src/ps2/Window_PS2.c | 23 ++++++++++++++++++++++- src/ps3/Window_PS3.c | 23 ++++++++++++++++++++++- src/psp/Window_PSP.c | 23 ++++++++++++++++++++++- src/psvita/Window_PSVita.c | 30 +++++++++++++++--------------- src/switch/Window_Switch.c | 23 ++++++++++++++++++++++- src/xbox/Window_Xbox.c | 23 ++++++++++++++++++++++- src/xbox360/Window_Xbox360.c | 23 ++++++++++++++++++++++- 14 files changed, 246 insertions(+), 68 deletions(-) diff --git a/src/3ds/Window_3DS.c b/src/3ds/Window_3DS.c index 75d2e9cfc..57ad19fb7 100644 --- a/src/3ds/Window_3DS.c +++ b/src/3ds/Window_3DS.c @@ -128,6 +128,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_3ds[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static Result irrst_result; void Gamepads_Init(void) { @@ -167,7 +188,7 @@ static void ProcessCircleInput(int port, int axis, circlePosition* pos, float de void Gamepads_Process(float delta) { u32 mods = hidKeysDown() | hidKeysHeld(); - int port = Gamepad_Connect(0x3D5, PadBind_Defaults); + int port = Gamepad_Connect(0x3D5, defaults_3ds); HandleButtons(port, mods); circlePosition hid_pos; diff --git a/src/Window_N64.c b/src/Window_N64.c index f2fd20823..0f0b21e1e 100644 --- a/src/Window_N64.c +++ b/src/Window_N64.c @@ -100,24 +100,24 @@ static void ProcessMouse(joypad_inputs_t* inputs, float delta) { /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ -static const BindMapping default_n64[BIND_COUNT] = { - [BIND_FORWARD] = { CCPAD_CUP, 0 }, - [BIND_BACK] = { CCPAD_CDOWN, 0 }, - [BIND_LEFT] = { CCPAD_CLEFT, 0 }, - [BIND_RIGHT] = { CCPAD_CRIGHT, 0 }, +static const BindMapping defaults_n64[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_CUP }, + [BIND_BACK] = { CCPAD_CDOWN }, + [BIND_LEFT] = { CCPAD_CLEFT }, + [BIND_RIGHT] = { CCPAD_CRIGHT }, - [BIND_FLY_UP] = { CCPAD_UP, 0 }, - [BIND_FLY_DOWN]= { CCPAD_DOWN, 0 }, - [BIND_SPEED] = { CCPAD_LEFT, 0 }, - [BIND_FLY] = { CCPAD_RIGHT, 0 }, + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN]= { CCPAD_DOWN }, + [BIND_SPEED] = { CCPAD_LEFT }, + [BIND_FLY] = { CCPAD_RIGHT }, - [BIND_JUMP] = { CCPAD_1, 0 }, - [BIND_INVENTORY] = { CCPAD_2, 0 }, - [BIND_PLACE_BLOCK] = { CCPAD_5, 0 }, - [BIND_HOTBAR_RIGHT] = { CCPAD_L, 0 }, - [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_INVENTORY] = { CCPAD_2 }, + [BIND_PLACE_BLOCK] = { CCPAD_5 }, + [BIND_HOTBAR_RIGHT] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, - [BIND_SET_SPAWN] = { CCPAD_START, 0 }, + [BIND_SET_SPAWN] = { CCPAD_START }, }; void Gamepads_Init(void) { @@ -169,7 +169,7 @@ void Gamepads_Process(float delta) { ProcessMouse(&inputs, delta); continue; } - int port = Gamepad_Connect(0x64 + i, default_n64); + int port = Gamepad_Connect(0x64 + i, defaults_n64); HandleButtons(port, inputs.btn); ProcessAnalogInput(port, &inputs, delta); } diff --git a/src/dreamcast/Window_Dreamcast.c b/src/dreamcast/Window_Dreamcast.c index 24f91dcdd..390d973e1 100644 --- a/src/dreamcast/Window_Dreamcast.c +++ b/src/dreamcast/Window_Dreamcast.c @@ -222,6 +222,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_dc[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } @@ -264,7 +285,7 @@ static void HandleController(int port, bool dual_analog, cont_state_t* state, fl // TODO: verify values are right if(dual_analog) { - HandleJoystick(port, PAD_AXIS_LEFT, state->joyx, state->joyy, delta); + HandleJoystick(port, PAD_AXIS_LEFT, state->joyx, state->joyy, delta); HandleJoystick(port, PAD_AXIS_RIGHT, state->joy2x, state->joy2y, delta); } else @@ -287,7 +308,7 @@ void Gamepads_Process(float delta) { int dual_analog = cont_has_capabilities(cont, CONT_CAPABILITIES_DUAL_ANALOG); if(dual_analog == -1) dual_analog = 0; - int port = Gamepad_Connect(0xDC + i, PadBind_Defaults); + int port = Gamepad_Connect(0xDC + i, defaults_dc); HandleButtons(port, state->buttons); HandleController(port, dual_analog, state, delta); } diff --git a/src/gcwii/Window_GCWii.c b/src/gcwii/Window_GCWii.c index 2561ce606..74310224b 100644 --- a/src/gcwii/Window_GCWii.c +++ b/src/gcwii/Window_GCWii.c @@ -111,25 +111,21 @@ void Window_RequestClose(void) { *#########################################################################################################################*/ static PADStatus gc_pads[PAD_CHANMAX]; -static const BindMapping gcpad_defaults[BIND_COUNT] = { - [BIND_FORWARD] = { CCPAD_UP, 0 }, - [BIND_BACK] = { CCPAD_DOWN, 0 }, - [BIND_LEFT] = { CCPAD_LEFT, 0 }, - [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, - [BIND_JUMP] = { CCPAD_1, 0 }, - [BIND_SET_SPAWN] = { CCPAD_START, 0 }, - [BIND_CHAT] = { CCPAD_4, 0 }, - [BIND_INVENTORY] = { CCPAD_3, 0 }, - [BIND_SEND_CHAT] = { CCPAD_START, 0 }, - [BIND_DELETE_BLOCK] = { CCPAD_L, 0 }, - [BIND_PLACE_BLOCK] = { CCPAD_R, 0 }, +static const BindMapping defaults_gc[BIND_COUNT] = { + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, - [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, - [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, - [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT } }; #define PAD_AXIS_SCALE 8.0f @@ -170,7 +166,7 @@ static void ProcessPADInput(PADStatus* pad, int i, float delta) { return; // not connected, still busy, etc } - int port = Gamepad_Connect(0x5C + i, gcpad_defaults); + int port = Gamepad_Connect(0x5C + i, defaults_gc); ProcessPAD_Buttons(port, gc_pads[i].button); ProcessPAD_Joystick(port, PAD_AXIS_LEFT, gc_pads[i].stickX, gc_pads[i].stickY, delta); ProcessPAD_Joystick(port, PAD_AXIS_RIGHT, gc_pads[i].substickX, gc_pads[i].substickY, delta); diff --git a/src/nds/Graphics_NDS.c b/src/nds/Graphics_NDS.c index 285cccba2..a96b92d49 100644 --- a/src/nds/Graphics_NDS.c +++ b/src/nds/Graphics_NDS.c @@ -1,5 +1,3 @@ -#include "Core.h" -#ifdef CC_BUILD_NDS #include "_GraphicsBase.h" #include "Errors.h" #include "Logger.h" @@ -833,5 +831,4 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { if (skipRendering) return; Draw_TexturedTriangles(verticesCount, startVertex); } -#endif diff --git a/src/nds/Platform_NDS.c b/src/nds/Platform_NDS.c index cde2cb6b5..e39bbc349 100644 --- a/src/nds/Platform_NDS.c +++ b/src/nds/Platform_NDS.c @@ -1,5 +1,3 @@ -#include "Core.h" -#if defined CC_BUILD_NDS #define CC_NO_UPDATER #define CC_NO_DYNLIB @@ -658,4 +656,4 @@ static cc_result GetMachineID(cc_uint32* key) { cc_result Platform_GetEntropy(void* data, int len) { return ERR_NOT_SUPPORTED; } -#endif + diff --git a/src/nds/Window_NDS.c b/src/nds/Window_NDS.c index f722b6ff4..a55f381e1 100644 --- a/src/nds/Window_NDS.c +++ b/src/nds/Window_NDS.c @@ -1,5 +1,3 @@ -#include "Core.h" -#if defined CC_BUILD_NDS #include "Window.h" #include "Platform.h" #include "Input.h" @@ -256,13 +254,34 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* -*#########################################################################################################################*/ +*#########################################################################################################################*/ +static const BindMapping defaults_nds[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0xD5, PadBind_Defaults); + int port = Gamepad_Connect(0xD5, defaults_nds); int mods = keysDown() | keysHeld(); Gamepad_SetButton(port, CCPAD_L, mods & KEY_L); @@ -379,4 +398,4 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { return ERR_NOT_SUPPORTED; } -#endif + diff --git a/src/ps2/Window_PS2.c b/src/ps2/Window_PS2.c index a421c3f93..4bd1fe94d 100644 --- a/src/ps2/Window_PS2.c +++ b/src/ps2/Window_PS2.c @@ -227,6 +227,27 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_ps2[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static char padBuf0[256] __attribute__((aligned(64))); static char padBuf1[256] __attribute__((aligned(64))); @@ -299,7 +320,7 @@ static void ProcessPad(int i, float delta) { int ret = padRead(i, 0, &pad); if (ret == 0) return; - int port = Gamepad_Connect(0x503 + i, PadBind_Defaults); + int port = Gamepad_Connect(0x503 + i, defaults_ps2); ProcessPadInput(port, delta, &pad); } diff --git a/src/ps3/Window_PS3.c b/src/ps3/Window_PS3.c index ffd5f702c..e7de5ce1c 100644 --- a/src/ps3/Window_PS3.c +++ b/src/ps3/Window_PS3.c @@ -271,6 +271,27 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_ps3[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static padInfo pad_info; static padData pad_data[MAX_PORT_NUM]; static cc_bool circle_main; @@ -333,7 +354,7 @@ void Gamepads_Process(float delta) { if (!pad_info.status[i]) continue; ioPadGetData(i, &pad_data[i]); - int port = Gamepad_Connect(0x503 + i, PadBind_Defaults); + int port = Gamepad_Connect(0x503 + i, defaults_ps3); ProcessPadInput(port, delta, &pad_data[i]); } } diff --git a/src/psp/Window_PSP.c b/src/psp/Window_PSP.c index ef2b6f5d3..1f493824e 100644 --- a/src/psp/Window_PSP.c +++ b/src/psp/Window_PSP.c @@ -83,6 +83,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_psp[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; @@ -125,7 +146,7 @@ static void ProcessCircleInput(int port, SceCtrlData* pad, float delta) { } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x503, PadBind_Defaults); + int port = Gamepad_Connect(0x503, defaults_psp); SceCtrlData pad; /* TODO implement */ diff --git a/src/psvita/Window_PSVita.c b/src/psvita/Window_PSVita.c index eb4d09c05..4648ddfb2 100644 --- a/src/psvita/Window_PSVita.c +++ b/src/psvita/Window_PSVita.c @@ -141,21 +141,21 @@ void Window_DisableRawMouse(void) { Input.RawMode = false; } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ -static const BindMapping vita_padbinds[BIND_COUNT] = { - [BIND_JUMP] = { CCPAD_1 }, - [BIND_SET_SPAWN] = { CCPAD_START }, - [BIND_CHAT] = { CCPAD_4 }, - [BIND_INVENTORY] = { CCPAD_3 }, - [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_SPEED] = { CCPAD_2, CCPAD_L }, - [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, - [BIND_FLY] = { CCPAD_2, CCPAD_R }, - [BIND_PLACE_BLOCK] = { CCPAD_L }, - [BIND_DELETE_BLOCK] = { CCPAD_R }, - [BIND_FLY_UP] = { CCPAD_UP }, - [BIND_FLY_DOWN] = { CCPAD_DOWN }, - [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, +static const BindMapping defaults_vita[BIND_COUNT] = { + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_FLY_UP] = { CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_LEFT }, [BIND_HOTBAR_RIGHT] = { CCPAD_RIGHT }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, }; static cc_bool circle_main; @@ -207,7 +207,7 @@ static void ProcessCircleInput(int port, int axis, int x, int y, float delta) { } static void ProcessPadInput(float delta) { - int port = Gamepad_Connect(0x503, vita_padbinds); + int port = Gamepad_Connect(0x503, defaults_vita); SceCtrlData pad; // sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that diff --git a/src/switch/Window_Switch.c b/src/switch/Window_Switch.c index 4521cb94a..63d52eeb1 100644 --- a/src/switch/Window_Switch.c +++ b/src/switch/Window_Switch.c @@ -147,6 +147,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_switch[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; } @@ -179,7 +200,7 @@ static void ProcessJoystickInput(int port, int axis, HidAnalogStickState* pos, f } void Gamepads_Process(float delta) { - int port = Gamepad_Connect(0x51C, PadBind_Defaults); + int port = Gamepad_Connect(0x51C, defaults_switch); u64 keys = padGetButtons(&pad); HandleButtons(port, keys); diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index 299f78970..fef5d7324 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -86,6 +86,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_xbox[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + static xid_dev_t* xid_ctrl; static xid_gamepad_in gp_state; @@ -184,7 +205,7 @@ void Gamepads_Process(float delta) { usbh_pooling_hubs(); #endif if (!xid_ctrl) return; - int port = Gamepad_Connect(0xB0, PadBind_Defaults); + int port = Gamepad_Connect(0xB0, defaults_xbox); HandleButtons(port, &gp_state); HandleJoystick(port, PAD_AXIS_LEFT, gp_state.leftStickX, gp_state.leftStickY, delta); diff --git a/src/xbox360/Window_Xbox360.c b/src/xbox360/Window_Xbox360.c index 71833c7b7..910c4977b 100644 --- a/src/xbox360/Window_Xbox360.c +++ b/src/xbox360/Window_Xbox360.c @@ -85,6 +85,27 @@ void Window_UpdateRawMouse(void) { } /*########################################################################################################################* *-------------------------------------------------------Gamepads----------------------------------------------------------* *#########################################################################################################################*/ +static const BindMapping defaults_xbox360[BIND_COUNT] = { + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_CHAT] = { CCPAD_4 }, + [BIND_INVENTORY] = { CCPAD_3 }, + [BIND_SEND_CHAT] = { CCPAD_START }, + [BIND_DELETE_BLOCK] = { CCPAD_L }, + [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_SPEED] = { CCPAD_2, CCPAD_L }, + [BIND_FLY] = { CCPAD_2, CCPAD_R }, + [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, + [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, + [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } +}; + void Gamepads_Init(void) { Input.Sources |= INPUT_SOURCE_GAMEPAD; @@ -131,7 +152,7 @@ static void HandleJoystick(int port, int axis, int x, int y, float delta) { void Gamepads_Process(float delta) { usb_do_poll(); - int port = Gamepad_Connect(0xB0360, PadBind_Defaults); + int port = Gamepad_Connect(0xB0360, defaults_xbox360); struct controller_data_s pad; int res = get_controller_data(&pad, 0); From 2b342b55bde655861d38df3960e4db9d7451b3ef Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 10 Sep 2025 22:02:29 +1000 Subject: [PATCH 082/115] PS2/Xbox/Xbox 360: Change L to place and R to delete for consistency with console editions NDS: B+L/R also move hotbar too --- src/nds/Window_NDS.c | 4 ++-- src/ps1/Window_PS1.c | 22 +++++++++++----------- src/ps2/Window_PS2.c | 4 ++-- src/ps3/Window_PS3.c | 4 ++-- src/xbox/Window_Xbox.c | 4 ++-- src/xbox360/Window_Xbox360.c | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/nds/Window_NDS.c b/src/nds/Window_NDS.c index a55f381e1..58d5e295b 100644 --- a/src/nds/Window_NDS.c +++ b/src/nds/Window_NDS.c @@ -272,8 +272,8 @@ static const BindMapping defaults_nds[BIND_COUNT] = { [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, - [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } + [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT } }; void Gamepads_Init(void) { diff --git a/src/ps1/Window_PS1.c b/src/ps1/Window_PS1.c index 71f69ab90..41952b1fc 100644 --- a/src/ps1/Window_PS1.c +++ b/src/ps1/Window_PS1.c @@ -142,22 +142,22 @@ static const BindMapping pad_defaults[BIND_COUNT] = { [BIND_LOOK_DOWN] = { CCPAD_4, CCPAD_DOWN }, [BIND_LOOK_LEFT] = { CCPAD_4, CCPAD_LEFT }, [BIND_LOOK_RIGHT] = { CCPAD_4, CCPAD_RIGHT }, - [BIND_FORWARD] = { CCPAD_UP, 0 }, - [BIND_BACK] = { CCPAD_DOWN, 0 }, - [BIND_LEFT] = { CCPAD_LEFT, 0 }, - [BIND_RIGHT] = { CCPAD_RIGHT, 0 }, - [BIND_JUMP] = { CCPAD_1, 0 }, - [BIND_SET_SPAWN] = { CCPAD_START, 0 }, - [BIND_INVENTORY] = { CCPAD_3, 0 }, + [BIND_FORWARD] = { CCPAD_UP }, + [BIND_BACK] = { CCPAD_DOWN }, + [BIND_LEFT] = { CCPAD_LEFT }, + [BIND_RIGHT] = { CCPAD_RIGHT }, + [BIND_JUMP] = { CCPAD_1 }, + [BIND_SET_SPAWN] = { CCPAD_START }, + [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_PLACE_BLOCK] = { CCPAD_L, 0 }, - [BIND_DELETE_BLOCK] = { CCPAD_R, 0 }, - [BIND_HOTBAR_LEFT] = { CCPAD_ZL, 0 }, - [BIND_HOTBAR_RIGHT] = { CCPAD_ZR, 0 } + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, + [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, + [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } }; static char pad_buff[2][34]; diff --git a/src/ps2/Window_PS2.c b/src/ps2/Window_PS2.c index 4bd1fe94d..990f0444d 100644 --- a/src/ps2/Window_PS2.c +++ b/src/ps2/Window_PS2.c @@ -237,8 +237,8 @@ static const BindMapping defaults_ps2[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/ps3/Window_PS3.c b/src/ps3/Window_PS3.c index e7de5ce1c..68078be90 100644 --- a/src/ps3/Window_PS3.c +++ b/src/ps3/Window_PS3.c @@ -281,8 +281,8 @@ static const BindMapping defaults_ps3[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index fef5d7324..038d31377 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -96,8 +96,8 @@ static const BindMapping defaults_xbox[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/xbox360/Window_Xbox360.c b/src/xbox360/Window_Xbox360.c index 910c4977b..75f1c4559 100644 --- a/src/xbox360/Window_Xbox360.c +++ b/src/xbox360/Window_Xbox360.c @@ -95,8 +95,8 @@ static const BindMapping defaults_xbox360[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, From 34ad75f2c9544fe8aa45c0e5165e651fc0a86e36 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 11 Sep 2025 06:36:03 +1000 Subject: [PATCH 083/115] Make L default to Place block control everywhere Switch: Also detect ZL/ZR --- src/3ds/Window_3DS.c | 4 ++-- src/dreamcast/Window_Dreamcast.c | 4 ++-- src/gcwii/Window_GCWii.c | 4 ++-- src/nds/Window_NDS.c | 4 ++-- src/psp/Window_PSP.c | 4 ++-- src/saturn/Window_Saturn.c | 4 ++-- src/switch/Window_Switch.c | 10 ++++++---- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/3ds/Window_3DS.c b/src/3ds/Window_3DS.c index 57ad19fb7..ff6bab4fb 100644 --- a/src/3ds/Window_3DS.c +++ b/src/3ds/Window_3DS.c @@ -138,8 +138,8 @@ static const BindMapping defaults_3ds[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/dreamcast/Window_Dreamcast.c b/src/dreamcast/Window_Dreamcast.c index 390d973e1..e62050ba3 100644 --- a/src/dreamcast/Window_Dreamcast.c +++ b/src/dreamcast/Window_Dreamcast.c @@ -232,8 +232,8 @@ static const BindMapping defaults_dc[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/gcwii/Window_GCWii.c b/src/gcwii/Window_GCWii.c index 74310224b..87556db8a 100644 --- a/src/gcwii/Window_GCWii.c +++ b/src/gcwii/Window_GCWii.c @@ -121,8 +121,8 @@ static const BindMapping defaults_gc[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/nds/Window_NDS.c b/src/nds/Window_NDS.c index 58d5e295b..32e49b3be 100644 --- a/src/nds/Window_NDS.c +++ b/src/nds/Window_NDS.c @@ -265,8 +265,8 @@ static const BindMapping defaults_nds[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/psp/Window_PSP.c b/src/psp/Window_PSP.c index 1f493824e..652503976 100644 --- a/src/psp/Window_PSP.c +++ b/src/psp/Window_PSP.c @@ -93,8 +93,8 @@ static const BindMapping defaults_psp[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, diff --git a/src/saturn/Window_Saturn.c b/src/saturn/Window_Saturn.c index c4ee28a94..c08a333f5 100644 --- a/src/saturn/Window_Saturn.c +++ b/src/saturn/Window_Saturn.c @@ -109,8 +109,8 @@ static const BindMapping saturn_defaults[BIND_COUNT] = { [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_DELETE_BLOCK] = { CCPAD_L, 0 }, - [BIND_PLACE_BLOCK] = { CCPAD_R, 0 } + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, }; void Gamepads_Init(void) { diff --git a/src/switch/Window_Switch.c b/src/switch/Window_Switch.c index 63d52eeb1..25e168f9b 100644 --- a/src/switch/Window_Switch.c +++ b/src/switch/Window_Switch.c @@ -157,8 +157,8 @@ static const BindMapping defaults_switch[BIND_COUNT] = { [BIND_CHAT] = { CCPAD_4 }, [BIND_INVENTORY] = { CCPAD_3 }, [BIND_SEND_CHAT] = { CCPAD_START }, - [BIND_DELETE_BLOCK] = { CCPAD_L }, - [BIND_PLACE_BLOCK] = { CCPAD_R }, + [BIND_PLACE_BLOCK] = { CCPAD_L }, + [BIND_DELETE_BLOCK] = { CCPAD_R }, [BIND_SPEED] = { CCPAD_2, CCPAD_L }, [BIND_FLY] = { CCPAD_2, CCPAD_R }, [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, @@ -173,8 +173,10 @@ void Gamepads_Init(void) { } static void HandleButtons(int port, u64 mods) { - Gamepad_SetButton(port, CCPAD_L, mods & HidNpadButton_L); - Gamepad_SetButton(port, CCPAD_R, mods & HidNpadButton_R); + Gamepad_SetButton(port, CCPAD_L, mods & HidNpadButton_L); + Gamepad_SetButton(port, CCPAD_R, mods & HidNpadButton_R); + Gamepad_SetButton(port, CCPAD_ZL, mods & HidNpadButton_ZL); + Gamepad_SetButton(port, CCPAD_ZR, mods & HidNpadButton_ZR); Gamepad_SetButton(port, CCPAD_1, mods & HidNpadButton_A); Gamepad_SetButton(port, CCPAD_2, mods & HidNpadButton_B); From 34c176600748003788a3f1df8c7bf8699e7f96fb Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 11 Sep 2025 20:45:08 +1000 Subject: [PATCH 084/115] Wii U: Less reliance on GX2R --- src/wiiu/Graphics_WiiU.c | 18 +++++++++++------- src/xbox/Window_Xbox.c | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/wiiu/Graphics_WiiU.c b/src/wiiu/Graphics_WiiU.c index 4f0da4e01..42006c299 100644 --- a/src/wiiu/Graphics_WiiU.c +++ b/src/wiiu/Graphics_WiiU.c @@ -372,7 +372,12 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { buf->elemSize = strideSizes[fmt]; buf->elemCount = count; - if (GX2RCreateBuffer(buf)) return buf; + // TODO calculate directly, avoid GX2R + uint32_t align = GX2RGetBufferAlignment(buf->flags); + uint32_t size = GX2RGetBufferAllocationSize(buf); + + buf->buffer = MEMAllocFromDefaultHeapEx(size, align); + if (buf->buffer) return buf; // Something went wrong ?? TODO Mem_Free(buf); return NULL; @@ -382,25 +387,24 @@ void Gfx_DeleteVb(GfxResourceID* vb) { GX2RBuffer* buf = *vb; if (!buf) return; - GX2RDestroyBufferEx(buf, 0); - Mem_Free(buf); + MEMFreeToDefaultHeap(buf->buffer); + Mem_Free(buf); *vb = NULL; } void Gfx_BindVb(GfxResourceID vb) { GX2RBuffer* buf = (GX2RBuffer*)vb; - GX2RSetAttributeBuffer(buf, 0, buf->elemSize, 0); - //GX2SetAttribBuffer(0, + GX2SetAttribBuffer(0, buf->elemSize * buf->elemCount, buf->elemSize, buf->buffer); } void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { GX2RBuffer* buf = (GX2RBuffer*)vb; - return GX2RLockBufferEx(buf, 0); + return buf->buffer; } void Gfx_UnlockVb(GfxResourceID vb) { GX2RBuffer* buf = (GX2RBuffer*)vb; - GX2RUnlockBufferEx(buf, 0); + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, buf->buffer, buf->elemSize * buf->elemCount); } diff --git a/src/xbox/Window_Xbox.c b/src/xbox/Window_Xbox.c index 038d31377..3018b961d 100644 --- a/src/xbox/Window_Xbox.c +++ b/src/xbox/Window_Xbox.c @@ -192,7 +192,7 @@ static void HandleButtons(int port, xid_gamepad_in* gp) { Gamepad_SetButton(port, CCPAD_DOWN, mods & XINPUT_GAMEPAD_DPAD_DOWN); } -#define AXIS_SCALE 8192.0f +#define AXIS_SCALE 4096.0f static void HandleJoystick(int port, int axis, int x, int y, float delta) { if (Math_AbsI(x) <= 6144) x = 0; if (Math_AbsI(y) <= 6144) y = 0; From 94768aa089ef7de960db6c248821bb4a7e5d063d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 12 Sep 2025 21:54:43 +1000 Subject: [PATCH 085/115] 3DS: Make vertex shaders slightly more efficient (save one instruction, share uniforms across programs) --- misc/3ds/coloured.v.pica | 25 +++--- misc/3ds/offset.v.pica | 28 +++--- misc/3ds/textured.v.pica | 25 +++--- src/3ds/Graphics_3DS.c | 61 ++++++------- src/3ds/pica_gpu.h | 13 +++ third_party/citro3d.c | 181 --------------------------------------- 6 files changed, 77 insertions(+), 256 deletions(-) create mode 100644 src/3ds/pica_gpu.h diff --git a/misc/3ds/coloured.v.pica b/misc/3ds/coloured.v.pica index d0b374ddf..44e4a3202 100644 --- a/misc/3ds/coloured.v.pica +++ b/misc/3ds/coloured.v.pica @@ -1,11 +1,15 @@ ; Vertex shader for rendering coloured vertices for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -16,14 +20,11 @@ .alias in_col v1 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col diff --git a/misc/3ds/offset.v.pica b/misc/3ds/offset.v.pica index 948143c2f..a42afe5ba 100644 --- a/misc/3ds/offset.v.pica +++ b/misc/3ds/offset.v.pica @@ -1,12 +1,15 @@ ; Vertex shader for rendering textured vertices with an offset for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; -.fvec tex_offset; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -19,19 +22,16 @@ .alias in_tex v2 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col ; out_tex = in_tex + tex_offset - add out_tex, tex_offset, in_tex + add out_tex, TEX_OFFSET, in_tex end .end diff --git a/misc/3ds/textured.v.pica b/misc/3ds/textured.v.pica index 66aa92791..d398f2a15 100644 --- a/misc/3ds/textured.v.pica +++ b/misc/3ds/textured.v.pica @@ -1,11 +1,15 @@ ; Vertex shader for rendering textured vertices for PICA200 GPU on the Nintendo 3DS ; ================================================================================== -; Uniforms -.fvec MVP[4]; +; Uniforms (layout common to all shaders) +.alias MVP_0 c0 +.alias MVP_1 c1 +.alias MVP_2 c2 +.alias MVP_3 c3 +.alias TEX_OFFSET c4 -; Constants -.constf ONE_DIV_255(0.003921568627, 0.003921568627, 0.003921568627, 0.003921568627) +; Constants (initialised in Graphics_3DS.c) +.alias ONE_DIV_255 c5 ; Outputs .out out_pos position @@ -18,14 +22,11 @@ .alias in_tex v2 .proc main - ; r0 = in_pos - mov r0, in_pos - - ; out_pos = MVP * r0 - dp4 out_pos.x, MVP[0], r0 - dp4 out_pos.y, MVP[1], r0 - dp4 out_pos.z, MVP[2], r0 - dp4 out_pos.w, MVP[3], r0 + ; out_pos = MVP * in_pos + dp4 out_pos.x, MVP_0, in_pos + dp4 out_pos.y, MVP_1, in_pos + dp4 out_pos.z, MVP_2, in_pos + dp4 out_pos.w, MVP_3, in_pos ; out_col = in_col * ONE_DIV_255 mul out_col, ONE_DIV_255, in_col diff --git a/src/3ds/Graphics_3DS.c b/src/3ds/Graphics_3DS.c index 3db6521dd..3cdc4c344 100644 --- a/src/3ds/Graphics_3DS.c +++ b/src/3ds/Graphics_3DS.c @@ -7,6 +7,12 @@ #define BUFFER_BASE_PADDR OS_VRAM_PADDR // VRAM physical address #include "../../third_party/citro3d.c" +#include "pica_gpu.h" +// See the .v.pica shader files in misc/3ds +#define CONST_MVP 0 // c0-c3 +#define CONST_TEX 4 // c4 +#define CONST_255 5 // c5 + // autogenerated from the .v.pica files by Makefile extern const u8 coloured_shbin[]; extern const u32 coloured_shbin_size; @@ -33,17 +39,12 @@ static cc_bool rendering3D; *------------------------------------------------------Vertex shaders-----------------------------------------------------* *#########################################################################################################################*/ #define UNI_MVP_MATRIX (1 << 0) -#define UNI_TEX_OFFSETS (1 << 1) -// cached uniforms (cached for multiple programs) static C3D_Mtx _mvp; -static float texOffsetX, texOffsetY; -static int texOffset; +static int texOffset, dirty_mvp; struct CCShader { DVLB_s* dvlb; shaderProgram_s program; - int uniforms; // which associated uniforms need to be resent to GPU - int locations[2]; // location of uniforms (not constant) }; static struct CCShader* gfx_activeShader; static struct CCShader shaders[3]; @@ -52,9 +53,6 @@ static void Shader_Alloc(struct CCShader* shader, const u8* binData, int binSize shader->dvlb = DVLB_ParseFile((u32*)binData, binSize); shaderProgramInit(&shader->program); shaderProgramSetVsh(&shader->program, &shader->dvlb->DVLE[0]); - - shader->locations[0] = shaderInstanceGetUniformLocation(shader->program.vertexShader, "MVP"); - shader->locations[1] = shaderInstanceGetUniformLocation(shader->program.vertexShader, "tex_offset"); } static void Shader_Free(struct CCShader* shader) { @@ -62,28 +60,14 @@ static void Shader_Free(struct CCShader* shader) { DVLB_Free(shader->dvlb); } -// Marks a uniform as changed on all programs -static void DirtyUniform(int uniform) { - for (int i = 0; i < Array_Elems(shaders); i++) - { - shaders[i].uniforms |= uniform; - } -} - -// Sends changed uniforms to the GPU for current program -static void ReloadUniforms(void) { +static void UpdateMVP(void) { struct CCShader* s = gfx_activeShader; + dirty_mvp = true; if (!s) return; // NULL if context is lost - if (s->uniforms & UNI_MVP_MATRIX) { - C3D_FVUnifMtx4x4(s->locations[0], &_mvp); - s->uniforms &= ~UNI_MVP_MATRIX; - } - - if (s->uniforms & UNI_TEX_OFFSETS) { - C3D_FVUnifSet(s->locations[1], - texOffsetX, texOffsetY, 0.0f, 0.0f); - s->uniforms &= ~UNI_TEX_OFFSETS; + if (dirty_mvp) { + pica_upload_mat4_constant(CONST_MVP, &_mvp); + dirty_mvp = false; } } @@ -101,7 +85,7 @@ static void SwitchProgram(void) { gfx_activeShader = shader; C3D_BindProgram(&shader->program); } - ReloadUniforms(); + UpdateMVP(); } @@ -571,6 +555,9 @@ void Gfx_BeginFrame(void) { extern void C3Di_UpdateContext(void); C3Di_UpdateContext(); + + static C3D_FVec _1_div_255 = { .x = 1/255.0f, .y = 1/255.0f, .z = 1/255.0f, .w = 1/255.0f }; + pica_upload_vec4_constant(CONST_255, &_1_div_255); } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -860,8 +847,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { } Mtx_Multiply(&_mvp, &_proj, &_view); - DirtyUniform(UNI_MVP_MATRIX); - ReloadUniforms(); + UpdateMVP(); } @@ -882,9 +868,8 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { Matrix_Mul(&_proj, matrix, &rot); // TODO avoid Matrix_Mul ? } + Mtx_Multiply(&_mvp, &_proj, &_view); UpdateMVP(); - DirtyUniform(UNI_MVP_MATRIX); - ReloadUniforms(); }*/ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { @@ -893,14 +878,16 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma Matrix_Mul(mvp, view, proj); } +static C3D_FVec tex_offset; void Gfx_EnableTextureOffset(float x, float y) { - texOffset = true; - texOffsetX = x; - texOffsetY = y; + texOffset = true; + tex_offset.x = x; + tex_offset.y = y; - shaders[2].uniforms |= UNI_TEX_OFFSETS; SwitchProgram(); + pica_upload_vec4_constant(CONST_TEX, &tex_offset); } + void Gfx_DisableTextureOffset(void) { texOffset = false; SwitchProgram(); diff --git a/src/3ds/pica_gpu.h b/src/3ds/pica_gpu.h new file mode 100644 index 000000000..c515243b8 --- /dev/null +++ b/src/3ds/pica_gpu.h @@ -0,0 +1,13 @@ +// https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_INDEX +// https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_DATAi +#define UPLOAD_TYPE_F32 0x80000000 + +static CC_INLINE void pica_upload_mat4_constant(int offset, C3D_Mtx* value) { + GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, offset | UPLOAD_TYPE_F32); + GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)value, 16); +} + +static CC_INLINE void pica_upload_vec4_constant(int offset, C3D_FVec* value) { + GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, offset | UPLOAD_TYPE_F32); + GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)value, 4); +} diff --git a/third_party/citro3d.c b/third_party/citro3d.c index d81d3a550..dd663b678 100644 --- a/third_party/citro3d.c +++ b/third_party/citro3d.c @@ -316,51 +316,6 @@ void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b) } - - -#define C3D_FVUNIF_COUNT 96 -#define C3D_IVUNIF_COUNT 4 - -static C3D_FVec C3D_FVUnif[C3D_FVUNIF_COUNT]; -static C3D_IVec C3D_IVUnif[C3D_IVUNIF_COUNT]; -static u16 C3D_BoolUnifs; - -static bool C3D_FVUnifDirty[C3D_FVUNIF_COUNT]; -static bool C3D_IVUnifDirty[C3D_IVUNIF_COUNT]; -static bool C3D_BoolUnifsDirty; - -static inline C3D_FVec* C3D_FVUnifWritePtr(int id, int size) -{ - int i; - for (i = 0; i < size; i ++) - C3D_FVUnifDirty[id+i] = true; - return &C3D_FVUnif[id]; -} - -static inline void C3D_FVUnifMtx4x4(int id, const C3D_Mtx* mtx) -{ - int i; - C3D_FVec* ptr = C3D_FVUnifWritePtr(id, 4); - for (i = 0; i < 4; i ++) - ptr[i] = mtx->r[i]; // Struct copy. -} - -static inline void C3D_FVUnifSet(int id, float x, float y, float z, float w) -{ - C3D_FVec* ptr = C3D_FVUnifWritePtr(id, 1); - ptr->x = x; - ptr->y = y; - ptr->z = z; - ptr->w = w; -} - -static void C3D_UpdateUniforms(void); - - - - - - typedef struct { u32 fragOpMode; @@ -452,10 +407,6 @@ static void C3Di_TexEnvBind(int id, C3D_TexEnv* env); static void C3Di_SetTex(int unit, C3D_Tex* tex); static void C3Di_EffectBind(C3D_Effect* effect); -static void C3Di_DirtyUniforms(void); -static void C3Di_LoadShaderUniforms(shaderInstance_s* si); -static void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type); - static bool C3Di_SplitFrame(u32** pBuf, u32* pSize); static void C3Di_RenderQueueInit(void); @@ -1180,132 +1131,6 @@ static void C3Di_SetTex(int unit, C3D_Tex* tex) } } - - - - - - - -static struct -{ - bool dirty; - int count; - float24Uniform_s* data; -} C3Di_ShaderFVecData; - -static bool C3Di_FVUnifEverDirty[C3D_FVUNIF_COUNT]; -static bool C3Di_IVUnifEverDirty[C3D_IVUNIF_COUNT]; - -static void C3D_UpdateUniforms(void) -{ - int i = 0; - - // Update FVec uniforms that come from shader constants - if (C3Di_ShaderFVecData.dirty) - { - while (i < C3Di_ShaderFVecData.count) - { - float24Uniform_s* u = &C3Di_ShaderFVecData.data[i++]; - GPUCMD_AddIncrementalWrites(GPUREG_VSH_FLOATUNIFORM_CONFIG, (u32*)u, 4); - C3D_FVUnifDirty[u->id] = false; - } - C3Di_ShaderFVecData.dirty = false; - i = 0; - } - - // Update FVec uniforms - while (i < C3D_FVUNIF_COUNT) - { - if (!C3D_FVUnifDirty[i]) - { - i ++; - continue; - } - - // Find the number of consecutive dirty uniforms - int j; - for (j = i; j < C3D_FVUNIF_COUNT && C3D_FVUnifDirty[j]; j ++); - - // Upload the uniforms - GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG, 0x80000000|i); - GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA, (u32*)&C3D_FVUnif[i], (j-i)*4); - - // Clear the dirty flag - int k; - for (k = i; k < j; k ++) - { - C3D_FVUnifDirty[k] = false; - C3Di_FVUnifEverDirty[k] = true; - } - - // Advance - i = j; - } - - // Update IVec uniforms - for (i = 0; i < C3D_IVUNIF_COUNT; i ++) - { - if (!C3D_IVUnifDirty[i]) continue; - - GPUCMD_AddWrite(GPUREG_VSH_INTUNIFORM_I0+i, C3D_IVUnif[i]); - C3D_IVUnifDirty[i] = false; - C3Di_IVUnifEverDirty[i] = false; - } - - // Update bool uniforms - if (C3D_BoolUnifsDirty) - { - GPUCMD_AddWrite(GPUREG_VSH_BOOLUNIFORM, 0x7FFF0000 | C3D_BoolUnifs); - C3D_BoolUnifsDirty = false; - } -} - -static void C3Di_DirtyUniforms(void) -{ - int i; - C3D_BoolUnifsDirty = true; - if (C3Di_ShaderFVecData.count) - C3Di_ShaderFVecData.dirty = true; - for (i = 0; i < C3D_FVUNIF_COUNT; i ++) - C3D_FVUnifDirty[i] = C3D_FVUnifDirty[i] || C3Di_FVUnifEverDirty[i]; - for (i = 0; i < C3D_IVUNIF_COUNT; i ++) - C3D_IVUnifDirty[i] = C3D_IVUnifDirty[i] || C3Di_IVUnifEverDirty[i]; -} - -static void C3Di_LoadShaderUniforms(shaderInstance_s* si) -{ - if (si->boolUniformMask) - { - C3D_BoolUnifs &= ~si->boolUniformMask; - C3D_BoolUnifs |= si->boolUniforms; - } - - C3D_BoolUnifsDirty = true; - - if (si->intUniformMask) - { - int i; - for (i = 0; i < 4; i ++) - { - if (si->intUniformMask & BIT(i)) - { - C3D_IVUnif[i] = si->intUniforms[i]; - C3D_IVUnifDirty[i] = true; - } - } - } - C3Di_ShaderFVecData.dirty = true; - C3Di_ShaderFVecData.count = si->numFloat24Uniforms; - C3Di_ShaderFVecData.data = si->float24Uniforms; -} - - - - - - - static void C3Di_OnRestore(void) { C3D_Context* ctx = C3Di_GetContext(); @@ -1314,8 +1139,6 @@ static void C3Di_OnRestore(void) | C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode | C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_Gas | C3DiF_Reset; - C3Di_DirtyUniforms(); - if (ctx->fogLut) ctx->flags |= C3DiF_FogLut; } @@ -1520,8 +1343,6 @@ static void C3Di_UpdateContext(void) GPUCMD_AddWrites(GPUREG_FOG_LUT_DATA0, ctx->fogLut->data, 128); } } - - C3D_UpdateUniforms(); } static bool C3Di_SplitFrame(u32** pBuf, u32* pSize) @@ -1577,6 +1398,4 @@ static void C3D_BindProgram(shaderProgram_s* program) ctx->flags |= C3DiF_VshCode | C3DiF_GshCode; } } - - C3Di_LoadShaderUniforms(program->vertexShader); } From 4003ff7d6bcfc88fb02d4375e4edda8e5cfee4a4 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 13 Sep 2025 08:18:52 +1000 Subject: [PATCH 086/115] 3DS: Send less commands per draw --- src/3ds/Graphics_3DS.c | 49 +++++++++++++++++++----------------------- src/3ds/pica_gpu.h | 20 +++++++++++++++++ third_party/citro3d.c | 10 --------- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/3ds/Graphics_3DS.c b/src/3ds/Graphics_3DS.c index 3cdc4c344..7ee615318 100644 --- a/src/3ds/Graphics_3DS.c +++ b/src/3ds/Graphics_3DS.c @@ -558,6 +558,14 @@ void Gfx_BeginFrame(void) { static C3D_FVec _1_div_255 = { .x = 1/255.0f, .y = 1/255.0f, .z = 1/255.0f, .w = 1/255.0f }; pica_upload_vec4_constant(CONST_255, &_1_div_255); + + // NOTE: GPUREG_VERTEX_OFFSET only works when drawing non-indexed arrays + GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0); + + // https://github.com/devkitPro/citro3d/issues/47 + // "Fyi the permutation specifies the order in which the attributes are stored in the buffer, LSB first. So 0x210 indicates attributes 0, 1 & 2." + // This just maps array attrib 0 = vertex attrib 0, array attrib 1 = vertex attrib 1, etc + pica_set_attrib_array0_mapping(0x210); } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -901,17 +909,25 @@ void Gfx_DisableTextureOffset(void) { cc_bool Gfx_WarnIfNecessary(void) { return false; } cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } -static void UpdateAttribFormat(VertexFormat fmt) { +static void UpdateAttribFormat(void) { C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // in_pos AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4); // in_col - if (fmt == VERTEX_FORMAT_TEXTURED) { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { AttrInfo_AddLoader(attrInfo, 2, GPU_FLOAT, 2); // in_tex } } +static void UpdateAttribConfig(void) { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + pica_set_attrib_array0_format(3, SIZEOF_VERTEX_TEXTURED); + } else { + pica_set_attrib_array0_format(2, SIZEOF_VERTEX_COLOURED); + } +} + static void UpdateTexEnv(VertexFormat fmt) { int func, source; @@ -938,7 +954,8 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_stride = strideSizes[fmt]; SwitchProgram(); - UpdateAttribFormat(fmt); + UpdateAttribFormat(); + UpdateAttribConfig(); UpdateTexEnv(fmt); } @@ -947,32 +964,10 @@ void Gfx_DrawVb_Lines(int verticesCount) { } static void SetVertexSource(int startVertex) { - // https://github.com/devkitPro/citro3d/issues/47 - // "Fyi the permutation specifies the order in which the attributes are stored in the buffer, LSB first. So 0x210 indicates attributes 0, 1 & 2." - const void* data; - int stride, attribs, permutation; - - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - data = (struct VertexTextured*)gfx_vertices + startVertex; - stride = SIZEOF_VERTEX_TEXTURED; - attribs = 3; - permutation = 0x210; - } else { - data = (struct VertexColoured*)gfx_vertices + startVertex; - stride = SIZEOF_VERTEX_COLOURED; - attribs = 2; - permutation = 0x10; - } + const void* data = (cc_uint8*)gfx_vertices + startVertex * gfx_stride; u32 pa = osConvertVirtToPhys(data); - u32 args[3]; // GPUREG_ATTRIBBUFFER0_OFFSET, GPUREG_ATTRIBBUFFER0_CONFIG1, GPUREG_ATTRIBBUFFER0_CONFIG2 - - args[0] = pa - BUFFER_BASE_PADDR; - args[1] = permutation; - args[2] = (stride << 16) | (attribs << 28); - - GPUCMD_AddIncrementalWrites(GPUREG_ATTRIBBUFFER0_OFFSET, args, 3); - // NOTE: Can't use GPUREG_VERTEX_OFFSET, it only works when drawing non-indexed arrays + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_OFFSET, pa - BUFFER_BASE_PADDR); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { diff --git a/src/3ds/pica_gpu.h b/src/3ds/pica_gpu.h index c515243b8..5a8c4b56c 100644 --- a/src/3ds/pica_gpu.h +++ b/src/3ds/pica_gpu.h @@ -1,3 +1,23 @@ +/*########################################################################################################################* +*--------------------------------------------------Vertex attribute config------------------------------------------------* +*#########################################################################################################################*/ + +// https://3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_ATTRIBBUFFERi_CONFIG1 +// Sets how to map first 8 vertex array components to vertex attributes (or padding) +static CC_INLINE void pica_set_attrib_array0_mapping(u32 mapping) { + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG1, mapping); +} + +// https://3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_ATTRIBBUFFERi_CONFIG2 +// Sets how to map last 4 vertex array components to vertex attributes, bytes per vertex, components count +static CC_INLINE void pica_set_attrib_array0_format(u32 num_attribs, u32 stride) { + GPUCMD_AddWrite(GPUREG_ATTRIBBUFFER0_CONFIG2, (stride << 16) | (num_attribs << 28)); +} + + +/*########################################################################################################################* +*--------------------------------------------------Vertex shader constants------------------------------------------------* +*#########################################################################################################################*/ // https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_INDEX // https://www.3dbrew.org/wiki/GPU/Internal_Registers#GPUREG_SH_FLOATUNIFORM_DATAi #define UPLOAD_TYPE_F32 0x80000000 diff --git a/third_party/citro3d.c b/third_party/citro3d.c index dd663b678..4d615d8ca 100644 --- a/third_party/citro3d.c +++ b/third_party/citro3d.c @@ -140,14 +140,6 @@ static void C3D_ImmDrawBegin(GPU_Primitive_t primitive); static void C3D_ImmSendAttrib(float x, float y, float z, float w); static void C3D_ImmDrawEnd(void); -static inline void C3D_ImmDrawRestartPrim(void) -{ - GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1); -} - - - - typedef struct { @@ -484,8 +476,6 @@ static void C3D_DrawElements(GPU_Primitive_t primitive, int count) GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1); // Number of vertices GPUCMD_AddWrite(GPUREG_NUMVERTICES, count); - // First vertex - GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0); // Enable triangle element drawing mode if necessary GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG, 2, 0x100); GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 2, 0x100); From d437434cf923e0679f44dac913b0b86a55fe7205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BF=E3=81=8B=E3=81=BF=E3=81=8B=E3=82=93?= <151894646+oorange32@users.noreply.github.com> Date: Sun, 14 Sep 2025 00:18:21 +0900 Subject: [PATCH 087/115] Add files via upload a new software renderer using fixed-point arithmetic for devices without an FPU --- src/Core.h | 1 + src/Graphics_SoftFP.c | 1146 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1147 insertions(+) create mode 100644 src/Graphics_SoftFP.c diff --git a/src/Core.h b/src/Core.h index 4e5226f3f..4ee2d6b48 100644 --- a/src/Core.h +++ b/src/Core.h @@ -147,6 +147,7 @@ typedef cc_uint8 cc_bool; #define CC_GFX_BACKEND_VULKAN 6 #define CC_GFX_BACKEND_GL11 7 #define CC_GFX_BACKEND_SOFTMIN 8 +#define CC_GFX_BACKEND_SOFTFP 9 #define CC_SSL_BACKEND_NONE 1 #define CC_SSL_BACKEND_BEARSSL 2 diff --git a/src/Graphics_SoftFP.c b/src/Graphics_SoftFP.c new file mode 100644 index 000000000..dcbf14211 --- /dev/null +++ b/src/Graphics_SoftFP.c @@ -0,0 +1,1146 @@ +#include "Core.h" +#if CC_GFX_BACKEND == CC_GFX_BACKEND_SOFTFP +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" +#include +#include + +// 16.16 fixed point +#define FP_SHIFT 16 +#define FP_ONE (1 << FP_SHIFT) +#define FP_HALF (FP_ONE >> 1) +#define FP_MASK ((1 << FP_SHIFT) - 1) + +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +#define FloatToFixed(x) ((int)((x) * FP_ONE)) +#define FixedToFloat(x) ((float)(x) / FP_ONE) +#define FixedToInt(x) ((x) >> FP_SHIFT) +#define IntToFixed(x) ((x) << FP_SHIFT) + +#define FixedMul(a, b) (((int64_t)(a) * (b)) >> FP_SHIFT) + +#define FixedDiv(a, b) (((int64_t)(a) << FP_SHIFT) / (b)) + +static int FixedReciprocal(int x) { + if (x == 0) return 0; + int64_t res = ((int64_t)FP_ONE << FP_SHIFT) / (int64_t)x; // (1<<32)/x -> fixed reciprocal + if (res > INT_MAX) return INT_MAX; + if (res < INT_MIN) return INT_MIN; + return (int)res; +} + +static cc_bool faceCulling; +static int fb_width, fb_height; +static struct Bitmap fb_bmp; +static int vp_hwidth_fp, vp_hheight_fp; +static int fb_maxX, fb_maxY; + +static BitmapCol* colorBuffer; +static BitmapCol clearColor; +static cc_bool colWrite = true; +static int cb_stride; + +static int* depthBuffer; +static cc_bool depthTest = true; +static cc_bool depthWrite = true; +static int db_stride; + +static void* gfx_vertices; +static GfxResourceID white_square; + +typedef struct FixedMatrix { + int m[4][4]; +} FixedMatrix; + +typedef struct VertexFixed { + int x, y, z, w; + int u, v; + PackedCol c; +} VertexFixed; + +static int texOffsetX_fp, texOffsetY_fp; // Fixed point texture offsets +static FixedMatrix _view_fp, _proj_fp, _mvp_fp; + +static void Gfx_RestoreState(void) { + InitDefaultResources(); + + struct Bitmap bmp; + BitmapCol pixels[1] = { BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 1, 1, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +static void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + Gfx.MaxTexWidth = 4096; + Gfx.MaxTexHeight = 4096; + Gfx.Created = true; + Gfx.BackendType = CC_GFX_BACKEND_SOFTGPU; + Gfx.Limitations = GFX_LIMIT_MINIMAL; + + Gfx_RestoreState(); +} + +static void DestroyBuffers(void) { + Window_FreeFramebuffer(&fb_bmp); + Mem_Free(depthBuffer); + depthBuffer = NULL; +} + +void Gfx_Free(void) { + Gfx_FreeState(); + DestroyBuffers(); +} + +typedef struct CCTexture { + int width, height; + BitmapCol pixels[]; +} CCTexture; + +static CCTexture* curTexture; +static BitmapCol* curTexPixels; +static int curTexWidth, curTexHeight; +static int texWidthMask, texHeightMask; +static int texSinglePixel; + +void Gfx_BindTexture(GfxResourceID texId) { + if (!texId) texId = white_square; + CCTexture* tex = texId; + + curTexture = tex; + curTexPixels = tex->pixels; + curTexWidth = tex->width; + curTexHeight = tex->height; + + texWidthMask = (1 << Math_ilog2(tex->width)) - 1; + texHeightMask = (1 << Math_ilog2(tex->height)) - 1; + + texSinglePixel = curTexWidth == 1; +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { + GfxResourceID data = *texId; + if (data) Mem_Free(data); + *texId = NULL; +} + +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)Mem_Alloc(2 + bmp->width * bmp->height, 4, "Texture"); + + tex->width = bmp->width; + tex->height = bmp->height; + + CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, + bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, + bmp->width, bmp->height); + return tex; +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + CCTexture* tex = (CCTexture*)texId; + BitmapCol* dst = (tex->pixels + x) + y * tex->width; + + CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, + part->scan0, rowWidth * BITMAPCOLOR_SIZE, + part->width, part->height); +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + faceCulling = enabled; +} + +static void SetAlphaTest(cc_bool enabled) { +} + +static void SetAlphaBlend(cc_bool enabled) { +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +static void ClearColorBuffer(void) { + int i, x, y, size = fb_width * fb_height; + + if (cb_stride == fb_width) { + //for (i = 0; i < size; i++) colorBuffer[i] = clearColor; + Mem_Set(colorBuffer, clearColor, sizeof(colorBuffer) * size); + } else { + for (y = 0; y < fb_height; y++) { + i = y * cb_stride; + for (x = 0; x < fb_width; x++) { + colorBuffer[i + x] = clearColor; + } + } + } +} + +static void ClearDepthBuffer(void) { + int i, size = fb_width * fb_height; + int maxDepth = 0x7FFFFFFF; // max depth + for (i = 0; i < size; i++) depthBuffer[i] = maxDepth; +} + +void Gfx_ClearBuffers(GfxBuffers buffers) { + if (buffers & GFX_BUFFER_COLOR) ClearColorBuffer(); + if (buffers & GFX_BUFFER_DEPTH) ClearDepthBuffer(); +} + +void Gfx_ClearColor(PackedCol color) { + int R = PackedCol_R(color); + int G = PackedCol_G(color); + int B = PackedCol_B(color); + int A = PackedCol_A(color); + + clearColor = BitmapCol_Make(R, G, B, A); +} + +void Gfx_SetDepthTest(cc_bool enabled) { + depthTest = enabled; +} + +void Gfx_SetDepthWrite(cc_bool enabled) { + depthWrite = enabled; +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + colWrite = !depthOnly; +} + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ + +static void MatrixToFixed(FixedMatrix* dst, const struct Matrix* src) { + dst->m[0][0] = FloatToFixed(src->row1.x); dst->m[0][1] = FloatToFixed(src->row1.y); + dst->m[0][2] = FloatToFixed(src->row1.z); dst->m[0][3] = FloatToFixed(src->row1.w); + + dst->m[1][0] = FloatToFixed(src->row2.x); dst->m[1][1] = FloatToFixed(src->row2.y); + dst->m[1][2] = FloatToFixed(src->row2.z); dst->m[1][3] = FloatToFixed(src->row2.w); + + dst->m[2][0] = FloatToFixed(src->row3.x); dst->m[2][1] = FloatToFixed(src->row3.y); + dst->m[2][2] = FloatToFixed(src->row3.z); dst->m[2][3] = FloatToFixed(src->row3.w); + + dst->m[3][0] = FloatToFixed(src->row4.x); dst->m[3][1] = FloatToFixed(src->row4.y); + dst->m[3][2] = FloatToFixed(src->row4.z); dst->m[3][3] = FloatToFixed(src->row4.w); +} + +static void MatrixMulFixed(FixedMatrix* dst, const FixedMatrix* a, const FixedMatrix* b) { + int i, j, k; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + int64_t sum = 0; + for (k = 0; k < 4; k++) { + sum += (int64_t)a->m[i][k] * b->m[k][j]; + } + dst->m[i][j] = (int)(sum >> FP_SHIFT); + } + } +} + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) { + MatrixToFixed(&_view_fp, matrix); + } + if (type == MATRIX_PROJ) { + MatrixToFixed(&_proj_fp, matrix); + } + + MatrixMulFixed(&_mvp_fp, &_view_fp, &_proj_fp); +} + +void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { + MatrixToFixed(&_view_fp, view); + MatrixToFixed(&_proj_fp, proj); + + MatrixMulFixed(&_mvp_fp, &_view_fp, &_proj_fp); + + Matrix_Mul(mvp, view, proj); +} + +void Gfx_EnableTextureOffset(float x, float y) { + texOffsetX_fp = FloatToFixed(x); + texOffsetY_fp = FloatToFixed(y); +} + +void Gfx_DisableTextureOffset(void) { + texOffsetX_fp = 0; + texOffsetY_fp = 0; +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } + +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.1f; + + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ + +enum { PLANE_LEFT=0, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + +static int PlaneDistFixed(const VertexFixed* v, int plane) { + int64_t result; + switch (plane) { + case PLANE_LEFT: + result = (int64_t)v->x + v->w; + break; + case PLANE_RIGHT: + result = (int64_t)v->w - v->x; + break; + case PLANE_BOTTOM: + result = (int64_t)v->y + v->w; + break; + case PLANE_TOP: + result = (int64_t)v->w - v->y; + break; + case PLANE_NEAR: + result = v->z; + break; + case PLANE_FAR: + result = (int64_t)v->w - (v->z >> 2); //hacked + break; + default: + return 0; + } + + // Clamp to valid range + if (result > INT_MAX) return INT_MAX; + if (result < INT_MIN) return INT_MIN; + return (int)result; +} + +static void LerpClipFixed(VertexFixed* out, const VertexFixed* a, const VertexFixed* b, int t) { + if (t < 0) t = 0; + if (t > FP_ONE) t = FP_ONE; + + int invt = FP_ONE - t; + + int64_t x_interp = ((int64_t)invt * a->x + (int64_t)t * b->x) >> FP_SHIFT; + int64_t y_interp = ((int64_t)invt * a->y + (int64_t)t * b->y) >> FP_SHIFT; + int64_t z_interp = ((int64_t)invt * a->z + (int64_t)t * b->z) >> FP_SHIFT; + int64_t w_interp = ((int64_t)invt * a->w + (int64_t)t * b->w) >> FP_SHIFT; + int64_t u_interp = ((int64_t)invt * a->u + (int64_t)t * b->u) >> FP_SHIFT; + int64_t v_interp = ((int64_t)invt * a->v + (int64_t)t * b->v) >> FP_SHIFT; + + // Clamp results + out->x = (x_interp > INT_MAX) ? INT_MAX : (x_interp < INT_MIN) ? INT_MIN : (int)x_interp; + out->y = (y_interp > INT_MAX) ? INT_MAX : (y_interp < INT_MIN) ? INT_MIN : (int)y_interp; + out->z = (z_interp > INT_MAX) ? INT_MAX : (z_interp < INT_MIN) ? INT_MIN : (int)z_interp; + out->w = (w_interp > INT_MAX) ? INT_MAX : (w_interp < INT_MIN) ? INT_MIN : (int)w_interp; + out->u = (u_interp > INT_MAX) ? INT_MAX : (u_interp < INT_MIN) ? INT_MIN : (int)u_interp; + out->v = (v_interp > INT_MAX) ? INT_MAX : (v_interp < INT_MIN) ? INT_MIN : (int)v_interp; + + out->c = (t < FP_HALF) ? a->c : b->c; +} + +static int SafeFixedDiv(int numerator, int denominator) { + if (denominator == 0) return FP_HALF; + if (ABS(denominator) < 16) return FP_HALF; // Avoid extreme divisions + + int64_t result = ((int64_t)numerator << FP_SHIFT) / denominator; + + if (result > FP_ONE) return FP_ONE; + if (result < 0) return 0; + return (int)result; +} + +static int ClipPolygonPlaneFixed(const VertexFixed* in, int inCount, VertexFixed* out, int plane) { + if (inCount == 0) return 0; + if (inCount > 15) inCount = 15; // Safety limit + + int outCount = 0; + + for (int i = 0; i < inCount; i++) { + const VertexFixed* cur = &in[i]; + const VertexFixed* next = &in[(i + 1) % inCount]; + + int dCur = PlaneDistFixed(cur, plane); + int dNext = PlaneDistFixed(next, plane); + cc_bool curIn = dCur >= 0; + cc_bool nextIn = dNext >= 0; + + if (curIn && nextIn) { + // Both inside + out[outCount++] = *next; + } else if (curIn && !nextIn) { + // Exiting + int denom = dCur - dNext; + int t = SafeFixedDiv(dCur, denom); + + VertexFixed intersection; + LerpClipFixed(&intersection, cur, next, t); + out[outCount++] = intersection; + } else if (!curIn && nextIn) { + // Entering + int denom = dCur - dNext; + int t = SafeFixedDiv(dCur, denom); + + VertexFixed intersection; + LerpClipFixed(&intersection, cur, next, t); + out[outCount++] = intersection; + out[outCount++] = *next; + } + // Both outside + + if (outCount >= 15) break; // Safety limit + } + + return outCount; +} + +static int ClipTriangleToFrustumFixed(const VertexFixed tri[3], VertexFixed* outPoly) { + VertexFixed buf1[16], buf2[16]; + VertexFixed* src = buf1; + VertexFixed* dst = buf2; + + src[0] = tri[0]; + src[1] = tri[1]; + src[2] = tri[2]; + int count = 3; + + for (int i = 0; i < 3; i++) { + if (src[i].w == 0) { + return 0; + } + } + + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + + for (int p = 0; p < 6; p++) { + int newCount = ClipPolygonPlaneFixed(src, count, dst, planes[p]); + + if (newCount == 0) { + return 0; + } + + // Swap buffers + VertexFixed* tmp = src; + src = dst; + dst = tmp; + count = newCount; + + if (count > 15) count = 15; // Safety limit + } + + for (int i = 0; i < count; i++) { + outPoly[i] = src[i]; + } + + return count; +} + +static void TransformVertex2D(int index, VertexFixed* vertex) { + char* ptr = (char*)gfx_vertices + index * gfx_stride; + struct VertexColoured* v_col; + struct VertexTextured* v_tex; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + v_col = (struct VertexColoured*)ptr; + vertex->x = FloatToFixed(v_col->x); + vertex->y = FloatToFixed(v_col->y); + vertex->u = 0; + vertex->v = 0; + vertex->c = v_col->Col; + } else { + v_tex = (struct VertexTextured*)ptr; + vertex->x = FloatToFixed(v_tex->x); + vertex->y = FloatToFixed(v_tex->y); + vertex->u = FloatToFixed(v_tex->U); + vertex->v = FloatToFixed(v_tex->V); + vertex->c = v_tex->Col; + } +} + +static int TransformVertex3D(int index, VertexFixed* vertex) { + char* ptr = (char*)gfx_vertices + index * gfx_stride; + struct VertexColoured* v_col; + struct VertexTextured* v_tex; + + int pos_x, pos_y, pos_z; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + v_col = (struct VertexColoured*)ptr; + pos_x = FloatToFixed(v_col->x); + pos_y = FloatToFixed(v_col->y); + pos_z = FloatToFixed(v_col->z); + vertex->u = 0; + vertex->v = 0; + vertex->c = v_col->Col; + } else { + v_tex = (struct VertexTextured*)ptr; + pos_x = FloatToFixed(v_tex->x); + pos_y = FloatToFixed(v_tex->y); + pos_z = FloatToFixed(v_tex->z); + vertex->u = FloatToFixed(v_tex->U) + texOffsetX_fp; + vertex->v = FloatToFixed(v_tex->V) + texOffsetY_fp; + vertex->c = v_tex->Col; + } + + if (ABS(pos_x) > (1 << 28) || ABS(pos_y) > (1 << 28) || ABS(pos_z) > (1 << 28)) { + return 0; + } + + int64_t x_temp = (int64_t)pos_x * _mvp_fp.m[0][0] + (int64_t)pos_y * _mvp_fp.m[1][0] + + (int64_t)pos_z * _mvp_fp.m[2][0] + ((int64_t)_mvp_fp.m[3][0] << FP_SHIFT); + int64_t y_temp = (int64_t)pos_x * _mvp_fp.m[0][1] + (int64_t)pos_y * _mvp_fp.m[1][1] + + (int64_t)pos_z * _mvp_fp.m[2][1] + ((int64_t)_mvp_fp.m[3][1] << FP_SHIFT); + int64_t z_temp = (int64_t)pos_x * _mvp_fp.m[0][2] + (int64_t)pos_y * _mvp_fp.m[1][2] + + (int64_t)pos_z * _mvp_fp.m[2][2] + ((int64_t)_mvp_fp.m[3][2] << FP_SHIFT); + int64_t w_temp = (int64_t)pos_x * _mvp_fp.m[0][3] + (int64_t)pos_y * _mvp_fp.m[1][3] + + (int64_t)pos_z * _mvp_fp.m[2][3] + ((int64_t)_mvp_fp.m[3][3] << FP_SHIFT); + + x_temp >>= FP_SHIFT; + y_temp >>= FP_SHIFT; + z_temp >>= FP_SHIFT; + w_temp >>= FP_SHIFT; + + vertex->x = (x_temp > INT_MAX) ? INT_MAX : (x_temp < INT_MIN) ? INT_MIN : (int)x_temp; + vertex->y = (y_temp > INT_MAX) ? INT_MAX : (y_temp < INT_MIN) ? INT_MIN : (int)y_temp; + vertex->z = (z_temp > INT_MAX) ? INT_MAX : (z_temp < INT_MIN) ? INT_MIN : (int)z_temp; + vertex->w = (w_temp > INT_MAX) ? INT_MAX : (w_temp < INT_MIN) ? INT_MIN : (int)w_temp; + + return 1; +} + +static cc_bool ViewportVertex3D(VertexFixed* vertex) { + if (vertex->w == 0) return false; + if (ABS(vertex->w) < 64) return false; // Too small w + + int invW = FixedReciprocal(vertex->w); + + if (ABS(invW) > (FP_ONE << 10)) return false; // 1024x magnification limit + + int64_t x_ndc = ((int64_t)vertex->x * invW) >> FP_SHIFT; + int64_t y_ndc = ((int64_t)vertex->y * invW) >> FP_SHIFT; + int64_t z_ndc = ((int64_t)vertex->z * invW) >> FP_SHIFT; + + int64_t screen_x = vp_hwidth_fp + ((x_ndc * vp_hwidth_fp) >> FP_SHIFT); + int64_t screen_y = vp_hheight_fp - ((y_ndc * vp_hheight_fp) >> FP_SHIFT); + + // Clamp + if (screen_x < -(fb_width << FP_SHIFT) || screen_x > (fb_width << (FP_SHIFT + 1))) return false; + if (screen_y < -(fb_height << FP_SHIFT) || screen_y > (fb_height << (FP_SHIFT + 1))) return false; + + vertex->x = (int)screen_x; + vertex->y = (int)screen_y; + vertex->z = (z_ndc > INT_MAX) ? INT_MAX : (z_ndc < INT_MIN) ? INT_MIN : (int)z_ndc; + vertex->w = invW; + + vertex->u = FixedMul(vertex->u, invW); + vertex->v = FixedMul(vertex->v, invW); + + return true; +} + +static void DrawSprite2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + PackedCol vColor = V0->c; + int minX = FixedToInt(V0->x); + int minY = FixedToInt(V0->y); + int maxX = FixedToInt(V1->x); + int maxY = FixedToInt(V2->y); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + int begTX = FixedMul(V0->u, IntToFixed(curTexWidth)) >> FP_SHIFT; + int begTY = FixedMul(V0->v, IntToFixed(curTexHeight)) >> FP_SHIFT; + int delTX = (FixedMul(V1->u, IntToFixed(curTexWidth)) >> FP_SHIFT) - begTX; + int delTY = (FixedMul(V2->v, IntToFixed(curTexHeight)) >> FP_SHIFT) - begTY; + + int width = maxX - minX, height = maxY - minY; + + int fast = delTX == width && delTY == height && + (begTX + delTX < curTexWidth) && + (begTY + delTY < curTexHeight); + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int x, y; + for (y = minY; y <= maxY; y++) + { + int texY = fast ? (begTY + (y - minY)) : (((begTY + delTY * (y - minY) / height)) & texHeightMask); + for (x = minX; x <= maxX; x++) + { + int texX = fast ? (begTX + (x - minX)) : (((begTX + delTX * (x - minX) / width)) & texWidthMask); + int texIndex = texY * curTexWidth + texX; + + BitmapCol color = curTexPixels[texIndex]; + int R, G, B, A; + + A = BitmapCol_A(color); + if (gfx_alphaBlend && A == 0) continue; + int cb_index = y * cb_stride + x; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = BitmapCol_R(color); + G = BitmapCol_G(color); + B = BitmapCol_B(color); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + color = BitmapCol_Make(R, G, B, 0xFF); + } + + if (vColor != PACKEDCOL_WHITE) { + int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(color); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(vColor), g2 = BitmapCol_G(color); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(vColor), b2 = BitmapCol_B(color); + B = ( b1 * b2 ) >> 8; + + color = BitmapCol_Make(R, G, B, 0xFF); + } + + colorBuffer[cb_index] = color; + } + } +} + +#define edgeFunctionFixed(ax,ay, bx,by, cx,cy) \ + (FixedMul((bx) - (ax), (cy) - (ay)) - FixedMul((by) - (ay), (cx) - (ax))) + +#define MultiplyColors(vColor, tColor) \ + a1 = PackedCol_A(vColor); \ + a2 = BitmapCol_A(tColor); \ + A = ( a1 * a2 ) >> 8; \ +\ + r1 = PackedCol_R(vColor); \ + r2 = BitmapCol_R(tColor); \ + R = ( r1 * r2 ) >> 8; \ +\ + g1 = PackedCol_G(vColor); \ + g2 = BitmapCol_G(tColor); \ + G = ( g1 * g2 ) >> 8; \ +\ + b1 = PackedCol_B(vColor); \ + b2 = BitmapCol_B(tColor); \ + B = ( b1 * b2 ) >> 8; \ + +static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int area = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, x2_fp, y2_fp); + if (area == 0) return; + + int factor = FixedReciprocal(area); + + int w0 = V0->w, w1 = V1->w, w2 = V2->w; + if (w0 <= 0 && w1 <= 0 && w2 <= 0) return; + + int z0 = V0->z, z1 = V1->z, z2 = V2->z; + PackedCol color = V0->c; + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp, y1_fp, x2_fp, y2_fp, minX_fp, minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp, y2_fp, x0_fp, y0_fp, minX_fp, minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, minX_fp, minY_fp); + + + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; + + if (!texturing) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else if (texSinglePixel) { + int rawY0 = FixedDiv(v0, w0); + int rawY1 = FixedDiv(v1, w1); + int rawY = min(rawY0, rawY1); + int texY = (FixedToInt(rawY) + 1) & texHeightMask; + MultiplyColors(color, curTexPixels[texY * curTexWidth]); + texturing = false; + } + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + int ic0 = FixedMul(bc0, factor); + int ic1 = FixedMul(bc1, factor); + int ic2 = FixedMul(bc2, factor); + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + int db_index = y * db_stride + x; + + int w_interp = FixedMul(ic0, w0) + FixedMul(ic1, w1) + FixedMul(ic2, w2); + if (w_interp == 0) continue; + int w = FixedReciprocal(w_interp); + int z_interp = FixedMul(ic0, z0) + FixedMul(ic1, z1) + FixedMul(ic2, z2); + int z = FixedMul(z_interp, w); + + if (depthTest && (z < 0 || z > depthBuffer[db_index])) continue; + if (!colWrite) { + if (depthWrite) depthBuffer[db_index] = z; + continue; + } + + if (texturing) { + int u_interp = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int v_interp = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int u = FixedMul(u_interp, w); + int v = FixedMul(v_interp, w); + + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + + int texIndex = texY * curTexWidth + texX; + BitmapCol tColor = curTexPixels[texIndex]; + + MultiplyColors(color, tColor); + } + + if (gfx_alphaTest && A < 0x80) continue; + if (depthWrite) depthBuffer[db_index] = z; + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); + continue; + } + + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + int finR = (R * A + dstR * (255 - A)) >> 8; + int finG = (G * A + dstG * (255 - A)) >> 8; + int finB = (B * A + dstB * (255 - A)) >> 8; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } +} +static void DrawTriangle2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + PackedCol color = V0->c; + + int area = edgeFunctionFixed(x0_fp,y0_fp, x1_fp,y1_fp, x2_fp,y2_fp); + if (area == 0) return; + int factor = FixedReciprocal(area); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp,y1_fp, x2_fp,y2_fp, minX_fp,minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp,y2_fp, x0_fp,y0_fp, minX_fp,minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp,y0_fp, x1_fp,y1_fp, minX_fp,minY_fp); + + int x, y; + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + int ic0 = FixedMul(bc0, factor); + int ic1 = FixedMul(bc1, factor); + int ic2 = FixedMul(bc2, factor); + + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + int cb_index = y * cb_stride + x; + + int R, G, B, A; + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + int u = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int v = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + int texIndex = texY * curTexWidth + texX; + + BitmapCol tColor = curTexPixels[texIndex]; + int a1 = PackedCol_A(color), a2 = BitmapCol_A(tColor); + A = ( a1 * a2 ) >> 8; + int r1 = PackedCol_R(color), r2 = BitmapCol_R(tColor); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(color), g2 = BitmapCol_G(tColor); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(color), b2 = BitmapCol_B(tColor); + B = ( b1 * b2 ) >> 8; + } else { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } + + if (gfx_alphaTest && A < 0x80) continue; + if (gfx_alphaBlend && A == 0) continue; + + if (gfx_alphaBlend && A != 255) { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; + } + + colorBuffer[cb_index] = BitmapCol_Make(R, G, B, 0xFF); + } + } +} + +static void ProcessClippedTriangleAndDraw(const VertexFixed* inVerts, int polyCount) { + if (polyCount < 3) return; + + for (int i = 1; i + 1 < polyCount; i++) { + VertexFixed A = inVerts[0]; + VertexFixed B = inVerts[i]; + VertexFixed C = inVerts[i + 1]; + + if (faceCulling) { + if (A.w > 0 && B.w > 0 && C.w > 0) { + int invA = FixedReciprocal(A.w); + int invB = FixedReciprocal(B.w); + int invC = FixedReciprocal(C.w); + + int ax = FixedMul(A.x, invA); + int ay = FixedMul(A.y, invA); + int bx = FixedMul(B.x, invB); + int by = FixedMul(B.y, invB); + int cx = FixedMul(C.x, invC); + int cy = FixedMul(C.y, invC); + + int area_ndc = edgeFunctionFixed(ax, ay, bx, by, cx, cy); + if (area_ndc < 0) continue; /* 裏向き → スキップ */ + } + } + + if (!ViewportVertex3D(&A) || !ViewportVertex3D(&B) || !ViewportVertex3D(&C)) { + continue; + } + + int minX = FixedToInt(min(A.x, min(B.x, C.x))); + int minY = FixedToInt(min(A.y, min(B.y, C.y))); + int maxX = FixedToInt(max(A.x, max(B.x, C.x))); + int maxY = FixedToInt(max(A.y, max(B.y, C.y))); + + if (maxX < 0 || minX > fb_maxX || maxY < 0 || minY > fb_maxY) { + continue; + } + + // too small + int area = edgeFunctionFixed(A.x, A.y, B.x, B.y, C.x, C.y); + if (ABS(area) <= FP_ONE) continue; + + DrawTriangle3D(&A, &B, &C); + } +} + +static void DrawClippedFixed(int mask, VertexFixed* v0, VertexFixed* v1, VertexFixed* v2, VertexFixed* v3) { + VertexFixed inTri[3], outPoly[16]; + int polyCount; + + // Triangle 1: v0, v1, v2 + inTri[0] = *v0; + inTri[1] = *v1; + inTri[2] = *v2; + + polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); + if (polyCount > 0) { + ProcessClippedTriangleAndDraw(outPoly, polyCount); + } + + // triangle 2: v2, v3, v0 + inTri[0] = *v2; + inTri[1] = *v3; + inTri[2] = *v0; + + polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); + if (polyCount > 0) { + ProcessClippedTriangleAndDraw(outPoly, polyCount); + } +} + +#define V0_VIS (1 << 0) +#define V1_VIS (1 << 1) +#define V2_VIS (1 << 2) +#define V3_VIS (1 << 3) +static void ClipLineFixed(const VertexFixed* v1, const VertexFixed* v2, VertexFixed* out, int d1, int d2) { + int denom = d1 - d2; + int t = denom == 0 ? FP_HALF : FixedDiv(d1, denom); + int invt = FP_ONE - t; + + out->x = FixedMul(invt, v1->x) + FixedMul(t, v2->x); + out->y = FixedMul(invt, v1->y) + FixedMul(t, v2->y); + out->z = FixedMul(invt, v1->z) + FixedMul(t, v2->z); + out->w = FixedMul(invt, v1->w) + FixedMul(t, v2->w); + out->u = FixedMul(invt, v1->u) + FixedMul(t, v2->u); + out->v = FixedMul(invt, v1->v) + FixedMul(t, v2->v); + out->c = v1->c; //TODO: 色補完する? +} + +void DrawQuadsFixed(int startVertex, int verticesCount, DrawHints hints) { + VertexFixed vertices[4]; + int i, j = startVertex; + + if (gfx_rendering2D && (hints & (DRAW_HINT_SPRITE|DRAW_HINT_RECT))) { + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + DrawSprite2D(&vertices[0], &vertices[1], &vertices[2]); + } + } else if (gfx_rendering2D) { + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex2D(j + 0, &vertices[0]); + TransformVertex2D(j + 1, &vertices[1]); + TransformVertex2D(j + 2, &vertices[2]); + TransformVertex2D(j + 3, &vertices[3]); + DrawTriangle2D(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); + } + } else { + for (i = 0; i < verticesCount / 4; i++, j += 4) { + TransformVertex3D(j + 0, &vertices[0]); + TransformVertex3D(j + 1, &vertices[1]); + TransformVertex3D(j + 2, &vertices[2]); + TransformVertex3D(j + 3, &vertices[3]); + + DrawClippedFixed(0x0F, &vertices[0], &vertices[1], &vertices[2], &vertices[3]); + } + } +} +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { } /* TODO */ + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { + DrawQuadsFixed(startVertex, verticesCount, hints); +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + DrawQuadsFixed(0, verticesCount, DRAW_HINT_NONE); +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawQuadsFixed(startVertex, verticesCount, DRAW_HINT_NONE); +} + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +static BitmapCol* CB_GetRow(struct Bitmap* bmp, int y, void* ctx) { + return colorBuffer + cb_stride * y; +} + +cc_result Gfx_TakeScreenshot(struct Stream* output) { + struct Bitmap bmp; + Bitmap_Init(bmp, fb_width, fb_height, NULL); + return Png_Encode(&bmp, output, CB_GetRow, false, NULL); +} + +cc_bool Gfx_WarnIfNecessary(void) { return false; } +cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } + +void Gfx_BeginFrame(void) { } + +void Gfx_EndFrame(void) { + Rect2D r = { 0, 0, fb_width, fb_height }; + Window_DrawFramebuffer(r, &fb_bmp); +} + +void Gfx_SetVSync(cc_bool vsync) { + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + if (depthBuffer) DestroyBuffers(); + + fb_width = Game.Width; + fb_height = Game.Height; + + Window_AllocFramebuffer(&fb_bmp, Game.Width, Game.Height); + colorBuffer = fb_bmp.scan0; + cb_stride = fb_bmp.width; + + depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); + db_stride = fb_width; + + Gfx_SetViewport(0, 0, Game.Width, Game.Height); + Gfx_SetScissor (0, 0, Game.Width, Game.Height); +} + +void Gfx_SetViewport(int x, int y, int w, int h) { + vp_hwidth_fp = FloatToFixed(w / 2.0f); + vp_hheight_fp = FloatToFixed(h / 2.0f); +} + +void Gfx_SetScissor (int x, int y, int w, int h) { + fb_maxX = x + w - 1; + fb_maxY = y + h - 1; +} + +void Gfx_GetApiInfo(cc_string* info) { + int pointerSize = sizeof(void*) * 8; + String_Format1(info, "-- Using software fixed-point (%i bit) --\n", &pointerSize); + PrintMaxTextureInfo(info); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif From c6fada2c1fe3aefc7a80de2d31aab52106f9acf7 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 14 Sep 2025 07:39:15 +1000 Subject: [PATCH 088/115] 3DS: Refactor vblank handling --- src/3ds/Graphics_3DS.c | 7 +++-- src/3ds/gsp_gpu.h | 25 ++++++++++++++++ third_party/citro3d.c | 66 ++++-------------------------------------- 3 files changed, 35 insertions(+), 63 deletions(-) create mode 100644 src/3ds/gsp_gpu.h diff --git a/src/3ds/Graphics_3DS.c b/src/3ds/Graphics_3DS.c index 7ee615318..c3743322a 100644 --- a/src/3ds/Graphics_3DS.c +++ b/src/3ds/Graphics_3DS.c @@ -7,6 +7,7 @@ #define BUFFER_BASE_PADDR OS_VRAM_PADDR // VRAM physical address #include "../../third_party/citro3d.c" +#include "gsp_gpu.h" #include "pica_gpu.h" // See the .v.pica shader files in misc/3ds #define CONST_MVP 0 // c0-c3 @@ -121,9 +122,7 @@ static aptHookCookie hookCookie; static void AptEventHook(APT_HookType hookType, void* param) { if (hookType == APTHOOK_ONSUSPEND) { C3Di_RenderQueueWaitDone(); - C3Di_RenderQueueDisableVBlank(); } else if (hookType == APTHOOK_ONRESTORE) { - C3Di_RenderQueueEnableVBlank(); C3Di_OnRestore(); } } @@ -153,6 +152,8 @@ static void InitCitro3D(void) { gfxSetDoubleBuffering(GFX_TOP, true); SetDefaultState(); AllocShaders(); + + GSP_setup(); } static GfxResourceID white_square; @@ -547,7 +548,7 @@ void Gfx_SetVSync(cc_bool vsync) { void Gfx_BeginFrame(void) { rendering3D = false; // wait for vblank for both screens TODO move to end? - if (gfx_vsync) C3D_FrameSync(); + if (gfx_vsync) GSP_wait_for_full_vblank(); C3D_FrameBegin(0); topTarget = &topTargetLeft; diff --git a/src/3ds/gsp_gpu.h b/src/3ds/gsp_gpu.h new file mode 100644 index 000000000..81c827301 --- /dev/null +++ b/src/3ds/gsp_gpu.h @@ -0,0 +1,25 @@ +static volatile uint32_t vblanks_0; +static volatile uint32_t vblanks_1; + +static void handle_vblank(void* ptr) { + uint32_t* counter = (uint32_t*)ptr; + (*counter)++; +} + +static void GSP_setup(void) { + // Start listening for VBLANK events + gspSetEventCallback(GSPGPU_EVENT_VBlank0, handle_vblank, (void*)&vblanks_0, false); + gspSetEventCallback(GSPGPU_EVENT_VBlank1, handle_vblank, (void*)&vblanks_1, false); +} + +// Waits for VBLANK for both top and bottom screens +static void GSP_wait_for_full_vblank(void) { + uint32_t init0 = vblanks_0; + uint32_t init1 = vblanks_1; + + for (;;) { + gspWaitForAnyEvent(); + if (vblanks_0 != init0 && vblanks_1 != init1) return; + } +} + diff --git a/third_party/citro3d.c b/third_party/citro3d.c index 4d615d8ca..b0e08d1ce 100644 --- a/third_party/citro3d.c +++ b/third_party/citro3d.c @@ -245,12 +245,9 @@ struct C3D_RenderTarget_tag // Flags for C3D_FrameBegin enum { - C3D_FRAME_SYNCDRAW = BIT(0), // Perform C3D_FrameSync before checking the GPU status C3D_FRAME_NONBLOCK = BIT(1), // Return false instead of waiting if the GPU is busy }; -static void C3D_FrameSync(void); - static bool C3D_FrameBegin(u8 flags); static bool C3D_FrameDrawOn(C3D_RenderTarget* target); static void C3D_FrameSplit(u8 flags); @@ -404,10 +401,6 @@ static bool C3Di_SplitFrame(u32** pBuf, u32* pSize); static void C3Di_RenderQueueInit(void); static void C3Di_RenderQueueExit(void); static void C3Di_RenderQueueWaitDone(void); -static void C3Di_RenderQueueEnableVBlank(void); -static void C3Di_RenderQueueDisableVBlank(void); - - @@ -837,21 +830,10 @@ static void C3D_ImmDrawEnd(void) static C3D_RenderTarget *linkedTarget[3]; static bool inFrame, inSafeTransfer; -static bool needSwapTop, needSwapBot, isTopStereo; -static u32 vblankCounter[2]; +static bool swapPending, isTopStereo; static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target); -static void onVBlank0(void* unused) -{ - vblankCounter[0]++; -} - -static void onVBlank1(void* unused) -{ - vblankCounter[1]++; -} - static void onQueueFinish(gxCmdQueue_s* queue) { if (inSafeTransfer) @@ -863,61 +845,28 @@ static void onQueueFinish(gxCmdQueue_s* queue) gxCmdQueueClear(queue); } } - else + else if (swapPending) { - if (needSwapTop) - { - gfxScreenSwapBuffers(GFX_TOP, isTopStereo); - needSwapTop = false; - } - if (needSwapBot) - { - gfxScreenSwapBuffers(GFX_BOTTOM, false); - needSwapBot = false; - } + gfxScreenSwapBuffers(GFX_TOP, isTopStereo); + gfxScreenSwapBuffers(GFX_BOTTOM, false); } } -static void C3D_FrameSync(void) -{ - u32 cur[2]; - u32 start[2] = { vblankCounter[0], vblankCounter[1] }; - do - { - gspWaitForAnyEvent(); - cur[0] = vblankCounter[0]; - cur[1] = vblankCounter[1]; - } while (cur[0]==start[0] || cur[1]==start[1]); -} - static bool C3Di_WaitAndClearQueue(s64 timeout) { gxCmdQueue_s* queue = &C3Di_GetContext()->gxQueue; if (!gxCmdQueueWait(queue, timeout)) return false; + gxCmdQueueStop(queue); gxCmdQueueClear(queue); return true; } -static void C3Di_RenderQueueEnableVBlank(void) -{ - gspSetEventCallback(GSPGPU_EVENT_VBlank0, onVBlank0, NULL, false); - gspSetEventCallback(GSPGPU_EVENT_VBlank1, onVBlank1, NULL, false); -} - -static void C3Di_RenderQueueDisableVBlank(void) -{ - gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, false); - gspSetEventCallback(GSPGPU_EVENT_VBlank1, NULL, NULL, false); -} - static void C3Di_RenderQueueInit(void) { C3D_Context* ctx = C3Di_GetContext(); - C3Di_RenderQueueEnableVBlank(); - GX_BindQueue(&ctx->gxQueue); gxCmdQueueSetCallback(&ctx->gxQueue, onQueueFinish, NULL); gxCmdQueueRun(&ctx->gxQueue); @@ -928,8 +877,6 @@ static void C3Di_RenderQueueExit(void) C3Di_WaitAndClearQueue(-1); gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL); GX_BindQueue(NULL); - - C3Di_RenderQueueDisableVBlank(); } static void C3Di_RenderQueueWaitDone(void) @@ -987,8 +934,7 @@ static void C3D_FrameEnd(u8 flags) C3D_RenderTarget* target; isTopStereo = false; - needSwapTop = true; - needSwapBot = true; + swapPending = true; for (int i = 2; i >= 0; i --) { From 31faecde59a267a68f36ee83cee6aefca94f3a6a Mon Sep 17 00:00:00 2001 From: Mechamorph <118144070+coyoteclan@users.noreply.github.com> Date: Sun, 14 Sep 2025 16:51:12 +0500 Subject: [PATCH 089/115] Correct a typo in readme.md --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f90a13443..363a4027f 100644 --- a/readme.md +++ b/readme.md @@ -419,7 +419,7 @@ Further information (e.g. style) for ClassiCube's source code can be found in th #### Tips * Press escape (after joining a world) or pause to switch to the pause menu. * Pause menu -> Options -> Controls lists all of the key combinations used by the client. -* Note that toggling 'vsync' to on will minimise CPU usage, while off will maximimise chunk loading speed. +* Note that toggling 'vsync' to on will minimise CPU usage, while off will maximise chunk loading speed. * Press F to cycle view distance. Lower view distances can improve performance. * If the server has disabled hacks, key combinations such as fly and speed will not do anything. @@ -476,3 +476,4 @@ Further information (e.g. style) for ClassiCube's source code can be found in th ## Sound Credits ClassiCube uses sounds from [Freesound.org](https://freesound.org)
Full credits are listed in [doc/sound-credits.md](doc/sound-credits.md) + From d0069553981c65fa29258302d1555c01aaa10d48 Mon Sep 17 00:00:00 2001 From: TMK <151894646+oorange32@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:10:37 +0900 Subject: [PATCH 090/115] latest version correcting the size for memset early clipping check --- src/Graphics_SoftFP.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Graphics_SoftFP.c b/src/Graphics_SoftFP.c index dcbf14211..acfd38be7 100644 --- a/src/Graphics_SoftFP.c +++ b/src/Graphics_SoftFP.c @@ -6,6 +6,7 @@ #include #include + // 16.16 fixed point #define FP_SHIFT 16 #define FP_ONE (1 << FP_SHIFT) @@ -179,8 +180,7 @@ static void ClearColorBuffer(void) { int i, x, y, size = fb_width * fb_height; if (cb_stride == fb_width) { - //for (i = 0; i < size; i++) colorBuffer[i] = clearColor; - Mem_Set(colorBuffer, clearColor, sizeof(colorBuffer) * size); + Mem_Set(colorBuffer, clearColor, sizeof(BitmapCol) * size); } else { for (y = 0; y < fb_height; y++) { i = y * cb_stride; @@ -989,28 +989,37 @@ static void ProcessClippedTriangleAndDraw(const VertexFixed* inVerts, int polyCo } } +static cc_bool TriangleFullyInsideFrustum(const VertexFixed tri[3]) { + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + for (int p = 0; p < 6; p++) { + for (int i = 0; i < 3; i++) { + if (PlaneDistFixed(&tri[i], planes[p]) < 0) return false; + } + } + return true; +} + static void DrawClippedFixed(int mask, VertexFixed* v0, VertexFixed* v1, VertexFixed* v2, VertexFixed* v3) { VertexFixed inTri[3], outPoly[16]; int polyCount; // Triangle 1: v0, v1, v2 - inTri[0] = *v0; - inTri[1] = *v1; - inTri[2] = *v2; - - polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); - if (polyCount > 0) { - ProcessClippedTriangleAndDraw(outPoly, polyCount); + inTri[0] = *v0; inTri[1] = *v1; inTri[2] = *v2; + if (TriangleFullyInsideFrustum(inTri)) { + // fully inside + ProcessClippedTriangleAndDraw(inTri, 3); + } else { + polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); + if (polyCount > 0) ProcessClippedTriangleAndDraw(outPoly, polyCount); } - // triangle 2: v2, v3, v0 - inTri[0] = *v2; - inTri[1] = *v3; - inTri[2] = *v0; - - polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); - if (polyCount > 0) { - ProcessClippedTriangleAndDraw(outPoly, polyCount); + // Triangle 2: v2, v3, v0 + inTri[0] = *v2; inTri[1] = *v3; inTri[2] = *v0; + if (TriangleFullyInsideFrustum(inTri)) { + ProcessClippedTriangleAndDraw(inTri, 3); + } else { + polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); + if (polyCount > 0) ProcessClippedTriangleAndDraw(outPoly, polyCount); } } From 9283b69c00785f7414f85debad6313e98b00fa6c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 16 Sep 2025 07:34:35 +1000 Subject: [PATCH 091/115] Xbox: Keep generated vs/ps ASM files --- misc/ps3/Makefile | 4 ++ misc/xbox/Makefile | 24 ++++++---- misc/xbox/README.md | 4 ++ misc/xbox/ps_coloured.asm | 14 ++++++ .../{ps_coloured.ps.cg => ps_coloured.cg} | 0 misc/xbox/ps_textured.asm | 30 ++++++++++++ .../{ps_textured.ps.cg => ps_textured.cg} | 0 misc/xbox/vs_coloured.asm | 24 ++++++++++ .../{vs_coloured.vs.cg => vs_coloured.cg} | 0 misc/xbox/vs_offset.asm | 29 ++++++++++++ misc/xbox/{vs_offset.vs.cg => vs_offset.cg} | 0 misc/xbox/vs_offset.inl | 2 +- misc/xbox/vs_textured.asm | 27 +++++++++++ .../{vs_textured.vs.cg => vs_textured.cg} | 0 third_party/citro3d.c | 47 ++++--------------- 15 files changed, 157 insertions(+), 48 deletions(-) create mode 100644 misc/xbox/ps_coloured.asm rename misc/xbox/{ps_coloured.ps.cg => ps_coloured.cg} (100%) create mode 100644 misc/xbox/ps_textured.asm rename misc/xbox/{ps_textured.ps.cg => ps_textured.cg} (100%) create mode 100644 misc/xbox/vs_coloured.asm rename misc/xbox/{vs_coloured.vs.cg => vs_coloured.cg} (100%) create mode 100644 misc/xbox/vs_offset.asm rename misc/xbox/{vs_offset.vs.cg => vs_offset.cg} (100%) create mode 100644 misc/xbox/vs_textured.asm rename misc/xbox/{vs_textured.vs.cg => vs_textured.cg} (100%) diff --git a/misc/ps3/Makefile b/misc/ps3/Makefile index 9064a20e3..370863e02 100644 --- a/misc/ps3/Makefile +++ b/misc/ps3/Makefile @@ -139,6 +139,10 @@ $(BUILD_DIR)/%.o: src/ps3/%.S $(BUILD_DIR)/%.o: third_party/bearssl/%.c $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +# prevent the .asm files from being deleted +.PRECIOUS: $(BUILD_DIR)/%.vpo $(BUILD_DIR)/%.fpo + $(BUILD_DIR)/%.vpo: $(SHADERS)/%.vcg $(CGCOMP) -v $(CGCFLAGS) $^ $@ $(BUILD_DIR)/%.fpo: $(SHADERS)/%.fcg diff --git a/misc/xbox/Makefile b/misc/xbox/Makefile index 3f006f719..c996ef87a 100644 --- a/misc/xbox/Makefile +++ b/misc/xbox/Makefile @@ -82,7 +82,7 @@ $(BUILD_DIR): #--------------------------------------------------------------------------------- # Executable generation #--------------------------------------------------------------------------------- -$(OBJS) : $(SHADER_OBJS) +$(BUILD_DIR)/Graphics_Xbox.o : $(SHADER_OBJS) $(TARGET).iso: $(TARGET).xbe mkdir -p $(BUILD_DIR)/cd @@ -111,15 +111,21 @@ $(BUILD_DIR)/%.o: src/xbox/%.S $(BUILD_DIR)/%.o: third_party/bearssl/%.c nxdk-cc $(NXDK_CFLAGS) $(CFLAGS) -c $< -o $@ -%.inl: %.vs.cg - $(CGC) -profile vp20 -o $@.$$$$ $< && \ - $(VP20COMPILER) $@.$$$$ > $@ && \ - rm -rf $@.$$$$ -%.inl: %.ps.cg - $(CGC) -profile fp20 -o $@.$$$$ $< && \ - $(FP20COMPILER) $@.$$$$ > $@ && \ - rm -rf $@.$$$$ +# prevent the .asm files from being deleted +.PRECIOUS: vs_%.asm ps_%.asm + +vs_%.inl: vs_%.asm + $(VP20COMPILER) $< > $@ + +vs_%.asm: vs_%.cg + $(CGC) -profile vp20 $< -o $@ + +ps_%.inl: ps_%.asm + $(FP20COMPILER) $< > $@ + +ps_%.asm: ps_%.cg + $(CGC) -profile fp20 $< -o $@ #--------------------------------------------------------------------------------- diff --git a/misc/xbox/README.md b/misc/xbox/README.md index f5da3eb2f..a813c938b 100644 --- a/misc/xbox/README.md +++ b/misc/xbox/README.md @@ -5,3 +5,7 @@ To see debug log messages in Xemu: ---- To launch directly, `-dvd_path cc-xbox.iso` + +#### + +The .asm files are auto generated from the .cg files, and shouldn't be manually edited. diff --git a/misc/xbox/ps_coloured.asm b/misc/xbox/ps_coloured.asm new file mode 100644 index 000000000..756815cbe --- /dev/null +++ b/misc/xbox/ps_coloured.asm @@ -0,0 +1,14 @@ +// nvparse 1.0 output generated by NVIDIA Cg compiler +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile fp20 +// source file: misc/xbox/ps_coloured.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile fp20 +//program main +//var float4 input.color : $vin.COLOR : COLOR0 : 0 : 1 +//var float4 main : $vout.COLOR : COLOR : -1 : 1 +!!RC1.0 +out.rgb = unsigned(col0.rgb); +out.a = unsigned(col0.a); +// 0 instructions diff --git a/misc/xbox/ps_coloured.ps.cg b/misc/xbox/ps_coloured.cg similarity index 100% rename from misc/xbox/ps_coloured.ps.cg rename to misc/xbox/ps_coloured.cg diff --git a/misc/xbox/ps_textured.asm b/misc/xbox/ps_textured.asm new file mode 100644 index 000000000..99fc0c06e --- /dev/null +++ b/misc/xbox/ps_textured.asm @@ -0,0 +1,30 @@ +// nvparse 1.0 output generated by NVIDIA Cg compiler +// cgc version 3.1.0013, build date Apr 24 2012 +// command line args: -profile fp20 +// source file: misc/xbox/ps_textured.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile fp20 +//program main +//semantic main.tex +//var sampler2D tex : : 0 : 1 : 1 +//var float4 input.color : $vin.COLOR : COLOR0 : 0 : 1 +//var float2 input.tex0 : $vin.TEXCOORD0 : TEXCOORD0 : 0 : 1 +//var float4 main : $vout.COLOR : COLOR : -1 : 1 +!!TS1.0 +texture_2d(); +// End of program +!!RC1.0 +{ + rgb + { + col0 = tex0.rgb * col0.rgb; + } + alpha + { + col0 = tex0.a * col0.a; + } +} +out.rgb = unsigned(col0.rgb); +out.a = unsigned(col0.a); +// 3 instructions diff --git a/misc/xbox/ps_textured.ps.cg b/misc/xbox/ps_textured.cg similarity index 100% rename from misc/xbox/ps_textured.ps.cg rename to misc/xbox/ps_textured.cg diff --git a/misc/xbox/vs_coloured.asm b/misc/xbox/vs_coloured.asm new file mode 100644 index 000000000..f3b4462df --- /dev/null +++ b/misc/xbox/vs_coloured.asm @@ -0,0 +1,24 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_coloured.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[COL0], v[3]; +MOV o[HPOS].w, R0; +END +# 8 instructions, 0 R-regs diff --git a/misc/xbox/vs_coloured.vs.cg b/misc/xbox/vs_coloured.cg similarity index 100% rename from misc/xbox/vs_coloured.vs.cg rename to misc/xbox/vs_coloured.cg diff --git a/misc/xbox/vs_offset.asm b/misc/xbox/vs_offset.asm new file mode 100644 index 000000000..fc0a6d64b --- /dev/null +++ b/misc/xbox/vs_offset.asm @@ -0,0 +1,29 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_offset.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#semantic main.tex_offset +#var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 tex_offset : : c[4] : 2 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[HPOS].w, R0; +MOV o[COL0], v[3]; +ADD o[TEX0], v[8], c[4]; +END +# 9 instructions, 0 R-regs diff --git a/misc/xbox/vs_offset.vs.cg b/misc/xbox/vs_offset.cg similarity index 100% rename from misc/xbox/vs_offset.vs.cg rename to misc/xbox/vs_offset.cg diff --git a/misc/xbox/vs_offset.inl b/misc/xbox/vs_offset.inl index a2395317b..135f1576d 100644 --- a/misc/xbox/vs_offset.inl +++ b/misc/xbox/vs_offset.inl @@ -1,6 +1,6 @@ // cgc version 3.1.0013, build date Apr 24 2012 // command line args: -profile vp20 -// source file: misc/xbox/vs_offset.vs.cg +// source file: misc/xbox/vs_offset.cg //vendor NVIDIA Corporation //version 3.1.0.13 //profile vp20 diff --git a/misc/xbox/vs_textured.asm b/misc/xbox/vs_textured.asm new file mode 100644 index 000000000..aaa6b3740 --- /dev/null +++ b/misc/xbox/vs_textured.asm @@ -0,0 +1,27 @@ +!!VP1.1 +# cgc version 3.1.0013, build date Apr 24 2012 +# command line args: -profile vp20 +# source file: misc/xbox/vs_textured.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile vp20 +#program main +#semantic main.mvp +#var float4 input.tex : $vin.TEXCOORD : TEXCOORD0 : 0 : 1 +#var float4 input.col : $vin.DIFFUSE : ATTR3 : 0 : 1 +#var float4 input.pos : $vin.POSITION : ATTR0 : 0 : 1 +#var float4x4 mvp : : c[0], 4 : 1 : 1 +#var float4 main.pos : $vout.POSITION : HPOS : -1 : 1 +#var float4 main.col : $vout.COLOR : COL0 : -1 : 1 +#var float4 main.tex : $vout.TEXCOORD0 : TEX0 : -1 : 1 +MUL R0, v[0].y, c[1]; +MAD R0, v[0].x, c[0], R0; +MAD R0, v[0].z, c[2], R0; +ADD R0, R0, c[3]; +RCP R1.x, R0.w; +MUL o[HPOS].xyz, R0, R1.x; +MOV o[HPOS].w, R0; +MOV o[COL0], v[3]; +MOV o[TEX0], v[8]; +END +# 9 instructions, 0 R-regs diff --git a/misc/xbox/vs_textured.vs.cg b/misc/xbox/vs_textured.cg similarity index 100% rename from misc/xbox/vs_textured.vs.cg rename to misc/xbox/vs_textured.cg diff --git a/third_party/citro3d.c b/third_party/citro3d.c index b0e08d1ce..9d658e0a8 100644 --- a/third_party/citro3d.c +++ b/third_party/citro3d.c @@ -250,10 +250,8 @@ enum static bool C3D_FrameBegin(u8 flags); static bool C3D_FrameDrawOn(C3D_RenderTarget* target); -static void C3D_FrameSplit(u8 flags); static void C3D_FrameEnd(u8 flags); -static void C3D_RenderTargetDelete(C3D_RenderTarget* target); static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags); static inline void C3D_RenderTargetDetachOutput(C3D_RenderTarget* target) @@ -832,8 +830,6 @@ static C3D_RenderTarget *linkedTarget[3]; static bool inFrame, inSafeTransfer; static bool swapPending, isTopStereo; -static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target); - static void onQueueFinish(gxCmdQueue_s* queue) { if (inSafeTransfer) @@ -907,20 +903,15 @@ static bool C3D_FrameDrawOn(C3D_RenderTarget* target) return true; } -static void C3D_FrameSplit(u8 flags) -{ - u32 *cmdBuf, cmdBufSize; - if (!inFrame) return; - if (C3Di_SplitFrame(&cmdBuf, &cmdBufSize)) - GX_ProcessCommandList(cmdBuf, cmdBufSize*4, flags); -} - static void C3D_FrameEnd(u8 flags) { C3D_Context* ctx = C3Di_GetContext(); if (!inFrame) return; - C3D_FrameSplit(flags); + u32 *cmdBuf, cmdBufSize; + if (C3Di_SplitFrame(&cmdBuf, &cmdBufSize)) + GX_ProcessCommandList(cmdBuf, cmdBufSize*4, flags); + GPUCMD_SetBuffer(NULL, 0, 0); inFrame = false; @@ -984,23 +975,6 @@ static void C3D_RenderTargetDepth(C3D_RenderTarget* target, GPU_DEPTHBUF depthFm C3D_FrameBufDepth(fb, depthBuf, depthFmt); } -static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target) -{ - vramFree(target->frameBuf.colorBuf); - vramFree(target->frameBuf.depthBuf); -} - -static void C3D_RenderTargetDelete(C3D_RenderTarget* target) -{ - if (inFrame) - svcBreak(USERBREAK_PANIC); // Shouldn't happen. - if (target->linked) - C3D_RenderTargetDetachOutput(target); - else - C3Di_WaitAndClearQueue(-1); - C3Di_RenderTargetDestroy(target); -} - static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags) { int id = 0; @@ -1079,6 +1053,9 @@ static void C3Di_OnRestore(void) ctx->flags |= C3DiF_FogLut; } +#define GXQUEUE_MAX_ENTRIES 32 +static gxCmdEntry_s queue_entries[GXQUEUE_MAX_ENTRIES]; + static bool C3D_Init(size_t cmdBufSize) { int i; @@ -1093,13 +1070,8 @@ static bool C3D_Init(size_t cmdBufSize) if (!ctx->cmdBuf) return false; - ctx->gxQueue.maxEntries = 32; - ctx->gxQueue.entries = (gxCmdEntry_s*)malloc(ctx->gxQueue.maxEntries*sizeof(gxCmdEntry_s)); - if (!ctx->gxQueue.entries) - { - linearFree(ctx->cmdBuf); - return false; - } + ctx->gxQueue.maxEntries = GXQUEUE_MAX_ENTRIES; + ctx->gxQueue.entries = queue_entries; ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_Effect | C3DiF_TexStatus | C3DiF_TexAll | C3DiF_Reset; @@ -1308,7 +1280,6 @@ static void C3D_Fini(void) return; C3Di_RenderQueueExit(); - free(ctx->gxQueue.entries); linearFree(ctx->cmdBuf); ctx->flags = 0; } From 95d311e9bf4e2619ce4c0806b2ea1588d9f7aff8 Mon Sep 17 00:00:00 2001 From: TMK <151894646+oorange32@users.noreply.github.com> Date: Tue, 16 Sep 2025 13:29:17 +0900 Subject: [PATCH 092/115] optimized Convert vertices to fixed-point format beforehand Perform clipping calculations while retaining quads --- src/Graphics_SoftFP.c | 473 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 418 insertions(+), 55 deletions(-) diff --git a/src/Graphics_SoftFP.c b/src/Graphics_SoftFP.c index acfd38be7..910a62478 100644 --- a/src/Graphics_SoftFP.c +++ b/src/Graphics_SoftFP.c @@ -64,6 +64,26 @@ typedef struct VertexFixed { static int texOffsetX_fp, texOffsetY_fp; // Fixed point texture offsets static FixedMatrix _view_fp, _proj_fp, _mvp_fp; +#define MAX_PRECONV_VBS 64 + +typedef struct { + void* vb; + VertexFixed* verts; + int count; + int stride; + VertexFormat fmt; +} PreconvEntry; + +static PreconvEntry preconvEntries[MAX_PRECONV_VBS]; +static int preconvEntryCount = 0; + + +static void* last_locked_vb = NULL; +static int last_locked_count = 0; +static VertexFormat last_locked_fmt = 0; +static int last_locked_stride = 0; + + static void Gfx_RestoreState(void) { InitDefaultResources(); @@ -246,18 +266,122 @@ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } -void Gfx_DeleteVb(GfxResourceID* vb) { - GfxResourceID data = *vb; - if (data) Mem_Free(data); - *vb = 0; + + +static PreconvEntry* FindPreconvEntry(void* vb) { + for (int i = 0; i < preconvEntryCount; i++) { + if (preconvEntries[i].vb == vb) return &preconvEntries[i]; + } + return NULL; } +static void FreePreconvEntryAt(int idx) { + if (preconvEntries[idx].verts) Mem_Free(preconvEntries[idx].verts); + if (idx != preconvEntryCount - 1) { + preconvEntries[idx] = preconvEntries[preconvEntryCount - 1]; + } + preconvEntryCount--; +} + +static void FreePreconvForVB(void* vb) { + PreconvEntry* e = FindPreconvEntry(vb); + if (!e) return; + int idx = (int)(e - preconvEntries); + FreePreconvEntryAt(idx); +} + +static int Preconv_Set(void* vb, int count, int stride, VertexFormat fmt) { + FreePreconvForVB(vb); + + if (count <= 0) return 0; + if (preconvEntryCount >= MAX_PRECONV_VBS) { + return 0; + } + + VertexFixed* arr = (VertexFixed*)Mem_Alloc(count, sizeof(VertexFixed), "vb-preconv"); + if (!arr) return 0; + + char* base = (char*)vb; + for (int i = 0; i < count; i++) { + char* ptr = base + i * stride; + if (fmt != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v = (struct VertexColoured*)ptr; + arr[i].x = FloatToFixed(v->x); + arr[i].y = FloatToFixed(v->y); + arr[i].z = 0; + arr[i].w = IntToFixed(1); + arr[i].u = 0; + arr[i].v = 0; + arr[i].c = v->Col; + } else { + struct VertexTextured* v = (struct VertexTextured*)ptr; + arr[i].x = FloatToFixed(v->x); + arr[i].y = FloatToFixed(v->y); + arr[i].z = FloatToFixed(v->z); + arr[i].w = IntToFixed(1); + arr[i].u = FloatToFixed(v->U) + texOffsetX_fp; + arr[i].v = FloatToFixed(v->V) + texOffsetY_fp; + arr[i].c = v->Col; + } + } + + preconvEntries[preconvEntryCount].vb = vb; + preconvEntries[preconvEntryCount].verts = arr; + preconvEntries[preconvEntryCount].count = count; + preconvEntries[preconvEntryCount].stride = stride; + preconvEntries[preconvEntryCount].fmt = fmt; + preconvEntryCount++; + return 1; +} + +static cc_bool Preconv_GetVertex(void* vb, int index, VertexFixed* out) { + PreconvEntry* e = FindPreconvEntry(vb); + if (!e) return false; + if (index < 0 || index >= e->count) return false; + *out = e->verts[index]; + return true; +} +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) { + FreePreconvForVB(data); + Mem_Free(data); + } + *vb = 0; +} void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + last_locked_vb = vb; + last_locked_count = count; + last_locked_fmt = fmt; + last_locked_stride = strideSizes[fmt]; return vb; } -void Gfx_UnlockVb(GfxResourceID vb) { - gfx_vertices = vb; +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + last_locked_vb = vb; + last_locked_count = count; + last_locked_fmt = fmt; + last_locked_stride = strideSizes[fmt]; + return vb; +} + + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; + if (last_locked_vb == vb && last_locked_count > 0) { + Preconv_Set(vb, last_locked_count, last_locked_stride, last_locked_fmt); + } else { + // count is unknown + } + last_locked_vb = NULL; last_locked_count = 0; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; + if (last_locked_vb == vb && last_locked_count > 0) { + Preconv_Set(vb, last_locked_count, last_locked_stride, last_locked_fmt); + } + last_locked_vb = NULL; last_locked_count = 0; } static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { @@ -266,14 +390,6 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - return vb; -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; -} - void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } /*########################################################################################################################* @@ -523,7 +639,10 @@ static int ClipTriangleToFrustumFixed(const VertexFixed tri[3], VertexFixed* out } static void TransformVertex2D(int index, VertexFixed* vertex) { + if (Preconv_GetVertex(gfx_vertices, index, vertex)) return; + char* ptr = (char*)gfx_vertices + index * gfx_stride; + struct VertexColoured* v_col; struct VertexTextured* v_tex; @@ -545,28 +664,28 @@ static void TransformVertex2D(int index, VertexFixed* vertex) { } static int TransformVertex3D(int index, VertexFixed* vertex) { - char* ptr = (char*)gfx_vertices + index * gfx_stride; - struct VertexColoured* v_col; - struct VertexTextured* v_tex; - int pos_x, pos_y, pos_z; - - if (gfx_format != VERTEX_FORMAT_TEXTURED) { - v_col = (struct VertexColoured*)ptr; - pos_x = FloatToFixed(v_col->x); - pos_y = FloatToFixed(v_col->y); - pos_z = FloatToFixed(v_col->z); - vertex->u = 0; - vertex->v = 0; - vertex->c = v_col->Col; + + if (Preconv_GetVertex(gfx_vertices, index, vertex)) { + pos_x = vertex->x; pos_y = vertex->y; pos_z = vertex->z; } else { - v_tex = (struct VertexTextured*)ptr; - pos_x = FloatToFixed(v_tex->x); - pos_y = FloatToFixed(v_tex->y); - pos_z = FloatToFixed(v_tex->z); - vertex->u = FloatToFixed(v_tex->U) + texOffsetX_fp; - vertex->v = FloatToFixed(v_tex->V) + texOffsetY_fp; - vertex->c = v_tex->Col; + // fallback + char* ptr = (char*)gfx_vertices + index * gfx_stride; + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + struct VertexColoured* v_col = (struct VertexColoured*)ptr; + pos_x = FloatToFixed(v_col->x); + pos_y = FloatToFixed(v_col->y); + pos_z = 0; + vertex->u = 0; vertex->v = 0; vertex->c = v_col->Col; + } else { + struct VertexTextured* v_tex = (struct VertexTextured*)ptr; + pos_x = FloatToFixed(v_tex->x); + pos_y = FloatToFixed(v_tex->y); + pos_z = FloatToFixed(v_tex->z); + vertex->u = FloatToFixed(v_tex->U) + texOffsetX_fp; + vertex->v = FloatToFixed(v_tex->V) + texOffsetY_fp; + vertex->c = v_tex->Col; + } } if (ABS(pos_x) > (1 << 28) || ABS(pos_y) > (1 << 28) || ABS(pos_z) > (1 << 28)) { @@ -699,7 +818,8 @@ static void DrawSprite2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { #define edgeFunctionFixed(ax,ay, bx,by, cx,cy) \ (FixedMul((bx) - (ax), (cy) - (ay)) - FixedMul((by) - (ay), (cx) - (ax))) - + + #define MultiplyColors(vColor, tColor) \ a1 = PackedCol_A(vColor); \ a2 = BitmapCol_A(tColor); \ @@ -717,6 +837,7 @@ static void DrawSprite2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { b2 = BitmapCol_B(tColor); \ B = ( b1 * b2 ) >> 8; \ +/* static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { int x0_fp = V0->x, y0_fp = V0->y; int x1_fp = V1->x, y1_fp = V1->y; @@ -844,6 +965,208 @@ static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { } } } +*/ + +static inline void MultiplyColorsInline(PackedCol vColor, BitmapCol tColor, + int *outR, int *outG, int *outB, int *outA) { + int a1 = PackedCol_A(vColor); + int r1 = PackedCol_R(vColor); + int g1 = PackedCol_G(vColor); + int b1 = PackedCol_B(vColor); + + int a2 = BitmapCol_A(tColor); + int r2 = BitmapCol_R(tColor); + int g2 = BitmapCol_G(tColor); + int b2 = BitmapCol_B(tColor); + + *outA = (a1 * a2) >> 8; + *outR = (r1 * r2) >> 8; + *outG = (g1 * g2) >> 8; + *outB = (b1 * b2) >> 8; +} + +static void DrawTriangle3D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { + int x0_fp = V0->x, y0_fp = V0->y; + int x1_fp = V1->x, y1_fp = V1->y; + int x2_fp = V2->x, y2_fp = V2->y; + + int minX = FixedToInt(min(x0_fp, min(x1_fp, x2_fp))); + int minY = FixedToInt(min(y0_fp, min(y1_fp, y2_fp))); + int maxX = FixedToInt(max(x0_fp, max(x1_fp, x2_fp))); + int maxY = FixedToInt(max(y0_fp, max(y1_fp, y2_fp))); + + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; + + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); + + int area = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, x2_fp, y2_fp); + if (area == 0) return; + + int factor = FixedReciprocal(area); + + int w0 = V0->w, w1 = V1->w, w2 = V2->w; + if (w0 <= 0 && w1 <= 0 && w2 <= 0) return; + + int z0 = V0->z, z1 = V1->z, z2 = V2->z; + PackedCol color = V0->c; + + int u0 = FixedMul(V0->u, IntToFixed(curTexWidth)); + int v0 = FixedMul(V0->v, IntToFixed(curTexHeight)); + int u1 = FixedMul(V1->u, IntToFixed(curTexWidth)); + int v1 = FixedMul(V1->v, IntToFixed(curTexHeight)); + int u2 = FixedMul(V2->u, IntToFixed(curTexWidth)); + int v2 = FixedMul(V2->v, IntToFixed(curTexHeight)); + + int dx01 = y0_fp - y1_fp, dy01 = x1_fp - x0_fp; + int dx12 = y1_fp - y2_fp, dy12 = x2_fp - x1_fp; + int dx20 = y2_fp - y0_fp, dy20 = x0_fp - x2_fp; + + int minX_fp = IntToFixed(minX) + FP_HALF; + int minY_fp = IntToFixed(minY) + FP_HALF; + + int bc0_start = edgeFunctionFixed(x1_fp, y1_fp, x2_fp, y2_fp, minX_fp, minY_fp); + int bc1_start = edgeFunctionFixed(x2_fp, y2_fp, x0_fp, y0_fp, minX_fp, minY_fp); + int bc2_start = edgeFunctionFixed(x0_fp, y0_fp, x1_fp, y1_fp, minX_fp, minY_fp); + + int R, G, B, A, x, y; + int a1, r1, g1, b1; + int a2, r2, g2, b2; + cc_bool texturing = gfx_format == VERTEX_FORMAT_TEXTURED; + + if (!texturing) { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); + } else if (texSinglePixel) { + int rawY0 = FixedDiv(v0, w0); + int rawY1 = FixedDiv(v1, w1); + int rawY = min(rawY0, rawY1); + int texY = (FixedToInt(rawY) + 1) & texHeightMask; + MultiplyColorsInline(color, curTexPixels[texY * curTexWidth], &R, &G, &B, &A); + texturing = false; + } else { + a1 = PackedCol_A(color); + r1 = PackedCol_R(color); + g1 = PackedCol_G(color); + b1 = PackedCol_B(color); + } + + int step_ic0_per_x = FixedMul(dx12, factor); // bc0 += dx12 per x -> ic0 += step_ic0_per_x + int step_ic1_per_x = FixedMul(dx20, factor); // bc1 += dx20 + int step_ic2_per_x = FixedMul(dx01, factor); // bc2 += dx01 + + for (y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + int ic0 = FixedMul(bc0_start, factor); + int ic1 = FixedMul(bc1_start, factor); + int ic2 = FixedMul(bc2_start, factor); + + int w_interp = FixedMul(ic0, w0) + FixedMul(ic1, w1) + FixedMul(ic2, w2); + int step_w = FixedMul(step_ic0_per_x, w0) + FixedMul(step_ic1_per_x, w1) + FixedMul(step_ic2_per_x, w2); + + int z_interp = FixedMul(ic0, z0) + FixedMul(ic1, z1) + FixedMul(ic2, z2); + int step_z = FixedMul(step_ic0_per_x, z0) + FixedMul(step_ic1_per_x, z1) + FixedMul(step_ic2_per_x, z2); + + int u_interp = FixedMul(ic0, u0) + FixedMul(ic1, u1) + FixedMul(ic2, u2); + int step_u = FixedMul(step_ic0_per_x, u0) + FixedMul(step_ic1_per_x, u1) + FixedMul(step_ic2_per_x, u2); + + int v_interp = FixedMul(ic0, v0) + FixedMul(ic1, v1) + FixedMul(ic2, v2); + int step_v = FixedMul(step_ic0_per_x, v0) + FixedMul(step_ic1_per_x, v1) + FixedMul(step_ic2_per_x, v2); + + int bc0 = bc0_start; + int bc1 = bc1_start; + int bc2 = bc2_start; + + for (x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + if (ic0 < 0 || ic1 < 0 || ic2 < 0) { + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int db_index = y * db_stride + x; + + if (w_interp == 0) { + // update and skip + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int w = FixedReciprocal(w_interp); + int z = FixedMul(z_interp, w); + + if (depthTest && (z < 0 || z > depthBuffer[db_index])) { + // update and continue + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + if (!colWrite) { + if (depthWrite) depthBuffer[db_index] = z; + // update and continue + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + continue; + } + + int Rloc = R, Gloc = G, Bloc = B, Aloc = A; // local copy (non-texturing path keeps them) + + if (texturing) { + int u = FixedMul(u_interp, w); + int v = FixedMul(v_interp, w); + + int texX = FixedToInt(u) & texWidthMask; + int texY = FixedToInt(v) & texHeightMask; + + int texIndex = texY * curTexWidth + texX; + BitmapCol tColor = curTexPixels[texIndex]; + + int ta = BitmapCol_A(tColor); + int tr = BitmapCol_R(tColor); + int tg = BitmapCol_G(tColor); + int tb = BitmapCol_B(tColor); + + Aloc = (a1 * ta) >> 8; + Rloc = (r1 * tr) >> 8; + Gloc = (g1 * tg) >> 8; + Bloc = (b1 * tb) >> 8; + } + + if (gfx_alphaTest && Aloc < 0x80) { + // update and continue + if (depthWrite) ; // nothing + } else { + if (depthWrite) depthBuffer[db_index] = z; + int cb_index = y * cb_stride + x; + + if (!gfx_alphaBlend) { + colorBuffer[cb_index] = BitmapCol_Make(Rloc, Gloc, Bloc, 0xFF); + } else { + BitmapCol dst = colorBuffer[cb_index]; + int dstR = BitmapCol_R(dst); + int dstG = BitmapCol_G(dst); + int dstB = BitmapCol_B(dst); + + int finR = (Rloc * Aloc + dstR * (255 - Aloc)) >> 8; + int finG = (Gloc * Aloc + dstG * (255 - Aloc)) >> 8; + int finB = (Bloc * Aloc + dstB * (255 - Aloc)) >> 8; + colorBuffer[cb_index] = BitmapCol_Make(finR, finG, finB, 0xFF); + } + } + + // update ic and interpolants + ic0 += step_ic0_per_x; ic1 += step_ic1_per_x; ic2 += step_ic2_per_x; + w_interp += step_w; z_interp += step_z; u_interp += step_u; v_interp += step_v; + } // x + } // y +} + + static void DrawTriangle2D(VertexFixed* V0, VertexFixed* V1, VertexFixed* V2) { int x0_fp = V0->x, y0_fp = V0->y; int x1_fp = V1->x, y1_fp = V1->y; @@ -999,30 +1322,58 @@ static cc_bool TriangleFullyInsideFrustum(const VertexFixed tri[3]) { return true; } -static void DrawClippedFixed(int mask, VertexFixed* v0, VertexFixed* v1, VertexFixed* v2, VertexFixed* v3) { - VertexFixed inTri[3], outPoly[16]; - int polyCount; - - // Triangle 1: v0, v1, v2 - inTri[0] = *v0; inTri[1] = *v1; inTri[2] = *v2; - if (TriangleFullyInsideFrustum(inTri)) { - // fully inside - ProcessClippedTriangleAndDraw(inTri, 3); - } else { - polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); - if (polyCount > 0) ProcessClippedTriangleAndDraw(outPoly, polyCount); +static int ClipQuadToFrustumFixed(const VertexFixed quad[4], VertexFixed* outPoly) { + VertexFixed buf1[16], buf2[16]; + VertexFixed* src = buf1; + VertexFixed* dst = buf2; + + for (int i = 0; i < 4; i++) src[i] = quad[i]; + int count = 4; + + // check w zero + for (int i = 0; i < 4; i++) if (src[i].w == 0) return 0; + + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + + for (int p = 0; p < 6; p++) { + int newCount = ClipPolygonPlaneFixed(src, count, dst, planes[p]); + if (newCount == 0) return 0; + // swap + VertexFixed* tmp = src; src = dst; dst = tmp; + count = newCount; + if (count > 15) count = 15; } - - // Triangle 2: v2, v3, v0 - inTri[0] = *v2; inTri[1] = *v3; inTri[2] = *v0; - if (TriangleFullyInsideFrustum(inTri)) { - ProcessClippedTriangleAndDraw(inTri, 3); - } else { - polyCount = ClipTriangleToFrustumFixed(inTri, outPoly); - if (polyCount > 0) ProcessClippedTriangleAndDraw(outPoly, polyCount); + + for (int i = 0; i < count; i++) outPoly[i] = src[i]; + return count; +} +static cc_bool QuadFullyInsideFrustum(const VertexFixed quad[4]) { + const int planes[6] = { PLANE_LEFT, PLANE_RIGHT, PLANE_BOTTOM, PLANE_TOP, PLANE_NEAR, PLANE_FAR }; + for (int p = 0; p < 6; p++) { + for (int i = 0; i < 4; i++) { + if (PlaneDistFixed(&quad[i], planes[p]) < 0) return false; + } + } + return true; +} + +static void DrawClippedFixed(int mask, VertexFixed* v0, VertexFixed* v1, VertexFixed* v2, VertexFixed* v3) { + VertexFixed quad[4] = { *v0, *v1, *v2, *v3 }; + VertexFixed outPoly[16]; + int polyCount; + + if (QuadFullyInsideFrustum(quad)) { + ProcessClippedTriangleAndDraw(quad, 4); + return; + } + + polyCount = ClipQuadToFrustumFixed(quad, outPoly); + if (polyCount > 0) { + ProcessClippedTriangleAndDraw(outPoly, polyCount); } } + #define V0_VIS (1 << 0) #define V1_VIS (1 << 1) #define V2_VIS (1 << 2) @@ -1039,6 +1390,18 @@ static void ClipLineFixed(const VertexFixed* v1, const VertexFixed* v2, VertexFi out->u = FixedMul(invt, v1->u) + FixedMul(t, v2->u); out->v = FixedMul(invt, v1->v) + FixedMul(t, v2->v); out->c = v1->c; //TODO: 色補完する? + /* + // Color linear interpolation + int aA = PackedCol_A(a->c), aR = PackedCol_R(a->c), aG = PackedCol_G(a->c), aB = PackedCol_B(a->c); + int bA = PackedCol_A(b->c), bR = PackedCol_R(b->c), bG = PackedCol_G(b->c), bB = PackedCol_B(b->c); + + int Acol = ((int64_t)invt * aA + (int64_t)t * bA) >> FP_SHIFT; + int Rcol = ((int64_t)invt * aR + (int64_t)t * bR) >> FP_SHIFT; + int Gcol = ((int64_t)invt * aG + (int64_t)t * bG) >> FP_SHIFT; + int Bcol = ((int64_t)invt * aB + (int64_t)t * bB) >> FP_SHIFT; + + out->c = PACKEDCOL(Rcol, Gcol, Bcol, Acol); + */ } void DrawQuadsFixed(int startVertex, int verticesCount, DrawHints hints) { From fab5b4a5aa87c1bb59cb0bf6490d7972f961bb4f Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 16 Sep 2025 07:16:15 +0300 Subject: [PATCH 093/115] NDS: Update the old Makefile paths --- misc/nds/Makefile | 10 +++++----- misc/nds/Makefile.arm7 | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/misc/nds/Makefile b/misc/nds/Makefile index 3c1871503..b10e01386 100644 --- a/misc/nds/Makefile +++ b/misc/nds/Makefile @@ -7,7 +7,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external GAME_TITLE := ClassiCube GAME_SUBTITLE := Built with BlocksDS GAME_AUTHOR := ClassiCube team -GAME_ICON := misc/ds/icon.bmp +GAME_ICON := misc/nds/icon.bmp GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_SUBTITLE);$(GAME_AUTHOR) @@ -36,15 +36,15 @@ endif all: $(ROM) clean: - $(MAKE) -f Makefile.arm9 clean --no-print-directory - $(MAKE) -f Makefile.arm7 clean --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm9 clean --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm7 clean --no-print-directory $(RM) $(ROM) $(BUILDDIR) $(SDIMAGE) arm9: - $(MAKE) -f misc/ds/Makefile.arm9 --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm9 --no-print-directory arm7: - $(MAKE) -f misc/ds/Makefile.arm7 --no-print-directory + $(MAKE) -f misc/nds/Makefile.arm7 --no-print-directory $(ROM): arm9 arm7 diff --git a/misc/nds/Makefile.arm7 b/misc/nds/Makefile.arm7 index b486d323b..6deb6c42c 100644 --- a/misc/nds/Makefile.arm7 +++ b/misc/nds/Makefile.arm7 @@ -6,7 +6,7 @@ export BLOCKSDSEXT ?= /opt/wonderful/thirdparty/blocksds/external export WONDERFUL_TOOLCHAIN ?= /opt/wonderful ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/ -SOURCEDIRS := misc/ds +SOURCEDIRS := misc/nds INCLUDEDIRS := DSIWIFI := third_party/dsiwifi From 19f625947b55d1a625ce8aa1c60db866cc68fb16 Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 16 Sep 2025 08:32:25 +0300 Subject: [PATCH 094/115] NDS: Fix level of header include paths --- src/nds/Graphics_NDS.c | 10 +++++----- src/nds/Platform_NDS.c | 22 +++++++++++----------- src/nds/Window_NDS.c | 22 +++++++++++----------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/nds/Graphics_NDS.c b/src/nds/Graphics_NDS.c index a96b92d49..414a7afd3 100644 --- a/src/nds/Graphics_NDS.c +++ b/src/nds/Graphics_NDS.c @@ -1,9 +1,9 @@ -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Logger.h" -#include "Window.h" +#include "../_GraphicsBase.h" +#include "../Errors.h" +#include "../Logger.h" +#include "../Window.h" #include -#include "_BlockAlloc.h" +#include "../_BlockAlloc.h" #define DS_MAT_PROJECTION 0 #define DS_MAT_POSITION 1 diff --git a/src/nds/Platform_NDS.c b/src/nds/Platform_NDS.c index e39bbc349..dd47bf40f 100644 --- a/src/nds/Platform_NDS.c +++ b/src/nds/Platform_NDS.c @@ -2,15 +2,15 @@ #define CC_NO_DYNLIB #define CC_XTEA_ENCRYPTION -#include "_PlatformBase.h" -#include "Stream.h" -#include "ExtMath.h" -#include "Funcs.h" -#include "Window.h" -#include "Utils.h" -#include "Errors.h" -#include "Options.h" -#include "Animations.h" +#include "../_PlatformBase.h" +#include "../Stream.h" +#include "../ExtMath.h" +#include "../Funcs.h" +#include "../Window.h" +#include "../Utils.h" +#include "../Errors.h" +#include "../Options.h" +#include "../Animations.h" #include #include @@ -31,7 +31,7 @@ #include #include #ifdef BUILD_DSI -#include "../third_party/dsiwifi/include/dsiwifi9.h" +#include #else #include #endif @@ -40,7 +40,7 @@ #include #include #include -#include "_PlatformConsole.h" +#include "../_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; // not used const cc_result ReturnCode_FileNotFound = ENOENT; diff --git a/src/nds/Window_NDS.c b/src/nds/Window_NDS.c index 32e49b3be..c8907a1ad 100644 --- a/src/nds/Window_NDS.c +++ b/src/nds/Window_NDS.c @@ -1,14 +1,14 @@ -#include "Window.h" -#include "Platform.h" -#include "Input.h" -#include "Event.h" -#include "Graphics.h" -#include "String.h" -#include "Funcs.h" -#include "Bitmap.h" -#include "Errors.h" -#include "ExtMath.h" -#include "Camera.h" +#include "../Window.h" +#include "../Platform.h" +#include "../Input.h" +#include "../Event.h" +#include "../Graphics.h" +#include "../String.h" +#include "../Funcs.h" +#include "../Bitmap.h" +#include "../Errors.h" +#include "../ExtMath.h" +#include "../Camera.h" #include #include #include From d606a2c7d34ebdd22d558b2ad36e5103f9b24cee Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 16 Sep 2025 07:18:30 +0300 Subject: [PATCH 095/115] Saturn: Update the yaul image version --- .github/workflows/build_saturn.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index 015d16a90..3e8edaf7a 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -16,13 +16,13 @@ jobs: timeout-minutes: 10 runs-on: ubuntu-latest container: - image: ijacquez/yaul:1.0.10 + image: ijacquez/yaul:latest steps: - uses: actions/checkout@v4 - name: Install prerequisites run: | - apt-get --allow-unauthenticated update - apt-get --allow-unauthenticated -y install curl + apt-get update + apt-get -y install curl - name: Compile Saturn build id: compile From a6398b12fad5882ea16293175c0a241def2d4b89 Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 16 Sep 2025 08:02:32 +0300 Subject: [PATCH 096/115] Saturn: Remove the problematic dependency fetch --- .github/workflows/build_saturn.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index 3e8edaf7a..6f6770477 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -19,11 +19,6 @@ jobs: image: ijacquez/yaul:latest steps: - uses: actions/checkout@v4 - - name: Install prerequisites - run: | - apt-get update - apt-get -y install curl - - name: Compile Saturn build id: compile run: | From c0bb55a83b5d8a2a10b0f96c527fd7d91162c04c Mon Sep 17 00:00:00 2001 From: Echo J Date: Tue, 16 Sep 2025 08:27:53 +0300 Subject: [PATCH 097/115] Saturn/NDS: Make ELF artifacts appear in Actions build --- .github/workflows/build_nds.yml | 4 ++-- misc/saturn/Makefile | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_nds.yml b/.github/workflows/build_nds.yml index 9ffd175fd..526ef7ed8 100644 --- a/.github/workflows/build_nds.yml +++ b/.github/workflows/build_nds.yml @@ -48,7 +48,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-nds/cc-arm9.elf' + SOURCE_FILE: 'build/nds/cc-arm9.elf' DEST_NAME: 'ClassiCube-nds.elf' - uses: ./.github/actions/upload_build @@ -60,7 +60,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-dsi/cc-arm9.elf' + SOURCE_FILE: 'build/dsi/cc-arm9.elf' DEST_NAME: 'ClassiCube-dsi.elf' diff --git a/misc/saturn/Makefile b/misc/saturn/Makefile index 52ba00908..9254d5baf 100644 --- a/misc/saturn/Makefile +++ b/misc/saturn/Makefile @@ -90,7 +90,10 @@ clean: $(BUILD_DIR)/$(TARGET).elf: $(SH_OBJS) $(SH_LD) $(foreach specs,$(SH_SPECS),-specs=$(specs)) $(SH_OBJS) $(SH_LDFLAGS) -o $@ -$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf +$(TARGET).elf: $(BUILD_DIR)/$(TARGET).elf + cp $< $@ + +$(BUILD_DIR)/$(TARGET).bin: $(TARGET).elf $(SH_OBJCOPY) -O binary $< $@ @[ -z "${SILENT}" ] && du -hs $@ | awk '{ print $$1; }' || true From 1fbf50dea488b9279b9679cd61afc1438cc0b987 Mon Sep 17 00:00:00 2001 From: oorange32 Date: Tue, 16 Sep 2025 15:51:04 +0900 Subject: [PATCH 098/115] add WinCE support --- Makefile | 13 +- src/Camera.c | 2 +- src/Core.h | 17 +- src/Game.c | 8 +- src/Platform.h | 10 +- src/Platform_WinCE.c | 781 +++++++++++++++++++++++++++++++++++++++++++ src/Window_WinCE.c | 693 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 1514 insertions(+), 10 deletions(-) create mode 100644 src/Platform_WinCE.c create mode 100644 src/Window_WinCE.c diff --git a/Makefile b/Makefile index d3bdfb065..1e84a4120 100644 --- a/Makefile +++ b/Makefile @@ -172,6 +172,15 @@ ifeq ($(PLAT),riscos) BUILD_DIR = build/riscos endif +ifeq ($(PLAT),wince) + CC = arm-mingw32ce-gcc + OEXT = .exe + CFLAGS += -march=armv5tej -mcpu=arm926ej-s -DUNICODE -D_WIN32_WCE + LDFLAGS = -g + LIBS = -lcoredll -lws2 + BUILD_DIR = build/wince +endif + ifdef BUILD_SDL2 CFLAGS += -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 LIBS += -lSDL2 @@ -228,7 +237,9 @@ serenityos: irix: $(MAKE) $(TARGET) PLAT=irix riscos: - $(MAKE) $(TARGET) PLAT=riscos + $(MAKE) $(TARGET) PLAT=riscos +wince: + $(MAKE) $(TARGET) PLAT=wince # Default overrides sdl2: $(MAKE) $(TARGET) BUILD_SDL2=1 diff --git a/src/Camera.c b/src/Camera.c index 30d98ab0f..a82a0d875 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -378,7 +378,7 @@ static void OnInit(void) { #ifdef CC_BUILD_WIN Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 40); -#elif defined CC_BUILD_SYMBIAN_3 || defined CC_BUILD_SYMBIAN_S60V5 +#elif defined CC_BUILD_SYMBIAN_3 || defined CC_BUILD_SYMBIAN_S60V5 || defined CC_BUILD_WINCE Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 70); #else Camera.Sensitivity = Options_GetInt(OPT_SENSITIVITY, 1, 200, 30); diff --git a/src/Core.h b/src/Core.h index 4ee2d6b48..7ff267c7e 100644 --- a/src/Core.h +++ b/src/Core.h @@ -213,7 +213,7 @@ typedef cc_uint8 cc_bool; #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_D3D11 #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_OPENAL #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL -#elif defined _WIN32 && !defined __WINSCW__ +#elif defined _WIN32 && !defined __WINSCW__ && !defined _WIN32_WCE #define CC_BUILD_WIN #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSSL @@ -652,6 +652,21 @@ typedef cc_uint8 cc_bool; #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 #define CC_DISABLE_ANIMATIONS #endif +#elif defined _WIN32_WCE + #define CC_BUILD_WINCE + #define CC_BUILD_NOMUSIC + #define CC_BUILD_NOSOUNDS + #define CC_BUILD_NOFPU + #undef CC_BUILD_ADVLIGHTING + #undef CC_BUILD_FREETYPE + #define CC_DISABLE_ANIMATIONS /* Very costly in FPU less system */ + #define CC_DISABLE_HELDBLOCK /* Very costly in FPU less system */ + #define CC_BUILD_TOUCH + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_WIN32CE + #define DEFAULT_NET_BACKEND CC_NET_BACKEND_BUILTIN + #define DEFAULT_AUD_BACKEND CC_AUD_BACKEND_NULL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTFP + #define DEFAULT_SSL_BACKEND CC_SSL_BACKEND_BEARSS #endif #endif diff --git a/src/Game.c b/src/Game.c index b51f4b613..7fb359889 100644 --- a/src/Game.c +++ b/src/Game.c @@ -885,9 +885,13 @@ void Game_Setup(void) { int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 0); /* No custom resolution has been set */ - if (width == 0 || height == 0) { + if (width == 0 || height == 0) { +#ifndef CC_BUILD_WINCE width = 854; height = 480; - if (DisplayInfo.Width < 854) width = 640; + if (DisplayInfo.Width < 854) width = 640; +#else + width = 240; height = 160; +#endif } String_InitArray(title, titleBuffer); diff --git a/src/Platform.h b/src/Platform.h index 6074e6421..da435ad89 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -8,7 +8,7 @@ Abstracts platform specific memory management, I/O, etc Copyright 2014-2025 ClassiCube | Licensed under BSD-3 */ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX #define _NL "\r\n" #define NATIVE_STR_LEN 300 #else @@ -20,7 +20,7 @@ Copyright 2014-2025 ClassiCube | Licensed under BSD-3 extern const char* Platform_AppNameSuffix; void* TempMem_Alloc(int size); -#if defined CC_BUILD_WIN +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE typedef struct cc_winstring_ { cc_unichar uni[NATIVE_STR_LEN]; /* String represented using UTF16 format */ char ansi[NATIVE_STR_LEN]; /* String lossily represented using ANSI format */ @@ -30,7 +30,7 @@ typedef struct cc_winstring_ { void Platform_EncodeString(cc_winstring* dst, const cc_string* src); #endif -#ifdef CC_BUILD_WIN +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE typedef cc_winstring cc_filepath; #else typedef struct cc_filepath_ { char buffer[NATIVE_STR_LEN]; } cc_filepath; @@ -245,7 +245,7 @@ int Stopwatch_ElapsedMS(cc_uint64 beg, cc_uint64 end); /*########################################################################################################################* *---------------------------------------------------------File I/O--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX typedef void* cc_file; #else typedef int cc_file; @@ -346,7 +346,7 @@ void Platform_LoadSysFonts(void); /*########################################################################################################################* *----------------------------------------------------------Sockets--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_WIN || defined CC_BUILD_XBOX +#if defined CC_BUILD_WIN || defined CC_BUILD_WINCE || defined CC_BUILD_XBOX typedef cc_uintptr cc_socket; #else typedef int cc_socket; diff --git a/src/Platform_WinCE.c b/src/Platform_WinCE.c new file mode 100644 index 000000000..93c290e6b --- /dev/null +++ b/src/Platform_WinCE.c @@ -0,0 +1,781 @@ +#include "Core.h" +#if defined CC_BUILD_WINCE + +#include "_PlatformBase.h" +#include "Stream.h" +#include "SystemFonts.h" +#include "Funcs.h" +#include "Utils.h" +#include "Errors.h" + +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#ifndef UNICODE +#define UNICODE +#define _UNICODE +#endif +#include +#include +#include +#include +#include + +static HANDLE heap; +const cc_result ReturnCode_FileShareViolation = ERROR_SHARING_VIOLATION; +const cc_result ReturnCode_FileNotFound = ERROR_FILE_NOT_FOUND; +const cc_result ReturnCode_DirectoryExists = ERROR_ALREADY_EXISTS; +const cc_result ReturnCode_SocketInProgess = WSAEINPROGRESS; +const cc_result ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK; +const cc_result ReturnCode_SocketDropped = WSAECONNRESET; + +const char* Platform_AppNameSuffix = " CE"; +cc_bool Platform_ReadonlyFilesystem; +cc_uint8 Platform_Flags = PLAT_FLAG_SINGLE_PROCESS; + +// Current directory management for Windows CE +static WCHAR current_directory[MAX_PATH] = L"\\"; +static cc_string Platform_NextArg(STRING_REF cc_string* args); + +static CRITICAL_SECTION dir_lock; +/*########################################################################################################################* +*-----------------------------------------------------Main entrypoint-----------------------------------------------------* +*#########################################################################################################################*/ +#include "main_impl.h" + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { + cc_result res; + SetupProgram(0, NULL); + + do { + res = RunProgram(0, NULL); + } while (Platform_IsSingleProcess() && Window_Main.Exists); + + Window_Free(); + ExitProcess(res); + return res; +} + +/*########################################################################################################################* +*---------------------------------------------------------Memory----------------------------------------------------------* +*#########################################################################################################################*/ + + +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + +void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapAlloc(heap, 0, size) : NULL; +} + +void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapAlloc(heap, HEAP_ZERO_MEMORY, size) : NULL; +} + +void* Mem_TryRealloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? HeapReAlloc(heap, 0, mem, size) : NULL; +} + +void Mem_Free(void* mem) { + if (mem) HeapFree(heap, 0, mem); +} + +/*########################################################################################################################* +*------------------------------------------------------Logging/Time-------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_Log(const char* msg, int len) { + WCHAR wbuf[2048]; + int wlen = MultiByteToWideChar(CP_UTF8, 0, msg, len, wbuf, 2047); + if (wlen > 0) { + wbuf[wlen] = 0; + OutputDebugStringW(wbuf); + OutputDebugStringW(L"\n"); + } +} + +#define FILETIME_EPOCH 50491123200ULL +#define FileTime_TotalSecs(time) ((time / 10000000) + FILETIME_EPOCH) + +TimeMS DateTime_CurrentUTC(void) { + SYSTEMTIME st; + FILETIME ft; + cc_uint64 raw; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + raw = ft.dwLowDateTime | ((cc_uint64)ft.dwHighDateTime << 32); + return FileTime_TotalSecs(raw); +} + +void DateTime_CurrentLocal(struct cc_datetime* t) { + SYSTEMTIME localTime; + GetLocalTime(&localTime); + + t->year = localTime.wYear; + t->month = localTime.wMonth; + t->day = localTime.wDay; + t->hour = localTime.wHour; + t->minute = localTime.wMinute; + t->second = localTime.wSecond; +} + +cc_uint64 Stopwatch_Measure(void) { + return GetTickCount(); +} + +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + return (end - beg) * 1000; // GetTickCount returns milliseconds +} + +/*########################################################################################################################* +*-------------------------------------------------------Crash handling----------------------------------------------------* +*#########################################################################################################################*/ +void CrashHandler_Install(void) { + // SetUnhandledExceptionFilter not available on Windows CE +} + +void Process_Abort2(cc_result result, const char* raw_msg) { + WCHAR wbuf[512]; + WCHAR fbuf[512]; + int wlen = MultiByteToWideChar(CP_UTF8, 0, raw_msg, -1, wbuf, 511); + if (wlen > 0) { + swprintf(fbuf, L"Error %s: 0x%04x", result, wbuf); + MessageBoxW(NULL, fbuf, L"Error", MB_OK | MB_ICONERROR); + } + ExitProcess(result); +} + +/*########################################################################################################################* +*-----------------------------------------------Current Directory Management---------------------------------------------* +*#########################################################################################################################*/ + +static void NormalizePath(WCHAR* path) { + WCHAR* src = path; + WCHAR* dst = path; + WCHAR* component_start; + + while (*src) { + if (*src == L'/' || *src == L'\\') { + *dst++ = L'\\'; + src++; + while (*src == L'/' || *src == L'\\') src++; + continue; + } + + component_start = dst; + while (*src && *src != L'/' && *src != L'\\') { + *dst++ = *src++; + } + + if (dst - component_start == 1 && component_start[0] == L'.') { + dst = component_start; + if (dst > path && dst[-1] == L'\\') dst--; + } else if (dst - component_start == 2 && component_start[0] == L'.' && component_start[1] == L'.') { + dst = component_start; + if (dst > path && dst[-1] == L'\\') dst--; + while (dst > path && dst[-1] != L'\\') dst--; + if (dst > path) dst--; + } + } + + if (dst == path) { + *dst++ = L'\\'; + } + *dst = L'\0'; +} + +static void SetCurrentDirectoryImpl(const WCHAR* path) { + EnterCriticalSection(&dir_lock); + + if (path[0] == L'\\') { + wcscpy(current_directory, path); + } else { + wcscat(current_directory, L"\\"); + wcscat(current_directory, path); + } + + NormalizePath(current_directory); + LeaveCriticalSection(&dir_lock); +} + +static void GetCurrentDirectoryImpl(WCHAR* buffer, DWORD size) { + EnterCriticalSection(&dir_lock); + wcsncpy(buffer, current_directory, size - 1); + buffer[size - 1] = L'\0'; + LeaveCriticalSection(&dir_lock); +} + +static void MakeAbsolutePath(const WCHAR* relative_path, WCHAR* absolute_path, DWORD size) { + if (relative_path[0] == L'\\') { + wcsncpy(absolute_path, relative_path, size - 1); + } else { + GetCurrentDirectoryImpl(absolute_path, size); + if (wcslen(absolute_path) + wcslen(relative_path) + 2 < size) { + wcscat(absolute_path, L"\\"); + wcscat(absolute_path, relative_path); + } + } + absolute_path[size - 1] = L'\0'; + NormalizePath(absolute_path); +} +/*########################################################################################################################* +*-----------------------------------------------------Directory/File------------------------------------------------------* +*#########################################################################################################################*/ +void Directory_GetCachePath(cc_string* path) { + String_AppendConst(path, "\\cache"); +} + +void Platform_EncodePath(cc_filepath* dst, const cc_string* src) { + Platform_EncodeString(dst, src); +} + +cc_result Directory_Create(const cc_filepath* path) { + WCHAR fullPath[MAX_PATH]; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + return CreateDirectoryW(fullPath, NULL) ? 0 : GetLastError(); +} + +int File_Exists(const cc_filepath* path) { + WCHAR fullPath[MAX_PATH]; + DWORD attribs; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + + attribs = GetFileAttributesW(fullPath); + return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY); +} + +static cc_result Directory_EnumCore(const cc_string* dirPath, const cc_string* file, DWORD attribs, + void* obj, Directory_EnumCallback callback) { + cc_string path; char pathBuffer[MAX_PATH + 10]; + int is_dir; + + if (file->length == 1 && file->buffer[0] == '.') return 0; + if (file->length == 2 && file->buffer[0] == '.' && file->buffer[1] == '.') return 0; + + String_InitArray(path, pathBuffer); + String_Format2(&path, "%s/%s", dirPath, file); + + is_dir = attribs & FILE_ATTRIBUTE_DIRECTORY; + callback(&path, obj, is_dir); + return 0; +} + +cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { + cc_string path; char pathBuffer[MAX_PATH + 10]; + WIN32_FIND_DATAW eW; + cc_filepath str; + HANDLE find; + cc_result res; + int i; + + String_InitArray(path, pathBuffer); + String_Format1(&path, "%s\\*", dirPath); + Platform_EncodePath(&str, &path); + + find = FindFirstFileW(str.uni, &eW); + if (find == INVALID_HANDLE_VALUE) return GetLastError(); + + do { + path.length = 0; + for (i = 0; i < MAX_PATH && eW.cFileName[i]; i++) { + // Convert wide char to UTF-8 + char utf8[4]; + int len = WideCharToMultiByte(CP_UTF8, 0, &eW.cFileName[i], 1, utf8, 4, NULL, NULL); + for (int j = 0; j < len; j++) { + String_Append(&path, utf8[j]); + } + } + if ((res = Directory_EnumCore(dirPath, &path, eW.dwFileAttributes, obj, callback))) return res; + } while (FindNextFileW(find, &eW)); + + res = GetLastError(); + FindClose(find); + return res == ERROR_NO_MORE_FILES ? 0 : res; +} + +static cc_result DoFile(cc_file* file, const cc_filepath* path, DWORD access, DWORD createMode) { + WCHAR fullPath[MAX_PATH]; + + MakeAbsolutePath(path->uni, fullPath, MAX_PATH); + + *file = CreateFileW(fullPath, access, FILE_SHARE_READ, NULL, createMode, 0, NULL); + return *file != INVALID_HANDLE_VALUE ? 0 : GetLastError(); +} + +cc_result File_Open(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_READ, OPEN_EXISTING); +} + +cc_result File_Create(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_WRITE | GENERIC_READ, CREATE_ALWAYS); +} + +cc_result File_OpenOrCreate(cc_file* file, const cc_filepath* path) { + return DoFile(file, path, GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS); +} + +cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { + BOOL success = ReadFile(file, data, count, (DWORD*)bytesRead, NULL); + return success ? 0 : GetLastError(); +} + +cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) { + BOOL success = WriteFile(file, data, count, (DWORD*)bytesWrote, NULL); + return success ? 0 : GetLastError(); +} + +cc_result File_Close(cc_file file) { + return CloseHandle(file) ? 0 : GetLastError(); +} + +cc_result File_Seek(cc_file file, int offset, int seekType) { + static cc_uint8 modes[] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; + DWORD pos = SetFilePointer(file, offset, NULL, modes[seekType]); + return pos != INVALID_SET_FILE_POINTER ? 0 : GetLastError(); +} + +cc_result File_Position(cc_file file, cc_uint32* pos) { + *pos = SetFilePointer(file, 0, NULL, FILE_CURRENT); + return *pos != INVALID_SET_FILE_POINTER ? 0 : GetLastError(); +} + +cc_result File_Length(cc_file file, cc_uint32* len) { + *len = GetFileSize(file, NULL); + return *len != INVALID_FILE_SIZE ? 0 : GetLastError(); +} + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +void Thread_Sleep(cc_uint32 milliseconds) { + Sleep(milliseconds); +} + +static DWORD WINAPI ExecThread(void* param) { + Thread_StartFunc func = (Thread_StartFunc)param; + func(); + return 0; +} + +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + DWORD threadID; + HANDLE thread = CreateThread(NULL, stackSize, ExecThread, (void*)func, 0, &threadID); + if (!thread) Process_Abort2(GetLastError(), "Creating thread"); + *handle = thread; +} + +void Thread_Detach(void* handle) { + if (!CloseHandle((HANDLE)handle)) { + Process_Abort2(GetLastError(), "Freeing thread handle"); + } +} + +void Thread_Join(void* handle) { + WaitForSingleObject((HANDLE)handle, INFINITE); + Thread_Detach(handle); +} + +void* Mutex_Create(const char* name) { + CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex"); + InitializeCriticalSection(ptr); + return ptr; +} + +void Mutex_Free(void* handle) { + DeleteCriticalSection((CRITICAL_SECTION*)handle); + Mem_Free(handle); +} + +void Mutex_Lock(void* handle) { + EnterCriticalSection((CRITICAL_SECTION*)handle); +} + +void Mutex_Unlock(void* handle) { + LeaveCriticalSection((CRITICAL_SECTION*)handle); +} + +void* Waitable_Create(const char* name) { + void* handle = CreateEventW(NULL, false, false, NULL); + if (!handle) { + Process_Abort2(GetLastError(), "Creating waitable"); + } + return handle; +} + +void Waitable_Free(void* handle) { + if (!CloseHandle((HANDLE)handle)) { + Process_Abort2(GetLastError(), "Freeing waitable"); + } +} + +void Waitable_Signal(void* handle) { + SetEvent((HANDLE)handle); +} + +void Waitable_Wait(void* handle) { + WaitForSingleObject((HANDLE)handle, INFINITE); +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { + WaitForSingleObject((HANDLE)handle, milliseconds); +} + +/*########################################################################################################################* +*--------------------------------------------------------Font/Text--------------------------------------------------------* +*#########################################################################################################################*/ +static void FontDirCallback(const cc_string* path, void* obj, int isDirectory) { + if (isDirectory) { + Directory_Enum(path, NULL, FontDirCallback); + } else { + SysFonts_Register(path, NULL); + } +} + +void Platform_LoadSysFonts(void) { + cc_string fontDir = String_FromConst("\\Windows\\Fonts"); + Directory_Enum(&fontDir, NULL, FontDirCallback); +} + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +static char sockaddr_size_check[sizeof(SOCKADDR_STORAGE) < CC_SOCKETADDR_MAXSIZE ? 1 : -1]; + +static cc_bool ParseIPv4(const cc_string* ip, int port, cc_sockaddr* dst) { + SOCKADDR_IN* addr4 = (SOCKADDR_IN*)dst->data; + cc_uint32 ip_addr; + if (!ParseIPv4Address(ip, &ip_addr)) return false; + + addr4->sin_addr.S_un.S_addr = ip_addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + + dst->size = sizeof(*addr4); + return true; +} + +static cc_bool ParseIPv6(const char* ip, int port, cc_sockaddr* dst) { + return false; +} + +static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { + struct hostent* res = gethostbyname(host); + SOCKADDR_IN* addr4; + char* src_addr; + int i; + + if (!res) { + cc_result wsa_res = WSAGetLastError(); + if (wsa_res == WSAHOST_NOT_FOUND) return SOCK_ERR_UNKNOWN_HOST; + return ERR_INVALID_ARGUMENT; + } + + if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT; + if (!res->h_addr_list) return ERR_INVALID_ARGUMENT; + + for (i = 0; i < SOCKET_MAX_ADDRS; i++) { + src_addr = res->h_addr_list[i]; + if (!src_addr) break; + addrs[i].size = sizeof(SOCKADDR_IN); + + addr4 = (SOCKADDR_IN*)addrs[i].data; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(port); + addr4->sin_addr = *(IN_ADDR*)src_addr; + } + + *numValidAddrs = i; + return i == 0 ? ERR_INVALID_ARGUMENT : 0; +} +cc_result Socket_Create(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + SOCKADDR* raw_addr = (SOCKADDR*)addr->data; + *s = socket(raw_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); + if (*s == INVALID_SOCKET) return WSAGetLastError(); + + if (nonblocking) { + u_long blockingMode = 1; + ioctlsocket(*s, FIONBIO, &blockingMode); + } + return 0; +} + +cc_result Socket_Connect(cc_socket s, cc_sockaddr* addr) { + SOCKADDR* raw_addr = (SOCKADDR*)addr->data; + int res = connect(s, raw_addr, addr->size); + return res == SOCKET_ERROR ? WSAGetLastError() : 0; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + int recvCount = recv(s, (char*)data, count, 0); + if (recvCount != SOCKET_ERROR) { *modified = recvCount; return 0; } + *modified = 0; return WSAGetLastError(); +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + int sentCount = send(s, (const char*)data, count, 0); + if (sentCount != SOCKET_ERROR) { *modified = sentCount; return 0; } + *modified = 0; return WSAGetLastError(); +} + +void Socket_Close(cc_socket s) { + shutdown(s, SD_BOTH); + closesocket(s); +} + +static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) { + fd_set set; + struct timeval time = { 0 }; + int selectCount; + + FD_ZERO(&set); + FD_SET(s, &set); + + if (mode == SOCKET_POLL_READ) { + selectCount = select(0, &set, NULL, NULL, &time); + } else { + selectCount = select(0, NULL, &set, NULL, &time); + } + + if (selectCount == SOCKET_ERROR) { *success = false; return WSAGetLastError(); } + *success = FD_ISSET(s, &set) != 0; return 0; +} + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return Socket_Poll(s, SOCKET_POLL_READ, readable); +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + int resultSize = sizeof(cc_result); + cc_result res = Socket_Poll(s, SOCKET_POLL_WRITE, writable); + if (res || *writable) return res; + + getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&res, &resultSize); + return res; +} + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Process_OpenSupported = false; + +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + return SetGameArgs(args, numArgs); +} + +void Process_Exit(cc_result code) { + ExitProcess(code); +} + +cc_result Process_StartOpen(const cc_string* args) { + return ERR_NOT_SUPPORTED; +} + +/*########################################################################################################################* +*--------------------------------------------------------Updater----------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Updater_Supported = false; +const struct UpdaterInfo Updater_Info = { "&eUpdate not supported on Windows CE", 0 }; + +cc_bool Updater_Clean(void) { return true; } +cc_result Updater_Start(const char** action) { return ERR_NOT_SUPPORTED; } +cc_result Updater_GetBuildTime(cc_uint64* timestamp) { return ERR_NOT_SUPPORTED; } +cc_result Updater_MarkExecutable(void) { return 0; } +cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { return ERR_NOT_SUPPORTED; } + +/*########################################################################################################################* +*-------------------------------------------------------Dynamic lib-------------------------------------------------------* +*#########################################################################################################################*/ +const cc_string DynamicLib_Ext = String_FromConst(".dll"); +static cc_result dynamicErr; + +void* DynamicLib_Load2(const cc_string* path) { + cc_filepath str; + void* lib; + + Platform_EncodePath(&str, path); + lib = LoadLibraryW(str.uni); + if (!lib) dynamicErr = GetLastError(); + return lib; +} + +void* DynamicLib_Get2(void* lib, const char* name) { + WCHAR wname[256]; + MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, 256); + + void* addr = GetProcAddressW((HMODULE)lib, wname); + if (!addr) dynamicErr = GetLastError(); + return addr; +} + +cc_bool DynamicLib_DescribeError(cc_string* dst) { + cc_result res = dynamicErr; + dynamicErr = 0; + Platform_DescribeError(res, dst); + String_Format1(dst, " (error %e)", &res); + return true; +} + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_EncodeString(cc_winstring* dst, const cc_string* src) { + int i; + + MultiByteToWideChar(CP_UTF8, 0, src->buffer, src->length, dst->uni, NATIVE_STR_LEN - 1); + dst->uni[src->length] = 0; + + WideCharToMultiByte(CP_ACP, 0, dst->uni, -1, dst->ansi, NATIVE_STR_LEN - 1, NULL, NULL); +} + +void Platform_Init(void) { + WSADATA wsaData; + cc_result res; + + heap = GetProcessHeap(); + + res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (res) Logger_SysWarn(res, "starting WSA"); +} + +void Platform_Free(void) { + WSACleanup(); +} + +cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { + WCHAR chars[NATIVE_STR_LEN]; + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + + res = FormatMessageW(flags, NULL, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + chars, NATIVE_STR_LEN, NULL); + if (!res) return false; + + String_AppendUtf16(dst, chars, res * 2); + return true; +} + +/*########################################################################################################################* +*-------------------------------------------------------Encryption--------------------------------------------------------* +*#########################################################################################################################*/ +static const cc_uint8 xor_key[] = { 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x9A }; + +cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { + const cc_uint8* bytes = (const cc_uint8*)data; + int i; + + for (i = 0; i < len; i++) { + String_Append(dst, bytes[i] ^ xor_key[i % 8]); + } + return 0; +} + +cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { + const cc_uint8* bytes = (const cc_uint8*)data; + int i; + + for (i = 0; i < len; i++) { + String_Append(dst, bytes[i] ^ xor_key[i % 8]); + } + return 0; +} + +cc_result Platform_GetEntropy(void* data, int len) { + // Simple random generator + static cc_uint32 seed = 1; + cc_uint8* bytes = (cc_uint8*)data; + int i; + + if (seed == 1) { + seed = GetTickCount(); + } + + for (i = 0; i < len; i++) { + seed = seed * 1103515245 + 12345; + bytes[i] = (cc_uint8)(seed >> 8); + } + return 0; +} + +/*########################################################################################################################* +*-----------------------------------------------------Configuration-------------------------------------------------------* +*#########################################################################################################################*/ +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + LPWSTR cmdLine = GetCommandLineW(); + char cmdLineUtf8[1024]; + cc_string cmdArgs; + int i; + + if (gameHasArgs) return GetGameArgs(args); + + WideCharToMultiByte(CP_UTF8, 0, cmdLine, -1, cmdLineUtf8, 1024, NULL, NULL); + cmdArgs = String_FromReadonly(cmdLineUtf8); + + Platform_NextArg(&cmdArgs); + + for (i = 0; i < GAME_MAX_CMDARGS; i++) { + args[i] = Platform_NextArg(&cmdArgs); + if (!args[i].length) break; + } + return i; +} + +static cc_string Platform_NextArg(STRING_REF cc_string* args) { + cc_string arg; + int end; + + // Remove leading spaces + while (args->length && args->buffer[0] == ' ') { + *args = String_UNSAFE_SubstringAt(args, 1); + } + + if (args->length && args->buffer[0] == '"') { + // Quoted argument + *args = String_UNSAFE_SubstringAt(args, 1); + end = String_IndexOf(args, '"'); + } else { + end = String_IndexOf(args, ' '); + } + + if (end == -1) { + arg = *args; + args->length = 0; + } else { + arg = String_UNSAFE_Substring(args, 0, end); + *args = String_UNSAFE_SubstringAt(args, end + 1); + } + return arg; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char** argv) { + WCHAR module_path[MAX_PATH]; + WCHAR* last_slash; + DWORD len; + + len = GetModuleFileNameW(NULL, module_path, MAX_PATH); + if (len == 0) { + SetCurrentDirectoryImpl(L"\\"); + return 0; + } + + last_slash = wcsrchr(module_path, L'\\'); + if (last_slash) { + *last_slash = L'\0'; + SetCurrentDirectoryImpl(module_path); + } else { + SetCurrentDirectoryImpl(L"\\"); + } + + return 0; +} + + +#endif diff --git a/src/Window_WinCE.c b/src/Window_WinCE.c new file mode 100644 index 000000000..04f7c9ede --- /dev/null +++ b/src/Window_WinCE.c @@ -0,0 +1,693 @@ +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_WIN32CE +/* + The Open Toolkit Library License + + Copyright (c) 2006 - 2009 the Open Toolkit library. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "_WindowBase.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Options.h" +#include "Errors.h" +#include "Gui.h" + +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#ifndef UNICODE +#define UNICODE +#define _UNICODE +#endif + +#include +#include + +/* https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelformat */ +#define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN +#define CC_WIN_CLASSNAME TEXT("ClassiCube_Window") +#define Rect_Width(rect) (rect.right - rect.left) +#define Rect_Height(rect) (rect.bottom - rect.top) + +static HINSTANCE win_instance; +static HDC win_DC; +static cc_bool suppress_resize; +static cc_bool is_ansiWindow, grabCursor; +static int windowX, windowY; + +static const cc_uint8 key_map[] = { +/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 08 */ CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, CCKEY_F5, CCKEY_ENTER, 0, 0, +/* 10 */ 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, +/* 18 */ 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, +/* 20 */ CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, +/* 28 */ CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0, +/* 30 */ '0', '1', '2', '3', '4', '5', '6', '7', +/* 38 */ '8', '9', 0, 0, 0, 0, 0, 0, +/* 40 */ 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', +/* 48 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', +/* 50 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', +/* 58 */ 'X', 'Y', 'Z', CCKEY_LWIN, CCKEY_RWIN, CCKEY_MENU, 0, CCKEY_SLEEP, +/* 60 */ CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, +/* 68 */ CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MULTIPLY, CCKEY_KP_PLUS, 0, CCKEY_KP_MINUS, CCKEY_KP_DECIMAL, CCKEY_KP_DIVIDE, +/* 70 */ CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, +/* 78 */ CCKEY_F9, CCKEY_F10, CCKEY_F11, CCKEY_F12, CCKEY_F13, CCKEY_F14, CCKEY_F15, CCKEY_F16, +/* 80 */ CCKEY_F17, CCKEY_F18, CCKEY_F19, CCKEY_F20, CCKEY_F21, CCKEY_F22, CCKEY_F23, CCKEY_F24, +/* 88 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 90 */ CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, 0, 0, 0, 0, 0, 0, +/* 98 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* A0 */ CCKEY_LSHIFT, CCKEY_RSHIFT, CCKEY_LCTRL, CCKEY_RCTRL, CCKEY_LALT, CCKEY_RALT, CCKEY_BROWSER_PREV, CCKEY_BROWSER_NEXT, +/* A8 */ CCKEY_BROWSER_REFRESH, CCKEY_BROWSER_STOP, CCKEY_BROWSER_SEARCH, CCKEY_BROWSER_FAVORITES, CCKEY_BROWSER_HOME, CCKEY_VOLUME_MUTE, CCKEY_VOLUME_DOWN, CCKEY_VOLUME_UP, +/* B0 */ CCKEY_MEDIA_NEXT, CCKEY_MEDIA_PREV, CCKEY_MEDIA_STOP, CCKEY_MEDIA_PLAY, CCKEY_LAUNCH_MAIL, CCKEY_LAUNCH_MEDIA, CCKEY_LAUNCH_APP1, CCKEY_LAUNCH_CALC, +/* B8 */ 0, 0, CCKEY_SEMICOLON, CCKEY_EQUALS, CCKEY_COMMA, CCKEY_MINUS, CCKEY_PERIOD, CCKEY_SLASH, +/* C0 */ CCKEY_TILDE, 0, 0, 0, 0, 0, 0, 0, +/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D8 */ 0, 0, 0, CCKEY_LBRACKET, CCKEY_BACKSLASH, CCKEY_RBRACKET, CCKEY_QUOTE, 0, +}; + +static int MapNativeKey(WPARAM vk_key, LPARAM meta) { + LPARAM ext = meta & (1UL << 24); + LPARAM scancode = (meta >> 16) & 0xFF; + int key; + if (ext) scancode |= 0xE000; + + switch (vk_key) + { + case VK_CONTROL: + return ext ? CCKEY_RCTRL : CCKEY_LCTRL; + case VK_MENU: + return ext ? CCKEY_RALT : CCKEY_LALT; + case VK_RETURN: + return ext ? CCKEY_KP_ENTER : CCKEY_ENTER; + } + + key = vk_key < Array_Elems(key_map) ? key_map[vk_key] : 0; + if (!key) Platform_Log2("Unknown key: %x, %x", &vk_key, &scancode); + return key; +} + +static cc_bool RefreshWindowDimensions(void) { + HWND hwnd = Window_Main.Handle.ptr; + RECT rect; + int width = Window_Main.Width, height = Window_Main.Height; + + GetClientRect(hwnd, &rect); + Window_Main.Width = Rect_Width(rect); + Window_Main.Height = Rect_Height(rect); + + return width != Window_Main.Width || height != Window_Main.Height; +} + +static void RefreshWindowPosition(void) { + HWND hwnd = Window_Main.Handle.ptr; + POINT topLeft = { 0, 0 }; + /* GetClientRect always returns 0,0 for left,top (see MSDN) */ + ClientToScreen(hwnd, &topLeft); + windowX = topLeft.x; windowY = topLeft.y; +} + +static void GrabCursor(void) { +#ifndef CC_BUILD_TOUCH + HWND hwnd = Window_Main.Handle.ptr; + RECT rect; + if (!grabCursor || !Input.RawMode) return; + + GetWindowRect(hwnd, &rect); + ClipCursor(&rect); +#endif +} + +static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { + float wheelDelta; + cc_bool sized; + HWND hwnd; + + switch (message) { + case WM_ACTIVATE: + Window_Main.Focused = LOWORD(wParam) != 0; + Event_RaiseVoid(&WindowEvents.FocusChanged); + break; + + case WM_ERASEBKGND: + return 1; /* Avoid flickering */ + + case WM_PAINT: + { + hwnd = Window_Main.Handle.ptr; + //ValidateRect(hwnd, NULL); + PAINTSTRUCT ps; + HWND hwnd = Window_Main.Handle.ptr; + HDC hdc = BeginPaint(handle, &ps); + EndPaint(handle, &ps); + Event_RaiseVoid(&WindowEvents.RedrawNeeded); + return 0; + } + + case WM_SIZE: + sized = RefreshWindowDimensions(); + + if (sized && !suppress_resize) Event_RaiseVoid(&WindowEvents.Resized); + Event_RaiseVoid(&WindowEvents.StateChanged); + break; + + case WM_MOVE: + RefreshWindowPosition(); + break; + + case WM_CHAR: + /* TODO: Use WM_UNICHAR instead, as WM_CHAR is just utf16 */ + Event_RaiseInt(&InputEvents.Press, (cc_unichar)wParam); + break; + +#ifndef CC_BUILD_TOUCH + case WM_MOUSEMOVE: + /* Set before position change, in case mouse buttons changed when outside window */ + if (!(wParam & 0x01)) Input_SetReleased(CCMOUSE_L); + //Input_SetNonRepeatable(CCMOUSE_L, wParam & 0x01); + Input_SetNonRepeatable(CCMOUSE_R, wParam & 0x02); + Input_SetNonRepeatable(CCMOUSE_M, wParam & 0x10); + /* TODO: do we need to set XBUTTON1/XBUTTON2 here */ + Pointer_SetPosition(0, LOWORD(lParam), HIWORD(lParam)); + break; +#else + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) + Input_UpdateTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; +#endif + case WM_MOUSEWHEEL: + wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; + Mouse_ScrollVWheel(wheelDelta); + return 0; +#ifndef CC_BUILD_TOUCH + case WM_LBUTTONDOWN: + Input_SetPressed(CCMOUSE_L); break; +#else + case WM_LBUTTONDOWN: + Input_AddTouch(0, (short)LOWORD(lParam), (short)HIWORD(lParam)); + break; +#endif + case WM_MBUTTONDOWN: + Input_SetPressed(CCMOUSE_M); break; + case WM_RBUTTONDOWN: + Input_SetPressed(CCMOUSE_R); break; + +#ifndef CC_BUILD_TOUCH + case WM_LBUTTONUP: + Input_SetReleased(CCMOUSE_L); break; +#else + case WM_LBUTTONUP: + Input_RemoveTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; +#endif + case WM_MBUTTONUP: + Input_SetReleased(CCMOUSE_M); break; + case WM_RBUTTONUP: + Input_SetReleased(CCMOUSE_R); break; + + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + { + cc_bool pressed = message == WM_KEYDOWN || message == WM_SYSKEYDOWN; + /* Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed + and released. It looks like neither key is released in this case, or that the wrong key is + released in the case of Control and Alt. + To combat this, we are going to release both keys when either is released. Hacky, but should work. + Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). + In this case, both keys will be reported as pressed. */ + cc_bool lShiftDown, rShiftDown; + int key; + + if (wParam == VK_SHIFT) { + /* The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit + to distinguish between left and right keys. Moreover, pressing both keys and releasing one + may result in both keys being held down (but not always).*/ + lShiftDown = ((USHORT)GetKeyState(VK_LSHIFT)) >> 15; + rShiftDown = ((USHORT)GetKeyState(VK_RSHIFT)) >> 15; + + if (!pressed || lShiftDown != rShiftDown) { + Input_Set(CCKEY_LSHIFT, lShiftDown); + Input_Set(CCKEY_RSHIFT, rShiftDown); + } + } else { + key = MapNativeKey(wParam, lParam); + if (key) Input_Set(key, pressed); + } + return 0; + } break; + + case WM_SYSCHAR: + return 0; + + case WM_KILLFOCUS: + /* TODO: Keep track of keyboard when focus is lost */ +#ifndef CC_BUILD_TOUCH + Input_Clear(); +#else + Input_SetTouchMode(TRUE); +#endif + break; + + case WM_CLOSE: + Window_Main.Exists = false; + Window_RequestClose(); + return 0; + + case WM_DESTROY: + UnregisterClassW(CC_WIN_CLASSNAME, win_instance); + break; + } + return DefWindowProc(handle, message, wParam, lParam); +} + + +/*########################################################################################################################* +*--------------------------------------------------Public implementation--------------------------------------------------* +*#########################################################################################################################*/ +void Window_PreInit(void) { + DisplayInfo.CursorVisible = true; +} + +void Window_Init(void) { + HDC hdc; + Input.Sources = INPUT_SOURCE_NORMAL; + + hdc = GetDC(NULL); + DisplayInfo.Width = GetSystemMetrics(SM_CXSCREEN); + DisplayInfo.Height = GetSystemMetrics(SM_CYSCREEN); + DisplayInfo.Depth = GetDeviceCaps(hdc, BITSPIXEL); + DisplayInfo.ScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + DisplayInfo.ScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; + ReleaseDC(NULL, hdc); + + /* https://docs.microsoft.com/en-us/windows/win32/opengl/reading-color-values-from-the-framebuffer */ + /* https://devblogs.microsoft.com/oldnewthing/20101013-00/?p=12543 */ + /* TODO probably should always multiply? not just for 16 colors */ + if (DisplayInfo.Depth != 1) return; + DisplayInfo.Depth *= GetDeviceCaps(hdc, PLANES); + Input_SetTouchMode(TRUE); + //Gui_SetTouchUI(TRUE); +} + +void Window_Free(void) { } + +static ATOM DoRegisterClass(void) { + ATOM atom; + cc_result res; + WNDCLASSW wc = { 0 }; + wc.style = CS_OWNDC; /* https://stackoverflow.com/questions/48663815/getdc-releasedc-cs-owndc-with-opengl-and-gdi */ + wc.hInstance = win_instance; + wc.lpfnWndProc = Window_Procedure; + wc.lpszClassName = CC_WIN_CLASSNAME; + + wc.hIcon = (HICON)LoadImage(win_instance, MAKEINTRESOURCE(1), IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0); + wc.hCursor = LoadCursorW(NULL, IDC_ARROW); + + if ((atom = RegisterClass(&wc))) return atom; +} + +static HWND CreateWindowHandle(ATOM atom, int width, int height) { + cc_result res; + HWND hwnd; + RECT r; + + /* Calculate final window rectangle after window decorations are added (titlebar, borders etc) */ + r.left = Display_CentreX(width); r.right = r.left + width; + r.top = Display_CentreY(height); r.bottom = r.top + height; + AdjustWindowRectEx(&r, CC_WIN_STYLE, false, 0); + + + if ((hwnd = CreateWindowExW(0, CC_WIN_CLASSNAME, NULL, CC_WIN_STYLE, + r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return hwnd; + res = GetLastError(); + + Process_Abort2(res, "Failed to create window"); + return NULL; +} + +static void DoCreateWindow(int width, int height) { + ATOM atom; + HWND hwnd; + + win_instance = GetModuleHandle(NULL); + /* TODO: UngroupFromTaskbar(); */ + width = Display_ScaleX(width); + height = Display_ScaleY(height); + + atom = DoRegisterClass(); + hwnd = CreateWindowHandle(atom, width, height); + RefreshWindowDimensions(); + RefreshWindowPosition(); + + win_DC = GetDC(hwnd); + if (!win_DC) Process_Abort2(GetLastError(), "Failed to get device context"); + + Window_Main.Exists = true; + Window_Main.Handle.ptr = hwnd; + Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; + Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; + + grabCursor = Options_GetBool(OPT_GRAB_CURSOR, false); +} +void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } +void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } + +void Window_Destroy(void) { + HWND hwnd = Window_Main.Handle.ptr; + if (win_DC) ReleaseDC(hwnd, win_DC); + DestroyWindow(hwnd); +} + +void Window_SetTitle(const cc_string* title) { + HWND hwnd = Window_Main.Handle.ptr; + cc_winstring str; + Platform_EncodeString(&str, title); + SetWindowTextW(hwnd, str.uni); +} + +void Clipboard_GetText(cc_string* value) { + HWND hwnd = Window_Main.Handle.ptr; + cc_bool unicode; + HANDLE hGlobal; + SIZE_T size; + void* src; + int i; + + /* retry up to 50 times */ + for (i = 0; i < 50; i++) { + if (!OpenClipboard(hwnd)) { + Thread_Sleep(10); + continue; + } + + unicode = true; + hGlobal = GetClipboardData(CF_UNICODETEXT); + if (!hGlobal) { + hGlobal = GetClipboardData(CF_TEXT); + unicode = false; + } + + if (!hGlobal) { CloseClipboard(); return; } + src = GlobalLock(hGlobal); + size = GlobalSize(hGlobal); + + /* ignore trailing NULL at end */ + /* TODO: Verify it's always there */ + if (unicode) { + String_AppendUtf16(value, src, size - 2); + } else { + String_AppendCP1252(value, src, size - 1); + } + + GlobalUnlock(hGlobal); + CloseClipboard(); + return; + } +} + +void Clipboard_SetText(const cc_string* value) { + HWND hwnd = Window_Main.Handle.ptr; + cc_unichar* text; + HANDLE hGlobal; + int i; + + /* retry up to 10 times */ + for (i = 0; i < 10; i++) { + if (!OpenClipboard(hwnd)) { + Thread_Sleep(100); + continue; + } + + hGlobal = GlobalAlloc(GMEM_MOVEABLE, (value->length + 1) * 2); + if (!hGlobal) { CloseClipboard(); return; } + + text = (cc_unichar*)GlobalLock(hGlobal); + for (i = 0; i < value->length; i++, text++) { + *text = Convert_CP437ToUnicode(value->buffer[i]); + } + *text = '\0'; + + GlobalUnlock(hGlobal); + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, hGlobal); + CloseClipboard(); + return; + } +} + +int Window_GetWindowState(void) { + HWND hwnd = Window_Main.Handle.ptr; + DWORD s = GetWindowLong(hwnd, GWL_STYLE); + + if ((s & WS_MINIMIZE)) return WINDOW_STATE_MINIMISED; + if ((s & WS_MAXIMIZE) && (s & WS_POPUP)) return WINDOW_STATE_FULLSCREEN; + return WINDOW_STATE_NORMAL; +} + +static void ToggleFullscreen(HWND hwnd, cc_bool fullscreen, UINT finalShow) { + DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + style |= (fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW); + + suppress_resize = true; + { + ShowWindow(hwnd, SW_RESTORE); /* reset maximised state */ + SetWindowLong(hwnd, GWL_STYLE, style); + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + ShowWindow(hwnd, finalShow); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + Window_ProcessEvents(0.0); + } + suppress_resize = false; + + /* call Resized event only once */ + RefreshWindowDimensions(); + Event_RaiseVoid(&WindowEvents.Resized); +} + +static UINT win_show; +cc_result Window_EnterFullscreen(void) { + HWND hwnd = Window_Main.Handle.ptr; + WINDOWPLACEMENT w = { 0 }; + w.length = sizeof(WINDOWPLACEMENT); + + win_show = w.showCmd; + ToggleFullscreen(hwnd, true, SW_MAXIMIZE); + return 0; +} + +cc_result Window_ExitFullscreen(void) { + HWND hwnd = Window_Main.Handle.ptr; + ToggleFullscreen(hwnd, false, win_show); + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { + HWND hwnd = Window_Main.Handle.ptr; + ShowWindow(hwnd, SW_SHOW); + BringWindowToTop(hwnd); + SetForegroundWindow(hwnd); +} + +void Window_SetSize(int width, int height) { + HWND hwnd = Window_Main.Handle.ptr; + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + RECT rect = { 0, 0, width, height }; + AdjustWindowRectEx(&rect, CC_WIN_STYLE, false, 0); + + SetWindowPos(hwnd, NULL, 0, 0, + Rect_Width(rect), Rect_Height(rect), SWP_NOMOVE); +} + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + +void Window_ProcessEvents(float delta) { + HWND foreground; + HWND hwnd; + MSG msg; + + while (PeekMessageW(&msg, NULL, 0, 0, 1)) { + TranslateMessage(&msg); DispatchMessageW(&msg); + } + + foreground = GetForegroundWindow(); + if (foreground) { + hwnd = Window_Main.Handle.ptr; + Window_Main.Focused = foreground == hwnd; + } +} + +void Gamepads_Init(void) { + +} + +void Gamepads_Process(float delta) { } + +static void Cursor_GetRawPos(int* x, int* y) { + POINT point; + GetCursorPos(&point); + *x = point.x; *y = point.y; +} + +void Cursor_SetPosition(int x, int y) { + SetCursorPos(x + windowX, y + windowY); +} +static void Cursor_DoSetVisible(cc_bool visible) { + int i; + /* ShowCursor actually is a counter (returns > 0 if visible, <= 0 if not) */ + /* Try multiple times in case cursor count was changed by something else */ + /* (there's at least system out there that requires 30 times) */ + if (visible) { + for (i = 0; i < 50 && ShowCursor(true) < 0; i++) { } + } else { + for (i = 0; i < 50 && ShowCursor(false) >= 0; i++) {} + } +} + +static void ShowDialogCore(const char* title, const char* msg) { + HWND hwnd = Window_Main.Handle.ptr; + + int tlen = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); + int mlen = MultiByteToWideChar(CP_UTF8, 0, msg, -1, NULL, 0); + + wchar_t* wtitle = (wchar_t*)malloc(tlen * sizeof(wchar_t)); + wchar_t* wmsg = (wchar_t*)malloc(mlen * sizeof(wchar_t)); + + MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, tlen); + MultiByteToWideChar(CP_UTF8, 0, msg, -1, wmsg, mlen); + + MessageBoxW(hwnd, wmsg, wtitle, 0); + + free(wtitle); + free(wmsg); +} + +static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load, + const char* const* fileExts, const cc_string* defaultName) { + // TODO + return 0; +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + const char* const* fileExts = args->filters; + cc_string filters; char buffer[NATIVE_STR_LEN]; + int i; + + /* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */ + String_InitArray(filters, buffer); + String_Format1(&filters, "%c (", args->description); + for (i = 0; fileExts[i]; i++) + { + if (i) String_Append(&filters, ';'); + String_Format1(&filters, "*%c", fileExts[i]); + } + String_Append(&filters, ')'); + String_Append(&filters, '\0'); + + for (i = 0; fileExts[i]; i++) + { + if (i) String_Append(&filters, ';'); + String_Format1(&filters, "*%c", fileExts[i]); + } + String_Append(&filters, '\0'); + + return OpenSaveFileDialog(&filters, args->Callback, true, fileExts, &String_Empty); +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + const char* const* titles = args->titles; + const char* const* fileExts = args->filters; + cc_string filters; char buffer[NATIVE_STR_LEN]; + int i; + + /* Filter tokens are \0 separated - e.g. "Map (*.cw)\0*.cw\0 */ + String_InitArray(filters, buffer); + for (i = 0; fileExts[i]; i++) + { + String_Format2(&filters, "%c (*%c)", titles[i], fileExts[i]); + String_Append(&filters, '\0'); + String_Format1(&filters, "*%c", fileExts[i]); + String_Append(&filters, '\0'); + } + return OpenSaveFileDialog(&filters, args->Callback, false, fileExts, &args->defaultName); +} + +static HDC draw_DC; +static HBITMAP draw_DIB; + +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + BITMAPINFO hdr = { 0 }; + cc_result res; + + bmp->width = width; + bmp->height = height; + if (!draw_DC) draw_DC = CreateCompatibleDC(win_DC); + + /* sizeof(BITMAPINFO) does not work on Windows 9x */ + hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + hdr.bmiHeader.biWidth = width; + hdr.bmiHeader.biHeight = -height; + hdr.bmiHeader.biBitCount = 32; + hdr.bmiHeader.biPlanes = 1; + + draw_DIB = CreateDIBSection(draw_DC, &hdr, DIB_RGB_COLORS, (void**)&bmp->scan0, NULL, 0); + if (draw_DIB) return; +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + HGDIOBJ oldSrc = SelectObject(draw_DC, draw_DIB); + BitBlt(win_DC, r.x, r.y, r.width, r.height, draw_DC, r.x, r.y, SRCCOPY); + SelectObject(draw_DC, oldSrc); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + if (draw_DIB) DeleteObject(draw_DIB); + draw_DIB = NULL; +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Close(void) { } + + +void Window_EnableRawMouse(void) { + Input.RawMode = true; +} + +void Window_UpdateRawMouse(void) { } + +void Window_DisableRawMouse(void) { + Input.RawMode = false; +} + +#endif From 7c9490116a85bfd4a4a24d84c965a65289d600b1 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 16 Sep 2025 17:14:16 +1000 Subject: [PATCH 099/115] workflow fixes --- .github/actions/upload_build/action.yml | 3 ++- .github/workflows/build_ps1.yml | 2 +- .github/workflows/build_saturn.yml | 7 ++++++- misc/saturn/Makefile | 5 +---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/actions/upload_build/action.yml b/.github/actions/upload_build/action.yml index 84f896586..83e7a2fd0 100644 --- a/.github/actions/upload_build/action.yml +++ b/.github/actions/upload_build/action.yml @@ -16,4 +16,5 @@ runs: - uses: actions/upload-artifact@v4 with: name: ${{ inputs.DEST_NAME }} - path: ${{ inputs.SOURCE_FILE }} \ No newline at end of file + path: ${{ inputs.SOURCE_FILE }} + if-no-files-found: error diff --git a/.github/workflows/build_ps1.yml b/.github/workflows/build_ps1.yml index f96be84bf..09c0714cc 100644 --- a/.github/workflows/build_ps1.yml +++ b/.github/workflows/build_ps1.yml @@ -41,7 +41,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-ps1/ClassiCube-PS1.elf' + SOURCE_FILE: 'build/ps1/ClassiCube-PS1.elf' DEST_NAME: 'ClassiCube-PS1.elf' - uses: ./.github/actions/upload_build diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index 6f6770477..a733d4d96 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -19,6 +19,11 @@ jobs: image: ijacquez/yaul:latest steps: - uses: actions/checkout@v4 + - name: Install prerequisites + run: | + apt-get update + apt-get install -y curl + - name: Compile Saturn build id: compile run: | @@ -34,7 +39,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build-saturn/ClassiCube-saturn.elf' + SOURCE_FILE: 'build/saturn/ClassiCube-saturn.elf' DEST_NAME: 'ClassiCube-saturn.elf' - uses: ./.github/actions/upload_build diff --git a/misc/saturn/Makefile b/misc/saturn/Makefile index 9254d5baf..52ba00908 100644 --- a/misc/saturn/Makefile +++ b/misc/saturn/Makefile @@ -90,10 +90,7 @@ clean: $(BUILD_DIR)/$(TARGET).elf: $(SH_OBJS) $(SH_LD) $(foreach specs,$(SH_SPECS),-specs=$(specs)) $(SH_OBJS) $(SH_LDFLAGS) -o $@ -$(TARGET).elf: $(BUILD_DIR)/$(TARGET).elf - cp $< $@ - -$(BUILD_DIR)/$(TARGET).bin: $(TARGET).elf +$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf $(SH_OBJCOPY) -O binary $< $@ @[ -z "${SILENT}" ] && du -hs $@ | awk '{ print $$1; }' || true From 6af12744ffd324d295958f17b6758e9ab9a34a2a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 16 Sep 2025 17:29:56 +1000 Subject: [PATCH 100/115] Really fix workflows --- .github/workflows/build_3ds.yml | 4 ++-- .github/workflows/build_android.yml | 4 ++-- .github/workflows/build_dreamcast.yml | 4 ++-- .github/workflows/build_freebsd.yml | 4 ++-- .github/workflows/build_haiku.yml | 4 ++-- .github/workflows/build_ios.yml | 4 ++-- .github/workflows/build_linux.yml | 8 ++++---- .github/workflows/build_mac32.yml | 4 ++-- .github/workflows/build_mac64.yml | 4 ++-- .github/workflows/build_macclassic.yml | 4 ++-- .github/workflows/build_msdos.yml | 4 ++-- .github/workflows/build_n64.yml | 4 ++-- .github/workflows/build_nds.yml | 4 ++-- .github/workflows/build_netbsd.yml | 4 ++-- .github/workflows/build_ps1.yml | 4 ++-- .github/workflows/build_ps2.yml | 4 ++-- .github/workflows/build_ps3.yml | 4 ++-- .github/workflows/build_psp.yml | 4 ++-- .github/workflows/build_rpi.yml | 8 ++++---- .github/workflows/build_saturn.yml | 4 ++-- .github/workflows/build_switch.yml | 4 ++-- .github/workflows/build_symbian.yml | 4 ++-- .github/workflows/build_vita.yml | 4 ++-- .github/workflows/build_webclient.yml | 4 ++-- .github/workflows/build_wiigc.yml | 4 ++-- .github/workflows/build_wiiu.yml | 4 ++-- .github/workflows/build_win-arm.yml | 8 ++++---- .github/workflows/build_windows.yml | 8 ++++---- .github/workflows/build_xbox.yml | 4 ++-- .github/workflows/build_xbox360.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 31 files changed, 70 insertions(+), 70 deletions(-) diff --git a/.github/workflows/build_3ds.yml b/.github/workflows/build_3ds.yml index 4bc07d802..b2591c27d 100644 --- a/.github/workflows/build_3ds.yml +++ b/.github/workflows/build_3ds.yml @@ -26,9 +26,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 3DS build' + NOTIFY_MESSAGE: 'Failed to produce 3DS build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml index 1ccca5234..1e5da610b 100644 --- a/.github/workflows/build_android.yml +++ b/.github/workflows/build_android.yml @@ -102,9 +102,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile android build' + NOTIFY_MESSAGE: 'Failed to produce android build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_dreamcast.yml b/.github/workflows/build_dreamcast.yml index 059030acf..8866fd570 100644 --- a/.github/workflows/build_dreamcast.yml +++ b/.github/workflows/build_dreamcast.yml @@ -36,9 +36,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Dreamcast build' + NOTIFY_MESSAGE: 'Failed to produce Dreamcast build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_freebsd.yml b/.github/workflows/build_freebsd.yml index cd5ccaac4..096686248 100644 --- a/.github/workflows/build_freebsd.yml +++ b/.github/workflows/build_freebsd.yml @@ -55,9 +55,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile FreeBSD build(s)' + NOTIFY_MESSAGE: 'Failed to produce FreeBSD build(s)' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_haiku.yml b/.github/workflows/build_haiku.yml index 7d4f05c75..cafb60c59 100644 --- a/.github/workflows/build_haiku.yml +++ b/.github/workflows/build_haiku.yml @@ -30,9 +30,9 @@ jobs: x86_64-unknown-haiku-gcc ${{ env.SRCS }} -o ClassiCube-haiku ${{ env.COMMON_FLAGS }} ${{ env.LIBS }} - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Haiku build' + NOTIFY_MESSAGE: 'Failed to produce Haiku build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ios.yml b/.github/workflows/build_ios.yml index 63514e3f3..141b941da 100644 --- a/.github/workflows/build_ios.yml +++ b/.github/workflows/build_ios.yml @@ -29,9 +29,9 @@ jobs: zip -r cc.ipa Payload - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile iOS build' + NOTIFY_MESSAGE: 'Failed to produce iOS build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 272bea502..387749370 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -53,9 +53,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Linux build' + NOTIFY_MESSAGE: 'Failed to produce 32 bit Linux build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' @@ -118,9 +118,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Linux build' + NOTIFY_MESSAGE: 'Failed to produce 64 bit Linux build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac32.yml b/.github/workflows/build_mac32.yml index 85bf6a32d..d233186c7 100644 --- a/.github/workflows/build_mac32.yml +++ b/.github/workflows/build_mac32.yml @@ -60,9 +60,9 @@ jobs: i386-apple-darwin8-lipo -create -output cc-mac32-universal cc-mac32-gl1 cc-mac32-ppc - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit macOS build' + NOTIFY_MESSAGE: 'Failed to produce 32 bit macOS build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac64.yml b/.github/workflows/build_mac64.yml index 072ae60f1..f308ea1f1 100644 --- a/.github/workflows/build_mac64.yml +++ b/.github/workflows/build_mac64.yml @@ -38,9 +38,9 @@ jobs: # https://wiki.freepascal.org/Code_Signing_for_macOS#Ad_hoc_signing - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit macOS builds' + NOTIFY_MESSAGE: 'Failed to produce 64 bit macOS builds' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_macclassic.yml b/.github/workflows/build_macclassic.yml index ecca53229..59fb5d703 100644 --- a/.github/workflows/build_macclassic.yml +++ b/.github/workflows/build_macclassic.yml @@ -28,9 +28,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Mac Classic build' + NOTIFY_MESSAGE: 'Failed to produce Mac Classic build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_msdos.yml b/.github/workflows/build_msdos.yml index fec5377c6..11eb37749 100644 --- a/.github/workflows/build_msdos.yml +++ b/.github/workflows/build_msdos.yml @@ -31,9 +31,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile MS DOS build' + NOTIFY_MESSAGE: 'Failed to produce MS DOS build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_n64.yml b/.github/workflows/build_n64.yml index 524264208..c155ae6ea 100644 --- a/.github/workflows/build_n64.yml +++ b/.github/workflows/build_n64.yml @@ -38,9 +38,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile N64 build' + NOTIFY_MESSAGE: 'Failed to produce N64 build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_nds.yml b/.github/workflows/build_nds.yml index 526ef7ed8..10e6a0e0f 100644 --- a/.github/workflows/build_nds.yml +++ b/.github/workflows/build_nds.yml @@ -33,9 +33,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile NDS build' + NOTIFY_MESSAGE: 'Failed to produce NDS build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_netbsd.yml b/.github/workflows/build_netbsd.yml index 35e80d5c4..fbc1e74a8 100644 --- a/.github/workflows/build_netbsd.yml +++ b/.github/workflows/build_netbsd.yml @@ -46,9 +46,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile NetBSD build(s)' + NOTIFY_MESSAGE: 'Failed to produce NetBSD build(s)' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps1.yml b/.github/workflows/build_ps1.yml index 09c0714cc..54615fccc 100644 --- a/.github/workflows/build_ps1.yml +++ b/.github/workflows/build_ps1.yml @@ -32,9 +32,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile PS1 build' + NOTIFY_MESSAGE: 'Failed to produce PS1 build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps2.yml b/.github/workflows/build_ps2.yml index 432b0b374..3b8b929bf 100644 --- a/.github/workflows/build_ps2.yml +++ b/.github/workflows/build_ps2.yml @@ -30,9 +30,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile PS2 build' + NOTIFY_MESSAGE: 'Failed to produce PS2 build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps3.yml b/.github/workflows/build_ps3.yml index 69bcba4af..be632a939 100644 --- a/.github/workflows/build_ps3.yml +++ b/.github/workflows/build_ps3.yml @@ -35,9 +35,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile PS3 build' + NOTIFY_MESSAGE: 'Failed to produce PS3 build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_psp.yml b/.github/workflows/build_psp.yml index f87effee4..939131ddc 100644 --- a/.github/workflows/build_psp.yml +++ b/.github/workflows/build_psp.yml @@ -30,9 +30,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile PSP build' + NOTIFY_MESSAGE: 'Failed to produce PSP build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_rpi.yml b/.github/workflows/build_rpi.yml index d1b3ff769..e19fe297c 100644 --- a/.github/workflows/build_rpi.yml +++ b/.github/workflows/build_rpi.yml @@ -44,9 +44,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile RPI 32 bit build' + NOTIFY_MESSAGE: 'Failed to produce RPI 32 bit build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' @@ -96,9 +96,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile RPI 64 bit build' + NOTIFY_MESSAGE: 'Failed to produce RPI 64 bit build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index a733d4d96..f503a52c0 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -30,9 +30,9 @@ jobs: make saturn - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Saturn build' + NOTIFY_MESSAGE: 'Failed to produce Saturn build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_switch.yml b/.github/workflows/build_switch.yml index 73ae6a02b..a3a5c9322 100644 --- a/.github/workflows/build_switch.yml +++ b/.github/workflows/build_switch.yml @@ -26,9 +26,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Switch build' + NOTIFY_MESSAGE: 'Failed to produce Switch build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_symbian.yml b/.github/workflows/build_symbian.yml index 92c41a744..ab83c1c37 100644 --- a/.github/workflows/build_symbian.yml +++ b/.github/workflows/build_symbian.yml @@ -43,9 +43,9 @@ jobs: DEST_NAME: 'ClassiCube-Symbian.sis' - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Symbian build' + NOTIFY_MESSAGE: 'Failed to produce Symbian build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_vita.yml b/.github/workflows/build_vita.yml index e79e5ee52..14b192904 100644 --- a/.github/workflows/build_vita.yml +++ b/.github/workflows/build_vita.yml @@ -26,9 +26,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Vita build' + NOTIFY_MESSAGE: 'Failed to produce Vita build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_webclient.yml b/.github/workflows/build_webclient.yml index 01f2746dd..a80e999e5 100644 --- a/.github/workflows/build_webclient.yml +++ b/.github/workflows/build_webclient.yml @@ -28,9 +28,9 @@ jobs: sed -i 's#eventHandler.useCapture);#{ useCapture: eventHandler.useCapture, passive: false });#g' ClassiCube.js - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Webclient' + NOTIFY_MESSAGE: 'Failed to produce Webclient' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build diff --git a/.github/workflows/build_wiigc.yml b/.github/workflows/build_wiigc.yml index 3d6a6deb5..d161b77c6 100644 --- a/.github/workflows/build_wiigc.yml +++ b/.github/workflows/build_wiigc.yml @@ -34,9 +34,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Wii/Gamecube build' + NOTIFY_MESSAGE: 'Failed to produce Wii/Gamecube build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_wiiu.yml b/.github/workflows/build_wiiu.yml index 9e50194fa..d56842c65 100644 --- a/.github/workflows/build_wiiu.yml +++ b/.github/workflows/build_wiiu.yml @@ -26,9 +26,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile WiiU build' + NOTIFY_MESSAGE: 'Failed to produce WiiU build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_win-arm.yml b/.github/workflows/build_win-arm.yml index df06567fa..67aaf75d6 100644 --- a/.github/workflows/build_win-arm.yml +++ b/.github/workflows/build_win-arm.yml @@ -37,9 +37,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Windows build' + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -72,9 +72,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Windows build' + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index aeb5f0719..f84df3112 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -49,9 +49,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 32 bit Windows build' + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' @@ -119,9 +119,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile 64 bit Windows build' + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox.yml b/.github/workflows/build_xbox.yml index 523ab31e0..67f341011 100644 --- a/.github/workflows/build_xbox.yml +++ b/.github/workflows/build_xbox.yml @@ -31,9 +31,9 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Xbox build' + NOTIFY_MESSAGE: 'Failed to produce Xbox build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox360.yml b/.github/workflows/build_xbox360.yml index e562895d6..6d6a573bf 100644 --- a/.github/workflows/build_xbox360.yml +++ b/.github/workflows/build_xbox360.yml @@ -33,9 +33,9 @@ jobs: make xbox360 - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: - NOTIFY_MESSAGE: 'Failed to compile Xbox 360 build' + NOTIFY_MESSAGE: 'Failed to produce Xbox 360 build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4aa09d71..63f43a4a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,7 +116,7 @@ jobs: - uses: ./.github/actions/notify_failure - if: ${{ always() && steps.compile.outcome == 'failure' }} + if: failure() with: NOTIFY_MESSAGE: 'Failed to produce release' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' @@ -218,4 +218,4 @@ jobs: if: ${{ always() && steps.compile.outcome == 'success' }} with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' - WORKFLOW_NAME: 'release' \ No newline at end of file + WORKFLOW_NAME: 'release' From 375ba9058961129344a8b0048772e63f2dca614f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 16 Sep 2025 17:44:15 +1000 Subject: [PATCH 101/115] Really really fix workflows --- .github/workflows/build_3ds.yml | 14 ++++++------- .github/workflows/build_android.yml | 14 ++++++------- .github/workflows/build_dreamcast.yml | 14 ++++++------- .github/workflows/build_freebsd.yml | 14 ++++++------- .github/workflows/build_haiku.yml | 13 ++++++------ .github/workflows/build_ios.yml | 13 ++++++------ .github/workflows/build_linux.yml | 28 +++++++++++++------------- .github/workflows/build_mac32.yml | 13 ++++++------ .github/workflows/build_mac64.yml | 13 ++++++------ .github/workflows/build_macclassic.yml | 14 ++++++------- .github/workflows/build_msdos.yml | 14 ++++++------- .github/workflows/build_n64.yml | 14 ++++++------- .github/workflows/build_nds.yml | 14 ++++++------- .github/workflows/build_netbsd.yml | 14 ++++++------- .github/workflows/build_ps1.yml | 14 ++++++------- .github/workflows/build_ps2.yml | 14 ++++++------- .github/workflows/build_ps3.yml | 14 ++++++------- .github/workflows/build_psp.yml | 14 ++++++------- .github/workflows/build_rpi.yml | 28 +++++++++++++------------- .github/workflows/build_saturn.yml | 15 +++++++------- .github/workflows/build_switch.yml | 14 ++++++------- .github/workflows/build_symbian.yml | 13 ++++++------ .github/workflows/build_vita.yml | 14 ++++++------- .github/workflows/build_webclient.yml | 13 ++++++------ .github/workflows/build_wiigc.yml | 14 ++++++------- .github/workflows/build_wiiu.yml | 14 ++++++------- .github/workflows/build_win-arm.yml | 24 ++++++++++++++-------- .github/workflows/build_windows.yml | 28 +++++++++++++------------- .github/workflows/build_xbox.yml | 14 ++++++------- .github/workflows/build_xbox360.yml | 13 ++++++------ .github/workflows/release.yml | 15 +++++++------- 31 files changed, 249 insertions(+), 232 deletions(-) diff --git a/.github/workflows/build_3ds.yml b/.github/workflows/build_3ds.yml index b2591c27d..7b2ff2d8a 100644 --- a/.github/workflows/build_3ds.yml +++ b/.github/workflows/build_3ds.yml @@ -24,13 +24,6 @@ jobs: run: | make 3ds - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 3DS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -56,3 +49,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: '3ds' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 3DS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml index 1e5da610b..87f63fcf3 100644 --- a/.github/workflows/build_android.yml +++ b/.github/workflows/build_android.yml @@ -99,13 +99,6 @@ jobs: # jarsigner -verbose # create aligned .apk file #$TOOLS_ROOT/zipalign -f 4 cc-signed.apk $ROOT_DIR/src/cc.apk - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce android build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -120,3 +113,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'android' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce android build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_dreamcast.yml b/.github/workflows/build_dreamcast.yml index 8866fd570..39a2439e1 100644 --- a/.github/workflows/build_dreamcast.yml +++ b/.github/workflows/build_dreamcast.yml @@ -34,13 +34,6 @@ jobs: export PATH=/opt/toolchains/dc/kos/utils/:$PATH make dreamcast - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Dreamcast build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -66,3 +59,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'dreamcast' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Dreamcast build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_freebsd.yml b/.github/workflows/build_freebsd.yml index 096686248..a34f44c39 100644 --- a/.github/workflows/build_freebsd.yml +++ b/.github/workflows/build_freebsd.yml @@ -52,13 +52,6 @@ jobs: i386-freebsd11-clang ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT32_FLAGS }} $LATEST_FLAG -o cc-fbsd32-gl1 ${{ env.LIBS }} x86_64-freebsd11-clang ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT64_FLAGS }} $LATEST_FLAG -o cc-fbsd64-gl1 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce FreeBSD build(s)' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -79,3 +72,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'freebsd' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce FreeBSD build(s)' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_haiku.yml b/.github/workflows/build_haiku.yml index cafb60c59..950c879ca 100644 --- a/.github/workflows/build_haiku.yml +++ b/.github/workflows/build_haiku.yml @@ -28,12 +28,6 @@ jobs: COMMON_FLAGS: "-O1 -s -fno-stack-protector -fno-math-errno -Qn -Werror" run: | x86_64-unknown-haiku-gcc ${{ env.SRCS }} -o ClassiCube-haiku ${{ env.COMMON_FLAGS }} ${{ env.LIBS }} - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Haiku build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -48,3 +42,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'haiku' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Haiku build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ios.yml b/.github/workflows/build_ios.yml index 141b941da..b88d2ce13 100644 --- a/.github/workflows/build_ios.yml +++ b/.github/workflows/build_ios.yml @@ -27,12 +27,6 @@ jobs: mkdir Payload mv ClassiCube.app Payload/ClassiCube.app zip -r cc.ipa Payload - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce iOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -46,3 +40,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ios' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce iOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 387749370..e053d556f 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -50,13 +50,6 @@ jobs: gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX32_FLAGS }} $LATEST_FLAG -o cc-nix32-gl1 ${{ env.LIBS }} gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX32_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -o cc-nix32-gl2 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 32 bit Linux build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -78,6 +71,13 @@ jobs: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'linux32' + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Linux build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + #============================================ # =============== 64 BIT LINUX ============== # =========================================== @@ -115,13 +115,6 @@ jobs: gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -o cc-nix64-gl1 ${{ env.LIBS }} gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -o cc-nix64-gl2 ${{ env.LIBS }} #gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.NIX64_FLAGS }} $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL2 -DCC_WIN_BACKEND=CC_WIN_BACKEND_SDL2 -o cc-sdl64-gl2 -lSDL2 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 64 bit Linux build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -148,3 +141,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'linux64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Linux build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac32.yml b/.github/workflows/build_mac32.yml index d233186c7..0d769852a 100644 --- a/.github/workflows/build_mac32.yml +++ b/.github/workflows/build_mac32.yml @@ -58,12 +58,6 @@ jobs: run: | PATH=$PATH:/usr/local/compiler/target/bin i386-apple-darwin8-lipo -create -output cc-mac32-universal cc-mac32-gl1 cc-mac32-ppc - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 32 bit macOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -96,3 +90,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'mac32' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit macOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_mac64.yml b/.github/workflows/build_mac64.yml index f308ea1f1..91bb8954e 100644 --- a/.github/workflows/build_mac64.yml +++ b/.github/workflows/build_mac64.yml @@ -36,12 +36,6 @@ jobs: clang ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.ARM64_FLAGS }} $LATEST_FLAG -o cc-mac-arm64 ${{ env.LIBS }} # https://wiki.freepascal.org/Code_Signing_for_macOS#Ad_hoc_signing - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 64 bit macOS builds' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -68,3 +62,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'mac64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit macOS builds' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_macclassic.yml b/.github/workflows/build_macclassic.yml index 59fb5d703..6b8656efc 100644 --- a/.github/workflows/build_macclassic.yml +++ b/.github/workflows/build_macclassic.yml @@ -27,13 +27,6 @@ jobs: make macclassic_68k RETRO68=/Retro68-build/toolchain ARCH_68040=1 - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Mac Classic build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -58,3 +51,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'macclassic' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Mac Classic build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_msdos.yml b/.github/workflows/build_msdos.yml index 11eb37749..55c72b565 100644 --- a/.github/workflows/build_msdos.yml +++ b/.github/workflows/build_msdos.yml @@ -30,13 +30,6 @@ jobs: make CC=gcc dos - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce MS DOS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -49,3 +42,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'msdos' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce MS DOS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_n64.yml b/.github/workflows/build_n64.yml index c155ae6ea..e13f8b794 100644 --- a/.github/workflows/build_n64.yml +++ b/.github/workflows/build_n64.yml @@ -35,13 +35,6 @@ jobs: make tools-install cd $REAL_DIR make n64 - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce N64 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -62,3 +55,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'n64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce N64 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_nds.yml b/.github/workflows/build_nds.yml index 10e6a0e0f..00830a6e1 100644 --- a/.github/workflows/build_nds.yml +++ b/.github/workflows/build_nds.yml @@ -30,13 +30,6 @@ jobs: make ds export BUILD_DSI=1 make ds - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce NDS build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -69,3 +62,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'nds' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce NDS build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_netbsd.yml b/.github/workflows/build_netbsd.yml index fbc1e74a8..786301cc4 100644 --- a/.github/workflows/build_netbsd.yml +++ b/.github/workflows/build_netbsd.yml @@ -43,13 +43,6 @@ jobs: LATEST_FLAG=-DCC_COMMIT_SHA=\"${GITHUB_SHA::9}\" x86_64-unknown-netbsd-gcc ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.PLAT64_FLAGS }} $LATEST_FLAG -o cc-netbsd64-gl1 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce NetBSD build(s)' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -64,3 +57,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'netbsd' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce NetBSD build(s)' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps1.yml b/.github/workflows/build_ps1.yml index 54615fccc..ae2306c96 100644 --- a/.github/workflows/build_ps1.yml +++ b/.github/workflows/build_ps1.yml @@ -31,13 +31,6 @@ jobs: make ps1 - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce PS1 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -68,3 +61,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps1' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS1 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps2.yml b/.github/workflows/build_ps2.yml index 3b8b929bf..d2d1c670d 100644 --- a/.github/workflows/build_ps2.yml +++ b/.github/workflows/build_ps2.yml @@ -28,13 +28,6 @@ jobs: run: | make ps2 - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce PS2 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -54,3 +47,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps2' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS2 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_ps3.yml b/.github/workflows/build_ps3.yml index be632a939..84f8adfd7 100644 --- a/.github/workflows/build_ps3.yml +++ b/.github/workflows/build_ps3.yml @@ -34,13 +34,6 @@ jobs: make ps3 - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce PS3 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -65,3 +58,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'ps3' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PS3 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_psp.yml b/.github/workflows/build_psp.yml index 939131ddc..2488824f1 100644 --- a/.github/workflows/build_psp.yml +++ b/.github/workflows/build_psp.yml @@ -28,13 +28,6 @@ jobs: run: | make psp - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce PSP build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -54,3 +47,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'psp' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce PSP build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_rpi.yml b/.github/workflows/build_rpi.yml index e19fe297c..2bfcd84f8 100644 --- a/.github/workflows/build_rpi.yml +++ b/.github/workflows/build_rpi.yml @@ -41,13 +41,6 @@ jobs: LATEST_FLAG=-DCC_COMMIT_SHA=\"$GITHUB_SHA\" $CC ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.RPI32_FLAGS }} $LATEST_FLAG -o cc-rpi32 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce RPI 32 bit build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -64,6 +57,13 @@ jobs: WORKFLOW_NAME: 'rpi32' + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce RPI 32 bit build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + + #============================================ # ================ 64 BIT RPI =============== # =========================================== @@ -93,13 +93,6 @@ jobs: LATEST_FLAG=-DCC_COMMIT_SHA=\"$GITHUB_SHA\" $CC ${{ env.SRCS }} ${{ env.FLAGS }} ${{ env.RPI64_FLAGS }} $LATEST_FLAG -o cc-rpi64 ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce RPI 64 bit build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -114,3 +107,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'rpi64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce RPI 64 bit build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index f503a52c0..7ea0af117 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -21,19 +21,13 @@ jobs: - uses: actions/checkout@v4 - name: Install prerequisites run: | - apt-get update + apt-get --allow-releaseinfo-change update apt-get install -y curl - name: Compile Saturn build id: compile run: | make saturn - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Saturn build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -60,3 +54,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'saturn' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Saturn build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_switch.yml b/.github/workflows/build_switch.yml index a3a5c9322..510c45f51 100644 --- a/.github/workflows/build_switch.yml +++ b/.github/workflows/build_switch.yml @@ -24,13 +24,6 @@ jobs: run: | make switch - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Switch build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -50,3 +43,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'switch' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Switch build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_symbian.yml b/.github/workflows/build_symbian.yml index ab83c1c37..b9eacf77a 100644 --- a/.github/workflows/build_symbian.yml +++ b/.github/workflows/build_symbian.yml @@ -42,15 +42,16 @@ jobs: SOURCE_FILE: 'misc/symbian/ClassiCube.sis' DEST_NAME: 'ClassiCube-Symbian.sis' - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Symbian build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/notify_success if: ${{ always() && steps.compile.outcome == 'success' }} with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'symbian' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Symbian build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_vita.yml b/.github/workflows/build_vita.yml index 14b192904..6c9ccc6b4 100644 --- a/.github/workflows/build_vita.yml +++ b/.github/workflows/build_vita.yml @@ -24,13 +24,6 @@ jobs: run: | make vita - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Vita build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -50,3 +43,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'vita' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Vita build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_webclient.yml b/.github/workflows/build_webclient.yml index a80e999e5..60ea87dc5 100644 --- a/.github/workflows/build_webclient.yml +++ b/.github/workflows/build_webclient.yml @@ -26,12 +26,6 @@ jobs: run: | emcc ${{ env.SRCS }} -o ClassiCube.js -s WASM=0 -s NO_EXIT_RUNTIME=1 -s LEGACY_VM_SUPPORT=1 -s ALLOW_MEMORY_GROWTH=1 -s ABORTING_MALLOC=0 -s ENVIRONMENT=web -s TOTAL_STACK=256Kb --js-library src/webclient/interop_web.js -Os -g2 -s SINGLE_FILE sed -i 's#eventHandler.useCapture);#{ useCapture: eventHandler.useCapture, passive: false });#g' ClassiCube.js - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Webclient' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -45,3 +39,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'webclient' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Webclient' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_wiigc.yml b/.github/workflows/build_wiigc.yml index d161b77c6..e65ff0d05 100644 --- a/.github/workflows/build_wiigc.yml +++ b/.github/workflows/build_wiigc.yml @@ -31,13 +31,6 @@ jobs: cp ClassiCube-wii.dol wiitest/apps/ClassiCube/boot.dol cp misc/wii/icon.png wiitest/apps/ClassiCube/icon.png cp misc/wii/meta.xml wiitest/apps/ClassiCube/meta.xml - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Wii/Gamecube build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -76,3 +69,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'wiigc' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Wii/Gamecube build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_wiiu.yml b/.github/workflows/build_wiiu.yml index d56842c65..5b219a359 100644 --- a/.github/workflows/build_wiiu.yml +++ b/.github/workflows/build_wiiu.yml @@ -23,13 +23,6 @@ jobs: id: compile run: | make wiiu - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce WiiU build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -56,3 +49,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'wiiu' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce WiiU build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_win-arm.yml b/.github/workflows/build_win-arm.yml index 67aaf75d6..648c3ff08 100644 --- a/.github/workflows/build_win-arm.yml +++ b/.github/workflows/build_win-arm.yml @@ -35,18 +35,18 @@ jobs: armv7-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -o cc-arm32-d3d11.exe $LATEST_FLAG ${{ env.LIBS }} - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'cc-arm32-d3d11.exe' DEST_NAME: 'ClassiCube-arm32-Direct3D11.exe' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows-ARM build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' #============================================ # ============== ARM64 WINDOWS ============== # =========================================== @@ -77,8 +77,16 @@ jobs: NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' + - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: SOURCE_FILE: 'cc-arm64-d3d11.exe' - DEST_NAME: 'ClassiCube-arm64-Direct3D11.exe' + DEST_NAME: 'ClassiCube-arm64-Direct3D11.exe' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows-ARM build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index f84df3112..6b7d23825 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -46,13 +46,6 @@ jobs: # mingw defaults to i686, but some really old CPUs only support i586 i686-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN32_FLAGS }} -march=i586 -o cc-w9x-ogl.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_GL1 -DCC_BUILD_NOSTDLIB ${{ env.LIBS }} - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -85,6 +78,13 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'win32' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 32 bit Windows build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' #============================================ @@ -118,13 +118,6 @@ jobs: x86_64-w64-mingw32-gcc ${{ env.SRCS }} ${{ env.COMMON_FLAGS }} ${{ env.WIN64_FLAGS }} -o cc-w64-d3d11.exe $LATEST_FLAG -DCC_GFX_BACKEND=CC_GFX_BACKEND_D3D11 ${{ env.LIBS }} - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: @@ -149,3 +142,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'win64' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce 64 bit Windows build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox.yml b/.github/workflows/build_xbox.yml index 67f341011..4bec2f29f 100644 --- a/.github/workflows/build_xbox.yml +++ b/.github/workflows/build_xbox.yml @@ -29,13 +29,6 @@ jobs: eval $(/usr/src/nxdk/bin/activate -s) make xbox - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Xbox build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} @@ -55,3 +48,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'xbox' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Xbox build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/build_xbox360.yml b/.github/workflows/build_xbox360.yml index 6d6a573bf..8bae230c4 100644 --- a/.github/workflows/build_xbox360.yml +++ b/.github/workflows/build_xbox360.yml @@ -31,12 +31,6 @@ jobs: export DEVKITXENON=/usr/local/xenon export PATH=$PATH:$DEVKITXENON/bin:$DEVKITXENON/usr/bin make xbox360 - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce Xbox 360 build' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' - uses: ./.github/actions/upload_build @@ -57,3 +51,10 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'xbox360' + + + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce Xbox 360 build' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 63f43a4a6..121f0855b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -113,13 +113,6 @@ jobs: make_unix_tar cc-linux32.tar.gz cc-linux-32 make_unix_tar cc-linux64.tar.gz cc-linux-64 - - - - uses: ./.github/actions/notify_failure - if: failure() - with: - NOTIFY_MESSAGE: 'Failed to produce release' - WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' # Generate Linux release files @@ -219,3 +212,11 @@ jobs: with: DESTINATION_URL: '${{ secrets.NOTIFY_URL }}' WORKFLOW_NAME: 'release' + + + # Log any failure + - uses: ./.github/actions/notify_failure + if: failure() + with: + NOTIFY_MESSAGE: 'Failed to produce release' + WEBHOOK_URL: '${{ secrets.WEBHOOK_URL }}' From 5cd53f201750c48e8e13e8ba2280d38edb2e6e89 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 17 Sep 2025 06:46:33 +1000 Subject: [PATCH 102/115] OpenGL: Simplify RGBA texture conversion --- .github/workflows/build_linux.yml | 10 +++++----- .github/workflows/build_ps1.yml | 2 +- src/_GLShared.h | 30 ++++++++++-------------------- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index e053d556f..e06137f79 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -129,11 +129,11 @@ jobs: SOURCE_FILE: 'cc-nix64-gl2' DEST_NAME: 'ClassiCube-Linux64-ModernGL' - - uses: ./.github/actions/upload_build - if: ${{ always() && steps.compile.outcome == 'success' }} - with: - SOURCE_FILE: 'cc-sdl64-gl2' - DEST_NAME: 'ClassiCube-Linux64-SDL2' +# - uses: ./.github/actions/upload_build +# if: ${{ always() && steps.compile.outcome == 'success' }} +# with: +# SOURCE_FILE: 'cc-sdl64-gl2' +# DEST_NAME: 'ClassiCube-Linux64-SDL2' - uses: ./.github/actions/notify_success diff --git a/.github/workflows/build_ps1.yml b/.github/workflows/build_ps1.yml index ae2306c96..9ab7c8e48 100644 --- a/.github/workflows/build_ps1.yml +++ b/.github/workflows/build_ps1.yml @@ -34,7 +34,7 @@ jobs: - uses: ./.github/actions/upload_build if: ${{ always() && steps.compile.outcome == 'success' }} with: - SOURCE_FILE: 'build/ps1/ClassiCube-PS1.elf' + SOURCE_FILE: 'build/ps1/ClassiCube-ps1.elf' DEST_NAME: 'ClassiCube-PS1.elf' - uses: ./.github/actions/upload_build diff --git a/src/_GLShared.h b/src/_GLShared.h index 8eec7ec8d..dd497511d 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -70,28 +70,18 @@ static void* FastAllocTempMem(int size) { static cc_bool convert_rgba; static void ConvertRGBA(void* dst, const void* src, int numPixels) { - cc_uint8* d = (cc_uint8*)dst; - cc_uint8* s = (cc_uint8*)src; + cc_uint8* d = (cc_uint8*)dst; + BitmapCol* s = (BitmapCol*)src; int i; - for (i = 0; i < numPixels; i++, d += 4, s += 4) { -#ifdef CC_BUILD_IRIX - d[0] = s[1]; - d[1] = s[2]; - d[2] = s[3]; - d[3] = s[0]; -#elif defined CC_BUILD_HPUX - /* HP-UX specific color channel mapping - try IRIX style G,B,A,R */ - d[0] = s[1]; /* R = G */ - d[1] = s[2]; /* G = B */ - d[2] = s[3]; /* B = A */ - d[3] = s[0]; /* A = R */ -#else - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = s[3]; -#endif + /* R,G,B,A byte order regardless of system endian */ + for (i = 0; i < numPixels; i++, d += 4, s++) + { + BitmapCol col = *s; + d[0] = BitmapCol_R(col); + d[1] = BitmapCol_G(col); + d[2] = BitmapCol_B(col); + d[3] = BitmapCol_A(col); } } From 4712bf590944482b985313fd6c8c620a9ebedeca Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 17 Sep 2025 20:04:57 +1000 Subject: [PATCH 103/115] Simplify pre processing of vertices --- src/Game.c | 8 +- src/Graphics_SoftFP.c | 284 ++++++++++++++++++------------------------ src/Window_WinCE.c | 135 ++++++++++---------- 3 files changed, 191 insertions(+), 236 deletions(-) diff --git a/src/Game.c b/src/Game.c index 7fb359889..b51f4b613 100644 --- a/src/Game.c +++ b/src/Game.c @@ -885,13 +885,9 @@ void Game_Setup(void) { int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 0); /* No custom resolution has been set */ - if (width == 0 || height == 0) { -#ifndef CC_BUILD_WINCE + if (width == 0 || height == 0) { width = 854; height = 480; - if (DisplayInfo.Width < 854) width = 640; -#else - width = 240; height = 160; -#endif + if (DisplayInfo.Width < 854) width = 640; } String_InitArray(title, titleBuffer); diff --git a/src/Graphics_SoftFP.c b/src/Graphics_SoftFP.c index 910a62478..0ba5e8f74 100644 --- a/src/Graphics_SoftFP.c +++ b/src/Graphics_SoftFP.c @@ -61,29 +61,10 @@ typedef struct VertexFixed { PackedCol c; } VertexFixed; +static int tex_offseting; static int texOffsetX_fp, texOffsetY_fp; // Fixed point texture offsets static FixedMatrix _view_fp, _proj_fp, _mvp_fp; -#define MAX_PRECONV_VBS 64 - -typedef struct { - void* vb; - VertexFixed* verts; - int count; - int stride; - VertexFormat fmt; -} PreconvEntry; - -static PreconvEntry preconvEntries[MAX_PRECONV_VBS]; -static int preconvEntryCount = 0; - - -static void* last_locked_vb = NULL; -static int last_locked_count = 0; -static VertexFormat last_locked_fmt = 0; -static int last_locked_stride = 0; - - static void Gfx_RestoreState(void) { InitDefaultResources(); @@ -260,128 +241,76 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } /*########################################################################################################################* *-------------------------------------------------------Vertex buffers----------------------------------------------------* *#########################################################################################################################*/ +// Preprocess vertex buffers into fixed point values +struct FPVertexColoured { + int x, y, z; + BitmapCol c; +}; + +struct FPVertexTextured { + int x, y, z; + BitmapCol c; + int u, v; +}; + +static VertexFormat buf_fmt; +static int buf_count; + +static void PreprocessTexturedVertices(void) { + struct FPVertexTextured* dst = gfx_vertices; + struct VertexTextured* src = gfx_vertices; + + for (int i = 0; i < buf_count; i++, src++, dst++) + { + dst->x = FloatToFixed(src->x); + dst->y = FloatToFixed(src->y); + dst->z = FloatToFixed(src->z); + dst->u = FloatToFixed(src->U); + dst->v = FloatToFixed(src->V); + dst->c = src->Col; + } +} + +static void PreprocessColouredVertices(void) { + struct FPVertexColoured* dst = gfx_vertices; + struct VertexColoured* src = gfx_vertices; + + for (int i = 0; i < buf_count; i++, src++, dst++) + { + dst->x = FloatToFixed(src->x); + dst->y = FloatToFixed(src->y); + dst->z = FloatToFixed(src->z); + dst->c = src->Col; + } +} + static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return Mem_TryAlloc(count, strideSizes[fmt]); } void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } - - -static PreconvEntry* FindPreconvEntry(void* vb) { - for (int i = 0; i < preconvEntryCount; i++) { - if (preconvEntries[i].vb == vb) return &preconvEntries[i]; - } - return NULL; -} - -static void FreePreconvEntryAt(int idx) { - if (preconvEntries[idx].verts) Mem_Free(preconvEntries[idx].verts); - if (idx != preconvEntryCount - 1) { - preconvEntries[idx] = preconvEntries[preconvEntryCount - 1]; - } - preconvEntryCount--; -} - -static void FreePreconvForVB(void* vb) { - PreconvEntry* e = FindPreconvEntry(vb); - if (!e) return; - int idx = (int)(e - preconvEntries); - FreePreconvEntryAt(idx); -} - -static int Preconv_Set(void* vb, int count, int stride, VertexFormat fmt) { - FreePreconvForVB(vb); - - if (count <= 0) return 0; - if (preconvEntryCount >= MAX_PRECONV_VBS) { - return 0; - } - - VertexFixed* arr = (VertexFixed*)Mem_Alloc(count, sizeof(VertexFixed), "vb-preconv"); - if (!arr) return 0; - - char* base = (char*)vb; - for (int i = 0; i < count; i++) { - char* ptr = base + i * stride; - if (fmt != VERTEX_FORMAT_TEXTURED) { - struct VertexColoured* v = (struct VertexColoured*)ptr; - arr[i].x = FloatToFixed(v->x); - arr[i].y = FloatToFixed(v->y); - arr[i].z = 0; - arr[i].w = IntToFixed(1); - arr[i].u = 0; - arr[i].v = 0; - arr[i].c = v->Col; - } else { - struct VertexTextured* v = (struct VertexTextured*)ptr; - arr[i].x = FloatToFixed(v->x); - arr[i].y = FloatToFixed(v->y); - arr[i].z = FloatToFixed(v->z); - arr[i].w = IntToFixed(1); - arr[i].u = FloatToFixed(v->U) + texOffsetX_fp; - arr[i].v = FloatToFixed(v->V) + texOffsetY_fp; - arr[i].c = v->Col; - } - } - - preconvEntries[preconvEntryCount].vb = vb; - preconvEntries[preconvEntryCount].verts = arr; - preconvEntries[preconvEntryCount].count = count; - preconvEntries[preconvEntryCount].stride = stride; - preconvEntries[preconvEntryCount].fmt = fmt; - preconvEntryCount++; - return 1; -} - -static cc_bool Preconv_GetVertex(void* vb, int index, VertexFixed* out) { - PreconvEntry* e = FindPreconvEntry(vb); - if (!e) return false; - if (index < 0 || index >= e->count) return false; - *out = e->verts[index]; - return true; -} void Gfx_DeleteVb(GfxResourceID* vb) { GfxResourceID data = *vb; - if (data) { - FreePreconvForVB(data); - Mem_Free(data); - } + if (data) Mem_Free(data); + *vb = 0; } + void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - last_locked_vb = vb; - last_locked_count = count; - last_locked_fmt = fmt; - last_locked_stride = strideSizes[fmt]; - return vb; + buf_fmt = fmt; + buf_count = count; + return vb; } -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - last_locked_vb = vb; - last_locked_count = count; - last_locked_fmt = fmt; - last_locked_stride = strideSizes[fmt]; - return vb; -} - - -void Gfx_UnlockVb(GfxResourceID vb) { +void Gfx_UnlockVb(GfxResourceID vb) { gfx_vertices = vb; - if (last_locked_vb == vb && last_locked_count > 0) { - Preconv_Set(vb, last_locked_count, last_locked_stride, last_locked_fmt); + + if (buf_fmt == VERTEX_FORMAT_TEXTURED) { + PreprocessTexturedVertices(); } else { - // count is unknown + PreprocessColouredVertices(); } - last_locked_vb = NULL; last_locked_count = 0; -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; - if (last_locked_vb == vb && last_locked_count > 0) { - Preconv_Set(vb, last_locked_count, last_locked_stride, last_locked_fmt); - } - last_locked_vb = NULL; last_locked_count = 0; } static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { @@ -392,6 +321,13 @@ void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return Gfx_LockVb(vb, fmt, count); +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { Gfx_UnlockVb(vb); } + + /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ @@ -444,13 +380,31 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma } void Gfx_EnableTextureOffset(float x, float y) { + tex_offseting = true; texOffsetX_fp = FloatToFixed(x); texOffsetY_fp = FloatToFixed(y); } void Gfx_DisableTextureOffset(void) { - texOffsetX_fp = 0; - texOffsetY_fp = 0; + tex_offseting = false; +} + +static CC_NOINLINE void ShiftTextureCoords(int count) { + for (int i = 0; i < count; i++) + { + struct FPVertexTextured* v = (struct FPVertexTextured*)gfx_vertices + i; + v->u += texOffsetX_fp; // TODO avoid overflow + v->v += texOffsetY_fp; + } +} + +static CC_NOINLINE void UnshiftTextureCoords(int count) { + for (int i = 0; i < count; i++) + { + struct FPVertexTextured* v = (struct FPVertexTextured*)gfx_vertices + i; + v->u -= texOffsetX_fp; // TODO avoid overflow + v->v -= texOffsetY_fp; + } } void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { @@ -639,55 +593,53 @@ static int ClipTriangleToFrustumFixed(const VertexFixed tri[3], VertexFixed* out } static void TransformVertex2D(int index, VertexFixed* vertex) { - if (Preconv_GetVertex(gfx_vertices, index, vertex)) return; - - char* ptr = (char*)gfx_vertices + index * gfx_stride; - - struct VertexColoured* v_col; - struct VertexTextured* v_tex; + struct FPVertexColoured* v_col; + struct FPVertexTextured* v_tex; if (gfx_format != VERTEX_FORMAT_TEXTURED) { - v_col = (struct VertexColoured*)ptr; - vertex->x = FloatToFixed(v_col->x); - vertex->y = FloatToFixed(v_col->y); + v_col = (struct FPVertexColoured*)gfx_vertices + index; + vertex->x = v_col->x; + vertex->y = v_col->y; vertex->u = 0; vertex->v = 0; - vertex->c = v_col->Col; + vertex->c = v_col->c; } else { - v_tex = (struct VertexTextured*)ptr; - vertex->x = FloatToFixed(v_tex->x); - vertex->y = FloatToFixed(v_tex->y); - vertex->u = FloatToFixed(v_tex->U); - vertex->v = FloatToFixed(v_tex->V); - vertex->c = v_tex->Col; + v_tex = (struct FPVertexTextured*)gfx_vertices + index; + vertex->x = v_tex->x; + vertex->y = v_tex->y; + vertex->u = v_tex->u; + vertex->v = v_tex->v; + vertex->c = v_tex->c; } } static int TransformVertex3D(int index, VertexFixed* vertex) { int pos_x, pos_y, pos_z; - - if (Preconv_GetVertex(gfx_vertices, index, vertex)) { - pos_x = vertex->x; pos_y = vertex->y; pos_z = vertex->z; + struct FPVertexColoured* v_col; + struct FPVertexTextured* v_tex; + + if (gfx_format != VERTEX_FORMAT_TEXTURED) { + v_col = (struct FPVertexColoured*)gfx_vertices + index; + vertex->x = v_col->x; + vertex->y = v_col->y; + vertex->z = v_col->z; + vertex->u = 0; + vertex->v = 0; + vertex->c = v_col->c; } else { - // fallback - char* ptr = (char*)gfx_vertices + index * gfx_stride; - if (gfx_format != VERTEX_FORMAT_TEXTURED) { - struct VertexColoured* v_col = (struct VertexColoured*)ptr; - pos_x = FloatToFixed(v_col->x); - pos_y = FloatToFixed(v_col->y); - pos_z = 0; - vertex->u = 0; vertex->v = 0; vertex->c = v_col->Col; - } else { - struct VertexTextured* v_tex = (struct VertexTextured*)ptr; - pos_x = FloatToFixed(v_tex->x); - pos_y = FloatToFixed(v_tex->y); - pos_z = FloatToFixed(v_tex->z); - vertex->u = FloatToFixed(v_tex->U) + texOffsetX_fp; - vertex->v = FloatToFixed(v_tex->V) + texOffsetY_fp; - vertex->c = v_tex->Col; - } + v_tex = (struct FPVertexTextured*)gfx_vertices + index; + vertex->x = v_tex->x; + vertex->y = v_tex->y; + vertex->z = v_tex->z; + vertex->u = v_tex->u; + vertex->v = v_tex->v; + vertex->c = v_tex->c; } + pos_x = vertex->x; + pos_y = vertex->y; + pos_z = vertex->z; + if (ABS(pos_x) > (1 << 28) || ABS(pos_y) > (1 << 28) || ABS(pos_z) > (1 << 28)) { return 0; } @@ -1425,6 +1377,8 @@ void DrawQuadsFixed(int startVertex, int verticesCount, DrawHints hints) { DrawTriangle2D(&vertices[2], &vertices[0], &vertices[3]); } } else { + if (tex_offseting) ShiftTextureCoords(verticesCount); + for (i = 0; i < verticesCount / 4; i++, j += 4) { TransformVertex3D(j + 0, &vertices[0]); TransformVertex3D(j + 1, &vertices[1]); @@ -1433,6 +1387,8 @@ void DrawQuadsFixed(int startVertex, int verticesCount, DrawHints hints) { DrawClippedFixed(0x0F, &vertices[0], &vertices[1], &vertices[2], &vertices[3]); } + + if (tex_offseting) UnshiftTextureCoords(verticesCount); } } void Gfx_SetVertexFormat(VertexFormat fmt) { diff --git a/src/Window_WinCE.c b/src/Window_WinCE.c index 04f7c9ede..f853744a2 100644 --- a/src/Window_WinCE.c +++ b/src/Window_WinCE.c @@ -30,7 +30,7 @@ #include "Funcs.h" #include "Bitmap.h" #include "Options.h" -#include "Errors.h" +#include "Errors.h" #include "Gui.h" #define WIN32_LEAN_AND_MEAN @@ -43,7 +43,7 @@ #endif #include -#include +#include /* https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelformat */ #define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN @@ -129,14 +129,14 @@ static void RefreshWindowPosition(void) { windowX = topLeft.x; windowY = topLeft.y; } -static void GrabCursor(void) { +static void GrabCursor(void) { #ifndef CC_BUILD_TOUCH HWND hwnd = Window_Main.Handle.ptr; RECT rect; if (!grabCursor || !Input.RawMode) return; GetWindowRect(hwnd, &rect); - ClipCursor(&rect); + ClipCursor(&rect); #endif } @@ -154,17 +154,17 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara case WM_ERASEBKGND: return 1; /* Avoid flickering */ - case WM_PAINT: + case WM_PAINT: { hwnd = Window_Main.Handle.ptr; - //ValidateRect(hwnd, NULL); - PAINTSTRUCT ps; - HWND hwnd = Window_Main.Handle.ptr; - HDC hdc = BeginPaint(handle, &ps); + //ValidateRect(hwnd, NULL); + PAINTSTRUCT ps; + HWND hwnd = Window_Main.Handle.ptr; + HDC hdc = BeginPaint(handle, &ps); EndPaint(handle, &ps); Event_RaiseVoid(&WindowEvents.RedrawNeeded); return 0; - } + } case WM_SIZE: sized = RefreshWindowDimensions(); @@ -181,7 +181,7 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara /* TODO: Use WM_UNICHAR instead, as WM_CHAR is just utf16 */ Event_RaiseInt(&InputEvents.Press, (cc_unichar)wParam); break; - + #ifndef CC_BUILD_TOUCH case WM_MOUSEMOVE: /* Set before position change, in case mouse buttons changed when outside window */ @@ -193,35 +193,35 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara Pointer_SetPosition(0, LOWORD(lParam), HIWORD(lParam)); break; #else - case WM_MOUSEMOVE: - if (wParam & MK_LBUTTON) - Input_UpdateTouch(0, LOWORD(lParam), HIWORD(lParam)); - break; + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) + Input_UpdateTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; #endif case WM_MOUSEWHEEL: wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; Mouse_ScrollVWheel(wheelDelta); - return 0; + return 0; #ifndef CC_BUILD_TOUCH case WM_LBUTTONDOWN: - Input_SetPressed(CCMOUSE_L); break; + Input_SetPressed(CCMOUSE_L); break; #else case WM_LBUTTONDOWN: - Input_AddTouch(0, (short)LOWORD(lParam), (short)HIWORD(lParam)); - break; + Input_AddTouch(0, (short)LOWORD(lParam), (short)HIWORD(lParam)); + break; #endif case WM_MBUTTONDOWN: Input_SetPressed(CCMOUSE_M); break; case WM_RBUTTONDOWN: - Input_SetPressed(CCMOUSE_R); break; - + Input_SetPressed(CCMOUSE_R); break; + #ifndef CC_BUILD_TOUCH case WM_LBUTTONUP: - Input_SetReleased(CCMOUSE_L); break; -#else + Input_SetReleased(CCMOUSE_L); break; +#else case WM_LBUTTONUP: - Input_RemoveTouch(0, LOWORD(lParam), HIWORD(lParam)); - break; + Input_RemoveTouch(0, LOWORD(lParam), HIWORD(lParam)); + break; #endif case WM_MBUTTONUP: Input_SetReleased(CCMOUSE_M); break; @@ -265,11 +265,11 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara return 0; case WM_KILLFOCUS: - /* TODO: Keep track of keyboard when focus is lost */ + /* TODO: Keep track of keyboard when focus is lost */ #ifndef CC_BUILD_TOUCH - Input_Clear(); -#else - Input_SetTouchMode(TRUE); + Input_Clear(); +#else + Input_SetTouchMode(TRUE); #endif break; @@ -309,8 +309,8 @@ void Window_Init(void) { /* https://devblogs.microsoft.com/oldnewthing/20101013-00/?p=12543 */ /* TODO probably should always multiply? not just for 16 colors */ if (DisplayInfo.Depth != 1) return; - DisplayInfo.Depth *= GetDeviceCaps(hdc, PLANES); - Input_SetTouchMode(TRUE); + DisplayInfo.Depth *= GetDeviceCaps(hdc, PLANES); + Input_SetTouchMode(TRUE); //Gui_SetTouchUI(TRUE); } @@ -339,8 +339,8 @@ static HWND CreateWindowHandle(ATOM atom, int width, int height) { /* Calculate final window rectangle after window decorations are added (titlebar, borders etc) */ r.left = Display_CentreX(width); r.right = r.left + width; - r.top = Display_CentreY(height); r.bottom = r.top + height; - AdjustWindowRectEx(&r, CC_WIN_STYLE, false, 0); + r.top = Display_CentreY(height); r.bottom = r.top + height; + AdjustWindowRectEx(&r, CC_WIN_STYLE, false, 0); if ((hwnd = CreateWindowExW(0, CC_WIN_CLASSNAME, NULL, CC_WIN_STYLE, @@ -355,6 +355,9 @@ static void DoCreateWindow(int width, int height) { ATOM atom; HWND hwnd; + width = min(width, 240); + height = min(height, 160); + win_instance = GetModuleHandle(NULL); /* TODO: UngroupFromTaskbar(); */ width = Display_ScaleX(width); @@ -479,8 +482,8 @@ static void ToggleFullscreen(HWND hwnd, cc_bool fullscreen, UINT finalShow) { ShowWindow(hwnd, SW_RESTORE); /* reset maximised state */ SetWindowLong(hwnd, GWL_STYLE, style); SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - ShowWindow(hwnd, finalShow); - InvalidateRect(hwnd, NULL, TRUE); + ShowWindow(hwnd, finalShow); + InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); Window_ProcessEvents(0.0); } @@ -521,7 +524,7 @@ void Window_SetSize(int width, int height) { HWND hwnd = Window_Main.Handle.ptr; DWORD style = GetWindowLong(hwnd, GWL_STYLE); RECT rect = { 0, 0, width, height }; - AdjustWindowRectEx(&rect, CC_WIN_STYLE, false, 0); + AdjustWindowRectEx(&rect, CC_WIN_STYLE, false, 0); SetWindowPos(hwnd, NULL, 0, 0, Rect_Width(rect), Rect_Height(rect), SWP_NOMOVE); @@ -572,28 +575,28 @@ static void Cursor_DoSetVisible(cc_bool visible) { } else { for (i = 0; i < 50 && ShowCursor(false) >= 0; i++) {} } -} - -static void ShowDialogCore(const char* title, const char* msg) { - HWND hwnd = Window_Main.Handle.ptr; - - int tlen = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); - int mlen = MultiByteToWideChar(CP_UTF8, 0, msg, -1, NULL, 0); - - wchar_t* wtitle = (wchar_t*)malloc(tlen * sizeof(wchar_t)); - wchar_t* wmsg = (wchar_t*)malloc(mlen * sizeof(wchar_t)); - - MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, tlen); - MultiByteToWideChar(CP_UTF8, 0, msg, -1, wmsg, mlen); - - MessageBoxW(hwnd, wmsg, wtitle, 0); - - free(wtitle); - free(wmsg); -} +} + +static void ShowDialogCore(const char* title, const char* msg) { + HWND hwnd = Window_Main.Handle.ptr; + + int tlen = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); + int mlen = MultiByteToWideChar(CP_UTF8, 0, msg, -1, NULL, 0); + + wchar_t* wtitle = (wchar_t*)malloc(tlen * sizeof(wchar_t)); + wchar_t* wmsg = (wchar_t*)malloc(mlen * sizeof(wchar_t)); + + MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, tlen); + MultiByteToWideChar(CP_UTF8, 0, msg, -1, wmsg, mlen); + + MessageBoxW(hwnd, wmsg, wtitle, 0); + + free(wtitle); + free(wmsg); +} static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load, - const char* const* fileExts, const cc_string* defaultName) { + const char* const* fileExts, const cc_string* defaultName) { // TODO return 0; } @@ -679,15 +682,15 @@ void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } void OnscreenKeyboard_SetText(const cc_string* text) { } void OnscreenKeyboard_Close(void) { } - -void Window_EnableRawMouse(void) { - Input.RawMode = true; -} - -void Window_UpdateRawMouse(void) { } - -void Window_DisableRawMouse(void) { - Input.RawMode = false; -} + +void Window_EnableRawMouse(void) { + Input.RawMode = true; +} + +void Window_UpdateRawMouse(void) { } + +void Window_DisableRawMouse(void) { + Input.RawMode = false; +} #endif From c25b0053d052d0ea2b3dfbd903899ebab43a7c39 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 17 Sep 2025 20:12:51 +1000 Subject: [PATCH 104/115] fix --- src/Core.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Core.h b/src/Core.h index 70d229429..d14569f79 100644 --- a/src/Core.h +++ b/src/Core.h @@ -138,6 +138,7 @@ typedef cc_uint8 cc_bool; #define CC_WIN_BACKEND_COCOA 6 #define CC_WIN_BACKEND_BEOS 7 #define CC_WIN_BACKEND_ANDROID 8 +#define CC_WIN_BACKEND_WIN32CE 9 #define CC_GFX_BACKEND_SOFTGPU 1 #define CC_GFX_BACKEND_GL1 2 @@ -147,7 +148,7 @@ typedef cc_uint8 cc_bool; #define CC_GFX_BACKEND_VULKAN 6 #define CC_GFX_BACKEND_GL11 7 #define CC_GFX_BACKEND_SOFTMIN 8 -#define CC_GFX_BACKEND_SOFTFP 9 +#define CC_GFX_BACKEND_SOFTFP 9 #define CC_SSL_BACKEND_NONE 1 #define CC_SSL_BACKEND_BEARSSL 2 From 1f58533518a80f1b4a063060955f9f800388b60a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 18 Sep 2025 07:53:53 +1000 Subject: [PATCH 105/115] GC/Wii: Use twiddled style calculation for texture upload --- src/gcwii/Graphics_GCWii.c | 89 +++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index e3321c246..04d673005 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -109,44 +109,66 @@ typedef struct CCTexture_ { // GX RGBA8 textures // - store pixels in 4x4 tiles // - store all of the AR values of the tile's pixels, then store all of the GB values -static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp, - int originX, int originY, int rowWidth) { - int stride = GX_GetTexObjWidth(&tex->obj) * 4; - // TODO not really right - // TODO originX ignored - originX &= ~0x03; - originY &= ~0x03; - - // http://hitmen.c02.at/files/yagcd/yagcd/chap15.html - // section 15.35 TPL (Texture Palette) - // "RGBA8 (4x4 tiles in two cache lines - first is AR and second is GB" - uint8_t *src = (uint8_t*)bmp->scan0; - uint8_t *dst = (uint8_t*)tex->pixels + stride * originY; - int srcWidth = bmp->width, srcHeight = bmp->height; - - for (int tileY = 0; tileY < srcHeight; tileY += 4) - for (int tileX = 0; tileX < srcWidth; tileX += 4) - { - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - uint32_t idx = (((tileY + y) * rowWidth) + tileX + x) << 2; +// +// http://hitmen.c02.at/files/yagcd/yagcd/chap15.html +// section 15.35 TPL (Texture Palette) +// "RGBA8 (4x4 tiles in two cache lines - first is AR and second is GB" +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, + unsigned* maskX, unsigned* maskY) { + *maskX = 0b00011; // 2 linear X bits, 1 bit until next block + *maskY = 0b01100; // 2 linear Y bits, 1 bit until next block - *dst++ = src[idx + 0]; // A - *dst++ = src[idx + 1]; // R - } - } - - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - uint32_t idx = (((tileY + y) * rowWidth) + tileX + x) << 2; + // Lower 2 X and Y bits are always linear + w >>= 3; + h >>= 3; + int shift = 5; - *dst++ = src[idx + 2]; // G - *dst++ = src[idx + 3]; // B - } - } + for (; w > 0; w >>= 1) { + *maskX += 0x01 << shift; + shift += 1; + } + + for (; h > 0; h >>= 1) { + *maskY += 0x01 << shift; + shift += 1; } } +static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp, + int originX, int originY, int rowWidth) { + int src_w = bmp->width, dst_w = GX_GetTexObjWidth(&tex->obj); + int src_h = bmp->height, dst_h = GX_GetTexObjHeight(&tex->obj); + + cc_uint16* dst_AR = (cc_uint16*)tex->pixels; + cc_uint16* dst_GB = (cc_uint16*)tex->pixels + 16; // offset by a 4x4 block + cc_uint32* src = bmp->scan0; + + unsigned maskX, maskY; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + unsigned begX = 0, begY = 0; + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { begX = (begX - maskX) & maskX; } + for (int y = 0; y < originY; y++) { begY = (begY - maskY) & maskY; } + + unsigned Y = begY; + for (int y = 0; y < src_h; y++) + { + unsigned X = begX; + for (int x = 0; x < src_w; x++) + { + BitmapCol c = src[x]; + dst_AR[X | Y] = (BitmapCol_A(c) << 8) | BitmapCol_R(c); + dst_GB[X | Y] = (BitmapCol_G(c) << 8) | BitmapCol_B(c); + + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + src += rowWidth; + } +} + +// TODO non power of two upload GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { int size = bmp->width * bmp->height * 4; CCTexture* tex = (CCTexture*)memalign(32, 32 + size); @@ -163,7 +185,6 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { CCTexture* tex = (CCTexture*)texId; - // TODO: wrong behaviour if x/y/part isn't multiple of 4 pixels ReorderPixels(tex, part, x, y, rowWidth); GX_InvalidateTexAll(); } From deb7538384d114ce101b3a20745e49cd2479c393 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 18 Sep 2025 21:19:46 +1000 Subject: [PATCH 106/115] PSP: WIP implementing raw GPU command API --- misc/psp/Makefile | 6 ++-- misc/vita/Makefile | 6 ++-- src/psp/Graphics_PSP.c | 18 ++++++------ src/psp/ge_gpu.h | 63 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 src/psp/ge_gpu.h diff --git a/misc/psp/Makefile b/misc/psp/Makefile index 0295f3422..76fd47eb8 100644 --- a/misc/psp/Makefile +++ b/misc/psp/Makefile @@ -18,7 +18,9 @@ SOURCE_DIRS = src src/psp third_party/bearssl # Directory where object files are placed BUILD_DIR = build/psp -PSP_EBOOT_TITLE = ClassiCube +SFO_TITLE = ClassiCube +SFO_DISCID = CUBE02000 + PSP_EBOOT_ICON = misc/psp/ICON0.png PSP_EBOOT_SFO = PARAM.SFO PSP_EBOOT_ICON1 = NULL @@ -82,7 +84,7 @@ $(TARGET).prx: $(TARGET).elf $(PRXGEN) $< $@ $(PSP_EBOOT_SFO): - $(MKSFO) -d MEMSIZE=1 '$(PSP_EBOOT_TITLE)' $@ + $(MKSFO) -d MEMSIZE=1 -s DISC_ID="$(SFO_DISCID)" '$(SFO_TITLE)' $@ $(PSP_EBOOT): $(TARGET).prx $(PSP_EBOOT_SFO) $(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ diff --git a/misc/vita/Makefile b/misc/vita/Makefile index aad057883..2125b292c 100644 --- a/misc/vita/Makefile +++ b/misc/vita/Makefile @@ -17,8 +17,8 @@ SOURCE_DIRS = src src/psvita third_party/bearssl # Directory where object files are placed BUILD_DIR = build/vita -PROJECT_TITLE = ClassiCube -PROJECT_TITLEID = CUBE00200 +SFO_TITLE = ClassiCube +SFO_TITLEID = CUBE00200 #--------------------------------------------------------------------------------- @@ -78,7 +78,7 @@ eboot.bin: $(TARGET).velf $(MAKE_FSELF) $(TARGET).velf eboot.bin param.sfo: - $(MKSOFEX) -s TITLE_ID="$(PROJECT_TITLEID)" "$(PROJECT_TITLE)" param.sfo + $(MKSOFEX) -s TITLE_ID="$(SFO_TITLEID)" "$(SFO_TITLE)" param.sfo $(TARGET).velf: $(TARGET).elf $(VITA_STRIP) -g $< diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index e6ef5dc98..03ddb2934 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -9,6 +9,7 @@ #include #include #include +#include "ge_gpu.h" #define BUFFER_WIDTH 512 #define SCREEN_WIDTH 480 @@ -26,13 +27,11 @@ static int formatFields[] = { GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_3D, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D }; -static ScePspFMatrix4 identity; static void guInit(void) { void* framebuffer0 = (void*)0; void* framebuffer1 = (void*)FB_SIZE; void* depthbuffer = (void*)(FB_SIZE + FB_SIZE); - Mem_Copy(&identity, &Matrix_Identity, sizeof(ScePspFMatrix4)); sceGuInit(); sceGuStart(GU_DIRECT, list); @@ -53,8 +52,7 @@ static void guInit(void) { sceGuClearDepth(65535); // sceGuClearDepth(0); sceGuDepthRange(0, 65535); // sceGuDepthRange(65535, 0); - - sceGuSetMatrix(GU_MODEL, &identity); + GE_upload_world_matrix((const float*)&Matrix_Identity); sceGuColor(0xffffffff); sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); sceGuDisable(GU_SCISSOR_TEST); @@ -394,12 +392,14 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) { /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ -static int matrix_modes[] = { GU_PROJECTION, GU_VIEW }; -static ScePspFMatrix4 tmp_matrix; // 16 byte aligned - void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { - Mem_Copy(&tmp_matrix, matrix, sizeof(ScePspFMatrix4)); - sceGuSetMatrix(matrix_modes[type], &tmp_matrix); + const float* m = (const float*)matrix; + + if (type == MATRIX_PROJ) { + GE_upload_proj_matrix(m); + } else { + GE_upload_view_matrix(m); + } } void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Matrix* mvp) { diff --git a/src/psp/ge_gpu.h b/src/psp/ge_gpu.h new file mode 100644 index 000000000..bf285c35c --- /dev/null +++ b/src/psp/ge_gpu.h @@ -0,0 +1,63 @@ +#include "../Funcs.h" + +// Hacky way to access GU's command buffer +extern struct GuDisplayListInternal +{ + unsigned int* start; + unsigned int* current; +} *gu_list; + +enum GE_COMMANDS { + GE_WORLDMATRIX_UPLOAD_INDEX = 0x3A, + GE_WORLDMATRIX_UPLOAD_DATA = 0x3B, + GE_VIEW_MATRIX_UPLOAD_INDEX = 0x3C, + GE_VIEW_MATRIX_UPLOAD_DATA = 0x3D, + GE_PROJ_MATRIX_UPLOAD_INDEX = 0x3E, + GE_PROJ_MATRIX_UPLOAD_DATA = 0x3F, +}; + + +// upper 8 bits are opcode, lower 24 bits are argument +#define GE_OPCODE_SHIFT 24 +static CC_INLINE void GE_PushI(int cmd, int argument) { + *(gu_list->current++) = (cmd << GE_OPCODE_SHIFT) | (argument & 0xffffff); +} + +static CC_INLINE void GE_PushF(int cmd, float argument) { + union IntAndFloat raw; raw.f = argument; + *(gu_list->current++) = (cmd << GE_OPCODE_SHIFT) | (raw.u >> 8); +} + + +/*########################################################################################################################* +*-----------------------------------------------------Matrix upload-------------------------------------------------------* +*#########################################################################################################################*/ +static void GE_upload_world_matrix(const float* matrix) { + GE_PushI(GE_WORLDMATRIX_UPLOAD_INDEX, 0); // uploading all 3x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 3; j++) + { + GE_PushF(GE_WORLDMATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} + +static void GE_upload_view_matrix(const float* matrix) { + GE_PushI(GE_VIEW_MATRIX_UPLOAD_INDEX, 0); // uploading all 3x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 3; j++) + { + GE_PushF(GE_VIEW_MATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} + +static void GE_upload_proj_matrix(const float* matrix) { + GE_PushI(GE_PROJ_MATRIX_UPLOAD_INDEX, 0); // uploading all 4x4 entries + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + { + GE_PushF(GE_PROJ_MATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); + } +} From 514b10f66262d57084e2d011ea730e7d110a4a7d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 19 Sep 2025 06:48:23 +1000 Subject: [PATCH 107/115] PSP: Save 1 GPU command per draw call --- misc/psp/README.md | 4 ++++ src/gcwii/Graphics_GCWii.c | 9 ++++++--- src/psp/Graphics_PSP.c | 36 ++++++++++++++++++++++-------------- src/psp/ge_gpu.h | 20 +++++++++++++++++++- 4 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 misc/psp/README.md diff --git a/misc/psp/README.md b/misc/psp/README.md new file mode 100644 index 000000000..d9ae102a4 --- /dev/null +++ b/misc/psp/README.md @@ -0,0 +1,4 @@ +To see debug log messages in PPSSPP: + +1) Make sure 'printf' log level in Logging Channels is set to "Debug" + diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index 04d673005..cfe4acce7 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -60,6 +60,7 @@ void Gfx_Create(void) { Gfx.MaxTexWidth = 1024; Gfx.MaxTexHeight = 1024; Gfx.MaxTexSize = 512 * 512; + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; Gfx.MinTexWidth = 4; Gfx.MinTexHeight = 4; @@ -168,13 +169,15 @@ static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp, } } -// TODO non power of two upload GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + int size = dst_w * dst_h * 4; CCTexture* tex = (CCTexture*)memalign(32, 32 + size); if (!tex) return NULL; - GX_InitTexObj(&tex->obj, tex->pixels, bmp->width, bmp->height, + GX_InitTexObj(&tex->obj, tex->pixels, dst_w, dst_h, GX_TF_RGBA8, GX_REPEAT, GX_REPEAT, GX_FALSE); GX_InitTexObjFilterMode(&tex->obj, GX_NEAR, GX_NEAR); diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index 03ddb2934..8f0e34345 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -18,7 +18,9 @@ #define FB_SIZE (BUFFER_WIDTH * SCREEN_HEIGHT * 4) static unsigned int __attribute__((aligned(16))) list[262144]; -#define GE_CMD_TEXTUREMAPENABLE 0x1E +static cc_uint8* gfx_vertices; +static int gfx_fields; + /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* @@ -61,7 +63,7 @@ static void guInit(void) { sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); sceGuFinish(); - sceGuSync(0,0); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); sceDisplayWaitVblankStart(); sceGuDisplay(GU_TRUE); } @@ -156,7 +158,7 @@ void Gfx_BindTexture(GfxResourceID texId) { CCTexture* tex = (CCTexture*)texId; if (!tex) tex = white_square; - sceGuTexMode(GU_PSM_8888,0,0,0); + sceGuTexMode(GU_PSM_8888, 0, 0, 0); sceGuTexImage(0, tex->width, tex->height, tex->width, tex->pixels); } @@ -186,7 +188,7 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { } void Gfx_SetDepthWrite(cc_bool enabled) { - sceGuDepthMask(enabled ? 0 : 0xffffffff); + sceGuDepthMask(enabled ? 0 : 0xffffffff); } void Gfx_SetDepthTest(cc_bool enabled) { GU_Toggle(GU_DEPTH_TEST); } @@ -272,11 +274,13 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { if (buffers & GFX_BUFFER_DEPTH) targets |= GU_DEPTH_BUFFER_BIT; sceGuClear(targets); + // Clear involves draw commands + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_EndFrame(void) { sceGuFinish(); - sceGuSync(0, 0); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); if (gfx_vsync) sceDisplayWaitVblankStart(); sceGuSwapBuffers(); @@ -288,10 +292,6 @@ void Gfx_SetViewport(int x, int y, int w, int h) { } void Gfx_SetScissor (int x, int y, int w, int h) { } -static cc_uint8* gfx_vertices; -static int gfx_fields; - - /*########################################################################################################################* *----------------------------------------------------------Buffers--------------------------------------------------------* *#########################################################################################################################*/ @@ -303,7 +303,10 @@ GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { return gfx_indices; } -void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_BindIb(GfxResourceID ib) { + // TODO doesn't work properly + //GE_set_index_buffer(ib); +} void Gfx_DeleteIb(GfxResourceID* ib) { } @@ -435,23 +438,28 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { } else { sceGuDisable(GU_TEXTURE_2D); } + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_DrawVb_Lines(int verticesCount) { - sceGuDrawArray(GU_LINES, gfx_fields, verticesCount, NULL, gfx_vertices); + // More efficient to set "indexed 16 bit" as default in Gfx_SetVertexFormat, + // rather than in every single triangle draw command + GE_set_vertex_format(gfx_fields); + sceGuDrawArray(GU_LINES, 0, verticesCount, NULL, gfx_vertices); + GE_set_vertex_format(gfx_fields | GU_INDEX_16BIT); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex, DrawHints hints) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices + startVertex * gfx_stride); } void Gfx_DrawVb_IndexedTris(int verticesCount) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices); } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - sceGuDrawArray(GU_TRIANGLES, gfx_fields | GU_INDEX_16BIT, ICOUNT(verticesCount), + sceGuDrawArray(GU_TRIANGLES, 0, ICOUNT(verticesCount), gfx_indices, gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED); } diff --git a/src/psp/ge_gpu.h b/src/psp/ge_gpu.h index bf285c35c..80478b46e 100644 --- a/src/psp/ge_gpu.h +++ b/src/psp/ge_gpu.h @@ -1,5 +1,6 @@ #include "../Funcs.h" +// https://github.com/pspdev/pspsdk/blob/c84807b8503fdf031d089cc0c6363d2d87715974/src/gu/doc/commands.txt // Hacky way to access GU's command buffer extern struct GuDisplayListInternal { @@ -8,12 +9,21 @@ extern struct GuDisplayListInternal } *gu_list; enum GE_COMMANDS { + GE_NOP = 0x00, + GE_SET_VB_ADDR = 0x01, + GE_SET_IB_ADDR = 0x02, + GE_SET_BASE_ADDR = 0x10, + GE_SET_VERTEX_FORMAT = 0x12, GE_WORLDMATRIX_UPLOAD_INDEX = 0x3A, GE_WORLDMATRIX_UPLOAD_DATA = 0x3B, GE_VIEW_MATRIX_UPLOAD_INDEX = 0x3C, GE_VIEW_MATRIX_UPLOAD_DATA = 0x3D, GE_PROJ_MATRIX_UPLOAD_INDEX = 0x3E, - GE_PROJ_MATRIX_UPLOAD_DATA = 0x3F, + GE_PROJ_MATRIX_UPLOAD_DATA = 0x3F, + + GE_SET_DEPTH_MASK = 0xE7, + GE_SET_COLOR_MASK = 0xE8, + GE_SET_ALPHA_MASK = 0xE9, }; @@ -61,3 +71,11 @@ static void GE_upload_proj_matrix(const float* matrix) { GE_PushF(GE_PROJ_MATRIX_UPLOAD_DATA, matrix[(i * 4) + j]); } } + + +/*########################################################################################################################* +*----------------------------------------------------Vertex drawing-------------------------------------------------------* +*#########################################################################################################################*/ +static CC_INLINE void GE_set_vertex_format(int format) { + GE_PushI(GE_SET_VERTEX_FORMAT, format); +} From 2e7a5c98973b1870679806598a78a76b9d19490a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 19 Sep 2025 07:32:02 +1000 Subject: [PATCH 108/115] PSP: Use swizzled textures --- src/gcwii/Graphics_GCWii.c | 2 +- src/psp/Graphics_PSP.c | 106 ++++++++++++++++++++++++++++------- src/psvita/Graphics_PSVita.c | 87 +++++++++++++++------------- 3 files changed, 135 insertions(+), 60 deletions(-) diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index cfe4acce7..8cd71c6cd 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -119,7 +119,7 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, *maskX = 0b00011; // 2 linear X bits, 1 bit until next block *maskY = 0b01100; // 2 linear Y bits, 1 bit until next block - // Lower 2 X and Y bits are always linear + // Adjust for lower 2 X and 2 Y linear bits w >>= 3; h >>= 3; int shift = 5; diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index 8f0e34345..dec23e21f 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -74,6 +74,7 @@ void Gfx_Create(void) { Gfx.MaxTexWidth = 512; Gfx.MaxTexHeight = 512; + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; Gfx.Created = true; gfx_vsync = true; @@ -103,6 +104,79 @@ static void Gfx_FreeState(void) { #define GU_Toggle(cap) if (enabled) { sceGuEnable(cap); } else { sceGuDisable(cap); } + + +/*########################################################################################################################* +*---------------------------------------------------------Swizzling-------------------------------------------------------* +*#########################################################################################################################*/ +// PSP swizzled textures are 16 bytes X 8 rows = 4 '32 bit' pixels X 8 rows +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) { + *maskX = 0b00011; // 2 linear X bits + *maskY = 0b11100; // 3 linear Y bits + + // Adjust for lower 2 X and 2 Y linear bits + w >>= 3; + h >>= 4; + int shift = 5; + + for (; w > 0; w >>= 1) { + *maskX += 0x01 << shift; + shift += 1; + } + + for (; h > 0; h >>= 1) { + *maskY += 0x01 << shift; + shift += 1; + } +} + +static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) { + int src_w = bmp->width, src_h = bmp->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = bmp->scan0 + y * rowWidth; + X = 0; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + +static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h, + int originX, int originY) { + int src_w = part->width, src_h = part->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } + for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } + unsigned startX = X; + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = part->scan0 + y * rowWidth; + X = startX; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + + /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ @@ -113,38 +187,28 @@ typedef struct CCTexture_ { } CCTexture; GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int size = bmp->width * bmp->height * 4; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + // Swizzled texture assumes at least 16 bytes x 8 rows + int size = max(16 * 8, dst_w * dst_h * 4); CCTexture* tex = (CCTexture*)memalign(16, 16 + size); - tex->width = bmp->width; - tex->height = bmp->height; + tex->width = dst_w; + tex->height = dst_h; - CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE, - bmp->scan0, rowWidth * BITMAPCOLOR_SIZE, - bmp->width, bmp->height); + UploadFullTexture(bmp, rowWidth, tex->pixels, dst_w, dst_h); return tex; } void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { CCTexture* tex = (CCTexture*)texId; - BitmapCol* dst = (tex->pixels + x) + y * tex->width; + UploadPartialTexture(part, rowWidth, tex->pixels, tex->width, tex->height, x, y); - CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE, - part->scan0, rowWidth * BITMAPCOLOR_SIZE, - part->width, part->height); // TODO: Do line by line and only invalidate the actually changed parts of lines? - sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4); + sceKernelDcacheWritebackInvalidateRange(tex->pixels, (tex->width * tex->height) * 4); } -/*void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { - CCTexture* tex = (CCTexture*)texId; - cc_uint32* dst = (tex->pixels + x) + y * tex->width; - - for (int yy = 0; yy < part->height; yy++) { - Mem_Copy(dst + (y + yy) * tex->width, part->scan0 + yy * rowWidth, part->width * 4); - } -}*/ - void Gfx_DeleteTexture(GfxResourceID* texId) { GfxResourceID data = *texId; if (data) Mem_Free(data); @@ -158,7 +222,7 @@ void Gfx_BindTexture(GfxResourceID texId) { CCTexture* tex = (CCTexture*)texId; if (!tex) tex = white_square; - sceGuTexMode(GU_PSM_8888, 0, 0, 0); + sceGuTexMode(GU_PSM_8888, 0, 0, 1); sceGuTexImage(0, tex->width, tex->height, tex->width, tex->pixels); } diff --git a/src/psvita/Graphics_PSVita.c b/src/psvita/Graphics_PSVita.c index c0790f71e..d2ba2025c 100644 --- a/src/psvita/Graphics_PSVita.c +++ b/src/psvita/Graphics_PSVita.c @@ -673,9 +673,12 @@ static void GPUTextures_DeleteUnreferenced(void) { } } + +/*########################################################################################################################* +*---------------------------------------------------------Swizzling-------------------------------------------------------* +*#########################################################################################################################*/ // See Graphics_Dreamcast.c for twiddling explanation -static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, - unsigned* maskX, unsigned* maskY) { +static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) { *maskX = 0; *maskY = 0; int shift = 0; @@ -699,18 +702,7 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, } } - -/*########################################################################################################################* -*---------------------------------------------------------Textures--------------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - int dst_w = Math_NextPowOf2(bmp->width); - int dst_h = Math_NextPowOf2(bmp->height); - int size = dst_w * dst_h * 4; - - struct GPUTexture* tex = GPUTexture_Alloc(size); - cc_uint32* dst = tex->data; - +static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) { int src_w = bmp->width, src_h = bmp->height; unsigned maskX, maskY; unsigned X = 0, Y = 0; @@ -728,6 +720,46 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, } Y = (Y - maskY) & maskY; } +} + +static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h, + int originX, int originY) { + int src_w = part->width, src_h = part->height; + unsigned maskX, maskY; + unsigned X = 0, Y = 0; + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); + + // Calculate start twiddled X and Y values + for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } + for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } + unsigned startX = X; + + for (int y = 0; y < src_h; y++) + { + cc_uint32* src = part->scan0 + y * rowWidth; + X = startX; + + for (int x = 0; x < src_w; x++, src++) + { + dst[X | Y] = *src; + X = (X - maskX) & maskX; + } + Y = (Y - maskY) & maskY; + } +} + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + int size = dst_w * dst_h * 4; + + struct GPUTexture* tex = GPUTexture_Alloc(size); + cc_uint32* dst = tex->data; + UploadFullTexture(bmp, rowWidth, dst, dst_w, dst_h); sceGxmTextureInitSwizzled(&tex->texture, dst, SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, dst_w, dst_h, 0); @@ -741,33 +773,12 @@ void Gfx_UpdateTexture(GfxResourceID texId, int originX, int originY, struct Bit struct GPUTexture* tex = (struct GPUTexture*)texId; int texWidth = sceGxmTextureGetWidth(&tex->texture); int texHeight = sceGxmTextureGetHeight(&tex->texture); - cc_uint32* dst = tex->data; - - int width = part->width, height = part->height; - unsigned maskX, maskY; - unsigned X = 0, Y = 0; - TwiddleCalcFactors(texWidth, texHeight, &maskX, &maskY); - // Calculate start twiddled X and Y values - for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; } - for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; } - unsigned startX = X; - - for (int y = 0; y < height; y++) - { - cc_uint32* src = part->scan0 + rowWidth * y; - X = startX; - - for (int x = 0; x < width; x++, src++) - { - dst[X | Y] = *src; - X = (X - maskX) & maskX; - } - Y = (Y - maskY) & maskY; - } + cc_uint32* dst = tex->data; + UploadPartialTexture(part, rowWidth, dst, texWidth, texHeight, originX, originY); // TODO: is it necessary to invalidate? probably just everything? - //sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4); + //sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * tex->height) * 4); } void Gfx_DeleteTexture(GfxResourceID* texId) { From 0efd939a2d8dd34483971ac1c6d3a0620c3dcacd Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 19 Sep 2025 19:12:00 +1000 Subject: [PATCH 109/115] Dreamcast: Include thread name in crash dump --- misc/vita/Makefile | 2 +- src/SSL.c | 6 ++---- src/dreamcast/Platform_Dreamcast.c | 12 ++++++++++-- src/psp/Graphics_PSP.c | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/misc/vita/Makefile b/misc/vita/Makefile index 2125b292c..02a411cac 100644 --- a/misc/vita/Makefile +++ b/misc/vita/Makefile @@ -35,7 +35,7 @@ DEPFILES := $(OBJS:%.o=%.d) #--------------------------------------------------------------------------------- # Code generation #--------------------------------------------------------------------------------- -CFLAGS = -O1 -DPLAT_VITA +CFLAGS = -O1 -DPLAT_VITA -fno-math-errno LDFLAGS = -Wl,-q LIBS = -lm -lSceDisplay_stub -lSceCtrl_stub -lSceTouch_stub -lSceGxm_stub -lSceCommonDialog_stub -lSceAppUtil_stub diff --git a/src/SSL.c b/src/SSL.c index 12bc3222a..fbb40e514 100644 --- a/src/SSL.c +++ b/src/SSL.c @@ -58,10 +58,8 @@ static unsigned x509_maybe_skip_verify(unsigned r) { if (r != BR_ERR_X509_EXPIRED) return r; cc_uint64 cur = DateTime_CurrentUTC(); - uint32_t days = (uint32_t)(cur / 86400) + 366; - - /* Time earlier than August 2024 usually mean an improperly calibrated RTC */ - if (days < 739464) return 0; + /* Time earlier than 19 Sep 2025 usually mean an improperly calibrated RTC */ + if (cur < 63893864669ull) return 0; #endif return r; diff --git a/src/dreamcast/Platform_Dreamcast.c b/src/dreamcast/Platform_Dreamcast.c index e81133c2b..bddd9f873 100644 --- a/src/dreamcast/Platform_Dreamcast.c +++ b/src/dreamcast/Platform_Dreamcast.c @@ -144,6 +144,13 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *-------------------------------------------------------Crash handling----------------------------------------------------* *#########################################################################################################################*/ +static cc_string GetThreadName(void) { + kthread_t* thd = thd_get_current(); + if (!thd) return String_FromReadonly("(unknown)"); + + return String_FromRawArray(thd->label); +} + static void HandleCrash(irq_t evt, irq_context_t* ctx, void* data) { uint32_t code = evt; log_timestamp = false; @@ -152,9 +159,10 @@ static void HandleCrash(irq_t evt, irq_context_t* ctx, void* data) { for (;;) { + cc_string name = GetThreadName(); Platform_LogConst("** CLASSICUBE FATALLY CRASHED **"); - Platform_Log2("PC: %h, error: %h", - &ctx->pc, &code); + Platform_Log3("PC: %h, error: %h, thd: %s", + &ctx->pc, &code, &name); Platform_LogConst(""); static const char* const regNames[] = { diff --git a/src/psp/Graphics_PSP.c b/src/psp/Graphics_PSP.c index dec23e21f..6a9eda4d1 100644 --- a/src/psp/Graphics_PSP.c +++ b/src/psp/Graphics_PSP.c @@ -206,6 +206,7 @@ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, i UploadPartialTexture(part, rowWidth, tex->pixels, tex->width, tex->height, x, y); // TODO: Do line by line and only invalidate the actually changed parts of lines? + // TODO: Invalidate full tex->size in case of very small textures? sceKernelDcacheWritebackInvalidateRange(tex->pixels, (tex->width * tex->height) * 4); } From f1d8dedd6f85cfeca6235c95452c89cbeb7a04fb Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 21 Sep 2025 09:07:10 +1000 Subject: [PATCH 110/115] Dreamcast: Try to fix crashes when playing music --- src/dreamcast/Audio_Dreamcast.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/dreamcast/Audio_Dreamcast.c b/src/dreamcast/Audio_Dreamcast.c index 64250b926..71e5a3774 100644 --- a/src/dreamcast/Audio_Dreamcast.c +++ b/src/dreamcast/Audio_Dreamcast.c @@ -2,7 +2,12 @@ #include "../Audio.h" /* TODO needs way more testing, especially with sounds */ -static cc_bool valid_handles[SND_STREAM_MAX]; +#define HANDLE_STATE_UNUSED 0 +#define HANDLE_STATE_ALLOCATED 1 +#define HANDLE_STATE_PLAYABLE 2 +// Need to manually track playable state, to avoid triggering divide by zero when 0 channels in poll +// https://github.com/KallistiOS/KallistiOS/pull/1099 - but manually check this to support older toolchains +static cc_uint8 valid_handles[SND_STREAM_MAX]; struct AudioBuffer { int available; @@ -28,7 +33,7 @@ void AudioBackend_Tick(void) { // TODO is this really threadsafe with music? should this be done in Audio_Poll instead? for (int i = 0; i < SND_STREAM_MAX; i++) { - if (valid_handles[i]) snd_stream_poll(i); + if (valid_handles[i] == HANDLE_STATE_PLAYABLE) snd_stream_poll(i); } } @@ -70,7 +75,7 @@ cc_result Audio_Init(struct AudioContext* ctx, int buffers) { ctx->count = buffers; ctx->bufHead = 0; - valid_handles[ctx->hnd] = true; + valid_handles[ctx->hnd] = HANDLE_STATE_ALLOCATED; return 0; } @@ -78,7 +83,7 @@ void Audio_Close(struct AudioContext* ctx) { if (ctx->count) { snd_stream_stop(ctx->hnd); snd_stream_destroy(ctx->hnd); - valid_handles[ctx->hnd] = false; + valid_handles[ctx->hnd] = HANDLE_STATE_UNUSED; } ctx->hnd = SND_STREAM_INVALID; @@ -115,6 +120,7 @@ cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) { cc_result Audio_Play(struct AudioContext* ctx) { snd_stream_start(ctx->hnd, ctx->sampleRate, ctx->channels == 2); + valid_handles[ctx->hnd] = HANDLE_STATE_PLAYABLE; return 0; } From 7ccfdf06609659fce1dc8fb5463dbd69e769785b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 21 Sep 2025 21:04:27 +1000 Subject: [PATCH 111/115] Dreamcast: B+L/R switch hotbar slot, WIP screenshot support --- src/Bitmap.c | 3 +- src/dreamcast/Graphics_Dreamcast.c | 50 +++++++++++++++++++----------- src/dreamcast/Window_Dreamcast.c | 5 +-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/Bitmap.c b/src/Bitmap.c index e4077ec1f..4854a1538 100644 --- a/src/Bitmap.c +++ b/src/Bitmap.c @@ -678,7 +678,7 @@ static cc_result Png_EncodeCore(struct Bitmap* bmp, struct Stream* stream, cc_ui cc_uint8* curLine = buffer + (bmp->width * 4) * 1; cc_uint8* bestLine = buffer + (bmp->width * 4) * 2; -#if CC_BUILD_MAXSTACK <= (50 * 1024) +#if CC_BUILD_MAXSTACK <= (64 * 1024) struct ZLibState* zlState = (struct ZLibState*)Mem_TryAlloc(1, sizeof(struct ZLibState)); #else struct ZLibState _zlState; @@ -689,6 +689,7 @@ static cc_result Png_EncodeCore(struct Bitmap* bmp, struct Stream* stream, cc_ui int y, lineSize; cc_result res; + if (!zlState) return ERR_OUT_OF_MEMORY; /* stream may not start at 0 (e.g. when making default.zip) */ if ((res = stream->Position(stream, &stream_beg))) return res; diff --git a/src/dreamcast/Graphics_Dreamcast.c b/src/dreamcast/Graphics_Dreamcast.c index 38f3d6ed8..861684967 100644 --- a/src/dreamcast/Graphics_Dreamcast.c +++ b/src/dreamcast/Graphics_Dreamcast.c @@ -718,7 +718,6 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f *-------------------------------------------------------Index buffers-----------------------------------------------------* *#########################################################################################################################*/ static void* gfx_vertices; -static int vb_size; GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { return (void*)1; @@ -743,15 +742,9 @@ void Gfx_DeleteVb(GfxResourceID* vb) { *vb = 0; } -void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; -} +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } -void Gfx_UnlockVb(GfxResourceID vb) { - gfx_vertices = vb; - //sceKernelDcacheWritebackInvalidateRange(vb, vb_size); -} +void Gfx_UnlockVb(GfxResourceID vb) { gfx_vertices = vb; } static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { @@ -760,15 +753,9 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - vb_size = count * strideSizes[fmt]; - return vb; -} +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; - //dcache_flush_range(vb, vb_size); -} +void Gfx_UnlockDynamicVb(GfxResourceID vb) { gfx_vertices = vb; } void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } @@ -988,8 +975,35 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { /*########################################################################################################################* *-----------------------------------------------------------Misc----------------------------------------------------------* *#########################################################################################################################*/ +static BitmapCol* DC_GetRow(struct Bitmap* bmp, int y, void* ctx) { + BitmapCol* tmp = (BitmapCol*)ctx; + uint16_t* src = vram_s + vid_mode->width * y; + int r, g, b, width = bmp->width; + + for (int x = 0; x < width; x++) + { + int r, g, b; + // RGB565 to RGB888 + r = ((src[x] >> 11) & 0x1F) << 3; + g = ((src[x] >> 6) & 0x3F) << 2; + b = ((src[x] >> 0) & 0x1F) << 3; + + tmp[x] = BitmapColor_RGB(r, g, b); + } + return tmp; +} + cc_result Gfx_TakeScreenshot(struct Stream* output) { - return ERR_NOT_SUPPORTED; + BitmapCol tmp[640]; + int width = vid_mode->width; + int height = vid_mode->height; + + struct Bitmap bmp; + bmp.scan0 = tmp; + bmp.width = width; + bmp.height = height; + + return Png_Encode(&bmp, output, DC_GetRow, false, tmp); } void Gfx_GetApiInfo(cc_string* info) { diff --git a/src/dreamcast/Window_Dreamcast.c b/src/dreamcast/Window_Dreamcast.c index e62050ba3..89fdb6554 100644 --- a/src/dreamcast/Window_Dreamcast.c +++ b/src/dreamcast/Window_Dreamcast.c @@ -239,8 +239,9 @@ static const BindMapping defaults_dc[BIND_COUNT] = { [BIND_NOCLIP] = { CCPAD_2, CCPAD_3 }, [BIND_FLY_UP] = { CCPAD_2, CCPAD_UP }, [BIND_FLY_DOWN] = { CCPAD_2, CCPAD_DOWN }, - [BIND_HOTBAR_LEFT] = { CCPAD_ZL }, - [BIND_HOTBAR_RIGHT] = { CCPAD_ZR } + [BIND_HOTBAR_LEFT] = { CCPAD_2, CCPAD_LEFT }, + [BIND_HOTBAR_RIGHT] = { CCPAD_2, CCPAD_RIGHT }, + [BIND_SCREENSHOT] = { CCPAD_3 }, }; void Gamepads_Init(void) { From 6a05c829524626053d2e8d4d5079c7db0569739e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 22 Sep 2025 06:41:13 +1000 Subject: [PATCH 112/115] GC/Wii: WIP using custom graphics API --- src/dreamcast/Graphics_Dreamcast.c | 3 +- src/gcwii/Graphics_GCWii.c | 24 +++--- src/gcwii/gx_gpu.h | 132 +++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 13 deletions(-) create mode 100644 src/gcwii/gx_gpu.h diff --git a/src/dreamcast/Graphics_Dreamcast.c b/src/dreamcast/Graphics_Dreamcast.c index 861684967..061643559 100644 --- a/src/dreamcast/Graphics_Dreamcast.c +++ b/src/dreamcast/Graphics_Dreamcast.c @@ -994,12 +994,11 @@ static BitmapCol* DC_GetRow(struct Bitmap* bmp, int y, void* ctx) { } cc_result Gfx_TakeScreenshot(struct Stream* output) { - BitmapCol tmp[640]; + BitmapCol tmp[1024]; int width = vid_mode->width; int height = vid_mode->height; struct Bitmap bmp; - bmp.scan0 = tmp; bmp.width = width; bmp.height = height; diff --git a/src/gcwii/Graphics_GCWii.c b/src/gcwii/Graphics_GCWii.c index 8cd71c6cd..1c889ec19 100644 --- a/src/gcwii/Graphics_GCWii.c +++ b/src/gcwii/Graphics_GCWii.c @@ -6,6 +6,7 @@ #include #include #include +#include "gx_gpu.h" static void* fifo_buffer; #define FIFO_SIZE (256 * 1024) @@ -269,7 +270,8 @@ static BitmapCol* GCWii_GetRow(struct Bitmap* bmp, int y, void* ctx) { int blockXStride = (4 * 4) * 4; // 16 pixels per tile // Do the inverse of converting from 4x4 tiled to linear - for (u32 x = 0; x < bmp->width; x++) + int width = bmp->width; + for (u32 x = 0; x < width; x++) { int tileY = y >> 2, tileX = x >> 2; int locY = y & 0x3, locX = x & 0x3; @@ -551,7 +553,7 @@ void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { GX_LoadProjectionMtx(dst, tmp[3*4+3] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC); } else { - GX_LoadPosMtxImm(dst, GX_PNMTX0); + XF_SetMatrix_3x4((GX_matrix_3x4*)&dst, XF_POS_MATRIX0); } } @@ -564,12 +566,12 @@ void Gfx_LoadMVP(const struct Matrix* view, const struct Matrix* proj, struct Ma static float texOffsetX, texOffsetY; static void UpdateTexCoordGen(void) { if (texOffsetX || texOffsetY) { - Mtx mat = { 0 }; + GX_matrix_2x4 mat = { 0 }; // https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml - mat[0][0] = 1; mat[0][3] = texOffsetX; - mat[1][1] = 1; mat[1][3] = texOffsetY; + mat.m[0][0] = 1; mat.m[0][3] = texOffsetX; + mat.m[1][1] = 1; mat.m[1][3] = texOffsetY; - GX_LoadTexMtxImm(mat, GX_TEXMTX0, GX_MTX2x4); + XF_SetMatrix_2x4(&mat, XF_TEX_MATRIX0); GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0); } else { GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); @@ -635,8 +637,8 @@ static void Draw_ColouredTriangles(int verticesCount, int startVertex) { { struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; - GX_Position3f32(v->x, v->y, v->z); - GX_Color1u32(v->Col); + FIFO_PUSH_F32x3(v->x, v->y, v->z); + FIFO_PUSH_U32(v->Col); } } @@ -646,9 +648,9 @@ static void Draw_TexturedTriangles(int verticesCount, int startVertex) { { struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; - GX_Position3f32(v->x, v->y, v->z); - GX_Color1u32(v->Col); - GX_TexCoord2f32(v->U, v->V); + FIFO_PUSH_F32x3(v->x, v->y, v->z); + FIFO_PUSH_U32(v->Col); + FIFO_PUSH_F32x2(v->U, v->V); } } diff --git a/src/gcwii/gx_gpu.h b/src/gcwii/gx_gpu.h new file mode 100644 index 000000000..47cfb2641 --- /dev/null +++ b/src/gcwii/gx_gpu.h @@ -0,0 +1,132 @@ +// https://patents.google.com/patent/US6618048 +// https://patents.google.com/patent/US6639595B1 - general +// https://patents.google.com/patent/US6700586 - Transform Functions (XF) unit mostly +// https://patents.google.com/patent/US7002591 - general +// https://patents.google.com/patent/US6697074 - Command Processor (CP) unit + opcodes +// https://patents.google.com/patent/US7995069B2 - Blitter Processor (BP) unit +// https://patents.google.com/patent/US20070165043A1 - FIFO unit +// https://patents.google.com/patent/US7034828B1 - some texture functions +// https://patents.google.com/patent/US6664962B1 - some texture functions +// yet another gamecube documentation +// dolphin headers + +typedef struct { float m[4][4]; } GX_matrix_4x4; +typedef struct { float m[3][4]; } GX_matrix_3x4; +typedef struct { float m[2][4]; } GX_matrix_2x4; + +#define ENTRIES_2x4 8 +#define ENTRIES_3x4 12 +#define ENTRIES_4x4 16 + + +/*########################################################################################################################* +*----------------------------------------------------FIFO functionality---------------------------------------------------* +*#########################################################################################################################*/ +#define FIFO_PUSH_I32(value) wgPipe->I32 = value; +#define FIFO_PUSH_F32(value) wgPipe->F32 = value; +#define FIFO_PUSH_U32(value) wgPipe->U32 = value; + +#define FIFO_PUSH_U8(value) wgPipe->U8 = value; + +#define FIFO_PUSH_F32x2(x, y) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); +#define FIFO_PUSH_F32x3(x, y, z) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); FIFO_PUSH_F32(z); +#define FIFO_PUSH_F32x4(x, y, z, w) FIFO_PUSH_F32(x); FIFO_PUSH_F32(y); FIFO_PUSH_F32(z); FIFO_PUSH_F32(w); + +#define FIFO_PUSH_MTX_2x4(mtx) \ + FIFO_PUSH_F32x4(mtx->m[0][0], mtx->m[0][1], mtx->m[0][2], mtx->m[0][3]); \ + FIFO_PUSH_F32x4(mtx->m[1][0], mtx->m[1][1], mtx->m[1][2], mtx->m[1][3]); \ + +#define FIFO_PUSH_MTX_3x4(mtx) \ + FIFO_PUSH_F32x4(mtx->m[0][0], mtx->m[0][1], mtx->m[0][2], mtx->m[0][3]); \ + FIFO_PUSH_F32x4(mtx->m[1][0], mtx->m[1][1], mtx->m[1][2], mtx->m[1][3]); \ + FIFO_PUSH_F32x4(mtx->m[2][0], mtx->m[2][1], mtx->m[2][2], mtx->m[2][3]); \ + + +/*########################################################################################################################* +*------------------------------------------------Command processor commands-----------------------------------------------* +*#########################################################################################################################*/ +enum { + // No operation + CP_CMD_NOP = 0x00, + // Loads Command Processor register + CP_CMD_LOAD_CP_REG = 0x08, + // Loads Transform Unit register(s) + CP_CMD_LOAD_XF_REGS = 0x10, + // Runs all commands in a display list + CP_CMD_CALL_DISPLIST = 0x40, + // Loads Blitting Processor register + CP_CMD_LOAD_BP_REG = 0x61, + // Primitive command types + CP_CMD_PRIM_BASE = 0x80, + // TODO missing indexed + stat commands +}; + +#define GX_NOP() \ + FIFO_PUSH_U8(CP_CMD_NOP); + +#define GX_LOAD_XF_REGISTERS(start_reg, num_regs) \ + FIFO_PUSH_U8(CP_CMD_LOAD_XF_REGS); \ + FIFO_PUSH_U32( ((((num_regs) - 1) & 0xFFFF) << 16) | (start_reg) ); \ + + +/*########################################################################################################################* +*-----------------------------------------------Transform Function registers----------------------------------------------* +*#########################################################################################################################*/ +enum { + // https://www.gc-forever.com/yagcd/chap5.html#sec5.11.3 + // 256 floats -> 64 rows of 4xFloats -> ~21 entries of 3x4Matrices + XF_REG_BASE_MATRICES_BEG = 0x0000, + XF_REG_BASE_MATRICES_END = 0x0100, + #define XF_REG_BASE_MATRIX(idx) XF_REG_BASE_MATRICES_BEG + ((idx) * ENTRIES_3x4) +}; + +/*########################################################################################################################* +*-----------------------------------------------Transform Function commands-----------------------------------------------* +*#########################################################################################################################*/ +typedef enum { + XF_BASE_MATRIX00, XF_BASE_MATRIX01, XF_BASE_MATRIX02, + XF_BASE_MATRIX03, XF_BASE_MATRIX04, XF_BASE_MATRIX05, + XF_BASE_MATRIX06, XF_BASE_MATRIX07, XF_BASE_MATRIX08, + XF_BASE_MATRIX09, XF_BASE_MATRIX10, XF_BASE_MATRIX11, + XF_BASE_MATRIX12, XF_BASE_MATRIX13, XF_BASE_MATRIX14, + XF_BASE_MATRIX15, XF_BASE_MATRIX16, XF_BASE_MATRIX17, + XF_BASE_MATRIX18, XF_BASE_MATRIX19, XF_BASE_MATRIX20, + + // Default mapping, allocate first 10 matrices for positions + // (that way can use the same index as a corresponding normal matrix) + XF_POS_MATRIX0 = XF_BASE_MATRIX00, + XF_POS_MATRIX1 = XF_BASE_MATRIX01, + XF_POS_MATRIX2 = XF_BASE_MATRIX02, + XF_POS_MATRIX3 = XF_BASE_MATRIX03, + XF_POS_MATRIX4 = XF_BASE_MATRIX04, + XF_POS_MATRIX5 = XF_BASE_MATRIX05, + XF_POS_MATRIX6 = XF_BASE_MATRIX06, + XF_POS_MATRIX7 = XF_BASE_MATRIX07, + XF_POS_MATRIX8 = XF_BASE_MATRIX08, + XF_POS_MATRIX9 = XF_BASE_MATRIX09, + + // Default mapping, allocate rest of matrices for textures + // (avoids overlapping with position matrices) + XF_TEX_MATRIX0 = XF_BASE_MATRIX10, + XF_TEX_MATRIX1 = XF_BASE_MATRIX11, + XF_TEX_MATRIX2 = XF_BASE_MATRIX12, + XF_TEX_MATRIX3 = XF_BASE_MATRIX13, + XF_TEX_MATRIX4 = XF_BASE_MATRIX14, + XF_TEX_MATRIX5 = XF_BASE_MATRIX15, + XF_TEX_MATRIX6 = XF_BASE_MATRIX16, + XF_TEX_MATRIX7 = XF_BASE_MATRIX17, + XF_TEX_MATRIX8 = XF_BASE_MATRIX18, + XF_TEX_MATRIX9 = XF_BASE_MATRIX19, +} XF_BASE_MATRIX_INDEX; + +static CC_INLINE void XF_SetMatrix_3x4(const GX_matrix_3x4* matrix, XF_BASE_MATRIX_INDEX index) +{ + GX_LOAD_XF_REGISTERS(XF_REG_BASE_MATRIX(index), ENTRIES_3x4); + FIFO_PUSH_MTX_3x4(matrix); +} + +static CC_INLINE void XF_SetMatrix_2x4(const GX_matrix_2x4* matrix, XF_BASE_MATRIX_INDEX index) +{ + GX_LOAD_XF_REGISTERS(XF_REG_BASE_MATRIX(index), ENTRIES_2x4); + FIFO_PUSH_MTX_2x4(matrix); +} From c1fee0c1612ab60b8b17afd4f586c90e218e0a6c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 23 Sep 2025 07:05:15 +1000 Subject: [PATCH 113/115] PSP: Save 70kb --- src/3ds/Platform_3DS.c | 2 ++ src/Platform_N64.c | 2 ++ src/_PlatformConsole.h | 2 -- src/dreamcast/Platform_Dreamcast.c | 2 ++ src/gcwii/Platform_GCWii.c | 2 ++ src/nds/Platform_NDS.c | 2 ++ src/ps1/Platform_PS1.c | 2 ++ src/ps2/Platform_PS2.c | 2 ++ src/ps3/Platform_PS3.c | 2 ++ src/ps4/Platform_PS4.c | 2 ++ src/psp/Platform_PSP.c | 5 +++++ src/psvita/Platform_PSVita.c | 2 ++ src/saturn/Platform_Saturn.c | 2 ++ src/switch/Platform_Switch.c | 2 ++ src/wiiu/Platform_WiiU.c | 2 ++ src/xbox/Platform_Xbox.c | 2 ++ src/xbox360/Platform_Xbox360.c | 2 ++ 17 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/3ds/Platform_3DS.c b/src/3ds/Platform_3DS.c index 43c801100..61977e0f5 100644 --- a/src/3ds/Platform_3DS.c +++ b/src/3ds/Platform_3DS.c @@ -455,6 +455,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/Platform_N64.c b/src/Platform_N64.c index 284b8baa9..8457b2b3e 100644 --- a/src/Platform_N64.c +++ b/src/Platform_N64.c @@ -257,6 +257,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/_PlatformConsole.h b/src/_PlatformConsole.h index 4bd178e6f..c8930a32e 100644 --- a/src/_PlatformConsole.h +++ b/src/_PlatformConsole.h @@ -80,5 +80,3 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { return 0; } -void Process_Exit(cc_result code) { exit(code); } - diff --git a/src/dreamcast/Platform_Dreamcast.c b/src/dreamcast/Platform_Dreamcast.c index bddd9f873..fe03ddebe 100644 --- a/src/dreamcast/Platform_Dreamcast.c +++ b/src/dreamcast/Platform_Dreamcast.c @@ -754,6 +754,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/gcwii/Platform_GCWii.c b/src/gcwii/Platform_GCWii.c index 807733b6e..291aab862 100644 --- a/src/gcwii/Platform_GCWii.c +++ b/src/gcwii/Platform_GCWii.c @@ -630,6 +630,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/nds/Platform_NDS.c b/src/nds/Platform_NDS.c index dd47bf40f..49e9ad220 100644 --- a/src/nds/Platform_NDS.c +++ b/src/nds/Platform_NDS.c @@ -642,6 +642,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/ps1/Platform_PS1.c b/src/ps1/Platform_PS1.c index 0ca7d3486..4cb69485e 100644 --- a/src/ps1/Platform_PS1.c +++ b/src/ps1/Platform_PS1.c @@ -197,6 +197,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/ps2/Platform_PS2.c b/src/ps2/Platform_PS2.c index 5edd24b9c..14b0e0df3 100644 --- a/src/ps2/Platform_PS2.c +++ b/src/ps2/Platform_PS2.c @@ -753,6 +753,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/ps3/Platform_PS3.c b/src/ps3/Platform_PS3.c index b038ad38e..f3043337d 100644 --- a/src/ps3/Platform_PS3.c +++ b/src/ps3/Platform_PS3.c @@ -491,6 +491,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/ps4/Platform_PS4.c b/src/ps4/Platform_PS4.c index e34734db9..c7f1677a9 100644 --- a/src/ps4/Platform_PS4.c +++ b/src/ps4/Platform_PS4.c @@ -533,6 +533,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + void Platform_Init(void) { Platform_LogConst("initing 2.."); } diff --git a/src/psp/Platform_PSP.c b/src/psp/Platform_PSP.c index d16133fd9..8406139f9 100644 --- a/src/psp/Platform_PSP.c +++ b/src/psp/Platform_PSP.c @@ -39,6 +39,9 @@ PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); PSP_DISABLE_AUTOSTART_PTHREAD() // reduces .elf size by 140 kb +// Save 70kb by not linking in sprintf/setenv code etc +void __timezone_update() { } + /*########################################################################################################################* *------------------------------------------------------Logging/Time-------------------------------------------------------* @@ -488,6 +491,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/psvita/Platform_PSVita.c b/src/psvita/Platform_PSVita.c index da0390719..caa4023f9 100644 --- a/src/psvita/Platform_PSVita.c +++ b/src/psvita/Platform_PSVita.c @@ -444,6 +444,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 6edbb4f7a..bdc901afb 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -231,6 +231,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/switch/Platform_Switch.c b/src/switch/Platform_Switch.c index f67e918b2..364bf2a1c 100644 --- a/src/switch/Platform_Switch.c +++ b/src/switch/Platform_Switch.c @@ -535,6 +535,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/wiiu/Platform_WiiU.c b/src/wiiu/Platform_WiiU.c index 7bc0b438c..3a280c5f8 100644 --- a/src/wiiu/Platform_WiiU.c +++ b/src/wiiu/Platform_WiiU.c @@ -470,6 +470,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/xbox/Platform_Xbox.c b/src/xbox/Platform_Xbox.c index d61358b83..ce6a1a933 100644 --- a/src/xbox/Platform_Xbox.c +++ b/src/xbox/Platform_Xbox.c @@ -464,6 +464,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* diff --git a/src/xbox360/Platform_Xbox360.c b/src/xbox360/Platform_Xbox360.c index d67c9654f..34626b334 100644 --- a/src/xbox360/Platform_Xbox360.c +++ b/src/xbox360/Platform_Xbox360.c @@ -340,6 +340,8 @@ cc_result Process_StartOpen(const cc_string* args) { return ERR_NOT_SUPPORTED; } +void Process_Exit(cc_result code) { exit(code); } + /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* From 61beafa967eb563c195ccf29d0f85c7268a3b241 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 23 Sep 2025 20:13:57 +1000 Subject: [PATCH 114/115] Avoid storing two texture IDs in entity struct --- src/Entity.c | 6 +++--- src/Entity.h | 3 ++- src/HeldBlockRenderer.c | 2 +- src/Model.c | 38 ++++++++++++++++++++------------------ src/psp/Platform_PSP.c | 6 +++--- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/Entity.c b/src/Entity.c index 13004e8cd..8a046cd65 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -229,13 +229,13 @@ static void Entity_CopySkin(struct Entity* dst, struct Entity* src) { dst->SkinType = src->SkinType; dst->uScale = src->uScale; dst->vScale = src->vScale; - dst->MobTextureId = src->MobTextureId; + dst->NonHumanSkin = src->NonHumanSkin; } /* Resets skin data for the given entity */ static void Entity_ResetSkin(struct Entity* e) { e->uScale = 1.0f; e->vScale = 1.0f; - e->MobTextureId = 0; + e->NonHumanSkin = false; e->TextureId = 0; e->SkinType = SKIN_64x32; } @@ -247,7 +247,7 @@ static void Entity_SetSkinAll(struct Entity* source, cc_bool reset) { int i; skin = String_FromRawArray(source->SkinRaw); - source->MobTextureId = Utils_IsUrlPrefix(&skin) ? source->TextureId : 0; + source->NonHumanSkin = Utils_IsUrlPrefix(&skin); for (i = 0; i < ENTITIES_MAX_COUNT; i++) { if (!Entities.List[i]) continue; diff --git a/src/Entity.h b/src/Entity.h index 9248b924d..2542be3ed 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -122,7 +122,8 @@ struct Entity { cc_uint8 SkinType; cc_uint8 SkinFetchState; cc_bool NoShade, OnGround; - GfxResourceID TextureId, MobTextureId; + GfxResourceID TextureId; + cc_bool NonHumanSkin; /* Whether custom skin is also used on non humanoid models */ float uScale, vScale; struct AnimatedComp Anim; diff --git a/src/HeldBlockRenderer.c b/src/HeldBlockRenderer.c index 4b5dcdf70..2f433340c 100644 --- a/src/HeldBlockRenderer.c +++ b/src/HeldBlockRenderer.c @@ -88,7 +88,7 @@ static void ResetHeldState(void) { held_entity.SkinType = p->SkinType; held_entity.TextureId = p->TextureId; - held_entity.MobTextureId = p->MobTextureId; + held_entity.NonHumanSkin = p->NonHumanSkin; held_entity.uScale = p->uScale; held_entity.vScale = p->vScale; } diff --git a/src/Model.c b/src/Model.c index 34f195ae4..33d480380 100644 --- a/src/Model.c +++ b/src/Model.c @@ -114,12 +114,12 @@ void Model_Render(struct Model* model, struct Entity* e) { } void Model_SetupState(struct Model* model, struct Entity* e) { - PackedCol col; + PackedCol color; float yawDelta; model->index = 0; - col = e->VTABLE->GetCol(e); - Models.Cols[0] = col; + color = e->VTABLE->GetCol(e); + Models.Cols[0] = color; /* If a model forgets to call Model_ApplyTexture but still tries to draw, */ /* then it is not using the model API properly. */ @@ -129,11 +129,13 @@ void Model_SetupState(struct Model* model, struct Entity* e) { Models.vScale = 100.0f; if (!e->NoShade) { - Models.Cols[1] = PackedCol_Scale(col, PACKEDCOL_SHADE_YMIN); - Models.Cols[2] = PackedCol_Scale(col, PACKEDCOL_SHADE_Z); - Models.Cols[4] = PackedCol_Scale(col, PACKEDCOL_SHADE_X); + Models.Cols[1] = PackedCol_Scale(color, PACKEDCOL_SHADE_YMIN); + Models.Cols[2] = PackedCol_Scale(color, PACKEDCOL_SHADE_Z); + Models.Cols[4] = PackedCol_Scale(color, PACKEDCOL_SHADE_X); } else { - Models.Cols[1] = col; Models.Cols[2] = col; Models.Cols[4] = col; + Models.Cols[1] = color; + Models.Cols[2] = color; + Models.Cols[4] = color; } Models.Cols[3] = Models.Cols[2]; @@ -151,7 +153,7 @@ void Model_ApplyTexture(struct Entity* e) { GfxResourceID tex; cc_bool _64x64; - tex = model->usesHumanSkin ? e->TextureId : e->MobTextureId; + tex = (model->usesHumanSkin || e->NonHumanSkin) ? e->TextureId : 0; if (tex) { Models.skinType = e->SkinType; } else { @@ -1449,7 +1451,7 @@ static void ChickenModel_MakeParts(void) { } static void ChickenModel_Draw(struct Entity* e) { - PackedCol col = Models.Cols[0]; + PackedCol color = Models.Cols[0]; int i; Model_ApplyTexture(e); Model_LockVB(e, CHICKEN_MAX_VERTICES); @@ -1464,7 +1466,7 @@ static void ChickenModel_Draw(struct Entity* e) { for (i = 0; i < FACE_COUNT; i++) { - Models.Cols[i] = PackedCol_Scale(col, 0.7f); + Models.Cols[i] = PackedCol_Scale(color, 0.7f); } Model_DrawRotate(e->Anim.LeftLegX, 0, 0, &chicken_leftLeg, false); @@ -2091,13 +2093,13 @@ static TextureLoc BlockModel_GetTex(Face face) { static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { struct VertexTextured* ptr, v; - PackedCol col; int tmp; + PackedCol color; int tmp; float xz1, xz2; TextureLoc loc = BlockModel_GetTex(FACE_ZMAX); TextureRec rec = Atlas1D_TexRec(loc, 1, &tmp); - col = Models.Cols[0]; - Block_Tint(col, bModel_block); + color = Models.Cols[0]; + Block_Tint(color, bModel_block); xz1 = 0.0f; xz2 = 0.0f; if (firstPart) { /* Need to break into two quads for when drawing a sprite model in hand. */ @@ -2109,7 +2111,7 @@ static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { } ptr = bModel_vertices; - v.Col = col; + v.Col = color; v.x = xz1; v.y = 0.0f; v.z = xz1; v.U = rec.u2; v.V = rec.v2; *ptr++ = v; v.y = 1.0f; v.V = rec.v1; *ptr++ = v; @@ -2121,13 +2123,13 @@ static void BlockModel_SpriteZQuad(cc_bool firstPart, cc_bool mirror) { static void BlockModel_SpriteXQuad(cc_bool firstPart, cc_bool mirror) { struct VertexTextured* ptr, v; - PackedCol col; int tmp; + PackedCol color; int tmp; float x1, x2, z1, z2; TextureLoc loc = BlockModel_GetTex(FACE_XMAX); TextureRec rec = Atlas1D_TexRec(loc, 1, &tmp); - col = Models.Cols[0]; - Block_Tint(col, bModel_block); + color = Models.Cols[0]; + Block_Tint(color, bModel_block); x1 = 0.0f; x2 = 0.0f; z1 = 0.0f; z2 = 0.0f; if (firstPart) { @@ -2139,7 +2141,7 @@ static void BlockModel_SpriteXQuad(cc_bool firstPart, cc_bool mirror) { } ptr = bModel_vertices; - v.Col = col; + v.Col = color; v.x = x1; v.y = 0.0f; v.z = z1; v.U = rec.u2; v.V = rec.v2; *ptr++ = v; v.y = 1.0f; v.V = rec.v1; *ptr++ = v; diff --git a/src/psp/Platform_PSP.c b/src/psp/Platform_PSP.c index 8406139f9..d66c390ae 100644 --- a/src/psp/Platform_PSP.c +++ b/src/psp/Platform_PSP.c @@ -37,10 +37,10 @@ cc_bool Platform_ReadonlyFilesystem; PSP_MODULE_INFO("ClassiCube", PSP_MODULE_USER, 1, 0); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); -PSP_DISABLE_AUTOSTART_PTHREAD() // reduces .elf size by 140 kb - +// Save 140 kb by not linking in pthreads +PSP_DISABLE_AUTOSTART_PTHREAD() // Save 70kb by not linking in sprintf/setenv code etc -void __timezone_update() { } +PSP_DISABLE_NEWLIB_TIMEZONE_SUPPORT() /*########################################################################################################################* From e39c5d55d398f066bf2eedef65aebe1ea4ea0502 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 23 Sep 2025 22:28:05 +1000 Subject: [PATCH 115/115] Cancel queued skin download if no more entities are using the skin Also transfer skin download responbitilites if entity downloading a skin stops using that skin, but there is at least one other entity using that skin --- src/Entity.c | 168 +++++++++++++++++++++++++++++++++------------------ src/Entity.h | 12 ++-- 2 files changed, 116 insertions(+), 64 deletions(-) diff --git a/src/Entity.c b/src/Entity.c index 8a046cd65..8a7a42903 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -207,49 +207,63 @@ cc_bool Entity_TouchesAnyWater(struct Entity* e) { /*########################################################################################################################* *------------------------------------------------------Entity skins-------------------------------------------------------* *#########################################################################################################################*/ -static struct Entity* Entity_FirstOtherWithSameSkinAndFetchedSkin(struct Entity* except) { - struct Entity* e; - cc_string skin, eSkin; - int i; - - skin = String_FromRawArray(except->SkinRaw); - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i] || Entities.List[i] == except) continue; - - e = Entities.List[i]; - eSkin = String_FromRawArray(e->SkinRaw); - if (e->SkinFetchState && String_Equals(&skin, &eSkin)) return e; - } - return NULL; -} - /* Copies skin data from another entity */ static void Entity_CopySkin(struct Entity* dst, struct Entity* src) { - dst->TextureId = src->TextureId; - dst->SkinType = src->SkinType; - dst->uScale = src->uScale; - dst->vScale = src->vScale; - dst->NonHumanSkin = src->NonHumanSkin; + dst->TextureId = src->TextureId; + dst->SkinType = src->SkinType; + dst->uScale = src->uScale; + dst->vScale = src->vScale; } /* Resets skin data for the given entity */ static void Entity_ResetSkin(struct Entity* e) { - e->uScale = 1.0f; e->vScale = 1.0f; - e->NonHumanSkin = false; e->TextureId = 0; - e->SkinType = SKIN_64x32; + e->uScale = 1.0f; + e->vScale = 1.0f; +} + +static void CheckSkin_Unchecked(struct Entity* e) { + cc_string skin, eSkin; + struct Entity* other; + cc_uint8 flags; + cc_result res; + int i; + + skin = String_FromRawArray(e->SkinRaw); + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + other = Entities.List[i]; + if (!other) continue; + /* Don't bother checking for other == e, as e->state is UNCHECKED anyways */ + if (other->SkinFetchState < SKIN_FETCH_DOWNLOADING) continue; + + eSkin = String_FromRawArray(other->SkinRaw); + if (!String_Equals(&skin, &eSkin)) continue; + + /* Another entity with same skin either finished or is downloading */ + if (other->SkinFetchState == SKIN_FETCH_COMPLETED) { + Entity_CopySkin(e, other); + e->SkinFetchState = SKIN_FETCH_COMPLETED; + } else { + e->SkinFetchState = SKIN_FETCH_WAITINGFOR; + } + return; + } + + flags = e == &LocalPlayer_Instances[0].Base ? HTTP_FLAG_NOCACHE : 0; + e->_skinReqID = Http_AsyncGetSkin(&skin, flags); + e->SkinFetchState = SKIN_FETCH_DOWNLOADING; } /* Copies or resets skin data for all entity with same skin */ static void Entity_SetSkinAll(struct Entity* source, cc_bool reset) { struct Entity* e; cc_string skin, eSkin; + skin = String_FromRawArray(source->SkinRaw); int i; - skin = String_FromRawArray(source->SkinRaw); - source->NonHumanSkin = Utils_IsUrlPrefix(&skin); - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { if (!Entities.List[i]) continue; e = Entities.List[i]; @@ -327,7 +341,6 @@ static cc_result ApplySkin(struct Entity* e, struct Bitmap* bmp, struct Stream* if ((res = Png_Decode(bmp, src))) return res; Gfx_DeleteTexture(&e->TextureId); - Entity_SetSkinAll(e, true); if ((res = EnsurePow2Skin(e, bmp))) return res; e->SkinType = Utils_CalcSkinType(bmp); @@ -356,49 +369,81 @@ static void LogInvalidSkin(cc_result res, const cc_string* skin, const cc_uint8* Logger_WarnFunc(&msg); } -static void Entity_CheckSkin(struct Entity* e) { - struct Entity* first; +static void CheckSkin_Downloading(struct Entity* e) { struct HttpRequest item; struct Stream mem; struct Bitmap bmp; cc_string skin; - cc_uint8 flags; cc_result res; - /* Don't check skin if don't have to */ - if (!e->Model->usesSkin) return; - if (e->SkinFetchState == SKIN_FETCH_COMPLETED) return; + if (!Http_GetResult(e->_skinReqID, &item)) return; + Entity_SetSkinAll(e, true); + if (!item.success) return; + + Stream_ReadonlyMemory(&mem, item.data, item.size); skin = String_FromRawArray(e->SkinRaw); - if (!e->SkinFetchState) { - first = Entity_FirstOtherWithSameSkinAndFetchedSkin(e); - flags = e == &LocalPlayer_Instances[0].Base ? HTTP_FLAG_NOCACHE : 0; - - if (!first) { - e->_skinReqID = Http_AsyncGetSkin(&skin, flags); - e->SkinFetchState = SKIN_FETCH_DOWNLOADING; - } else { - Entity_CopySkin(e, first); - e->SkinFetchState = SKIN_FETCH_COMPLETED; - return; - } + if ((res = ApplySkin(e, &bmp, &mem, &skin))) { + LogInvalidSkin(res, &skin, item.data, item.size); } - if (!Http_GetResult(e->_skinReqID, &item)) return; - - if (!item.success) { - Entity_SetSkinAll(e, true); - } else { - Stream_ReadonlyMemory(&mem, item.data, item.size); - - if ((res = ApplySkin(e, &bmp, &mem, &skin))) { - LogInvalidSkin(res, &skin, item.data, item.size); - } - Mem_Free(bmp.scan0); - } + Mem_Free(bmp.scan0); HttpRequest_Free(&item); } +static void Entity_CheckSkin(struct Entity* e) { + /* Don't check skin if don't have to */ + if (!e->Model->usesSkin) return; + + switch (e->SkinFetchState) + { + case SKIN_FETCH_UNCHECKED: + CheckSkin_Unchecked(e); return; + case SKIN_FETCH_WAITINGFOR: + return; /* Waiting for another entity to download it */ + case SKIN_FETCH_DOWNLOADING: + CheckSkin_Downloading(e); return; + case SKIN_FETCH_COMPLETED: + return; /* Nothing to do as skin has been downloaded */ + } +} + +/* Returns whether this entity is currently waiting on given skin to download */ +static CC_INLINE cc_bool IsWaitingForSkinToDownload(struct Entity* e, cc_string* skin) { + cc_string eSkin; + if (e->SkinFetchState != SKIN_FETCH_WAITINGFOR) return false; + + eSkin = String_FromRawArray(e->SkinRaw); + return String_Equals(skin, &eSkin); +} + +/* Transfers skin downloading responsibility to another entity */ +static void TransferSkinDownload(struct Entity* e, struct Entity* src) { + e->SkinFetchState = SKIN_FETCH_DOWNLOADING; + e->_skinReqID = src->_skinReqID; +} + +/* Either transfers skin download or cancels it altogether */ +static void DerefDownloadingSkin(struct Entity* src) { + struct Entity* e; + cc_string skin = String_FromRawArray(src->SkinRaw); + int i; + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + e = Entities.List[i]; + + if (!IsWaitingForSkinToDownload(e, &skin)) continue; + Platform_Log1("Transferring skin download: %s", &skin); + TransferSkinDownload(e, src); + return; + } + + Platform_Log1("Cancelling skin download: %s", &skin); + Http_TryCancel(src->_skinReqID); +} + /* Returns true if no other entities are sharing this skin texture */ static cc_bool CanDeleteTexture(struct Entity* except) { int i; @@ -414,9 +459,10 @@ static cc_bool CanDeleteTexture(struct Entity* except) { CC_NOINLINE static void DeleteSkin(struct Entity* e) { if (CanDeleteTexture(e)) Gfx_DeleteTexture(&e->TextureId); + if (e->SkinFetchState == SKIN_FETCH_DOWNLOADING) DerefDownloadingSkin(e); Entity_ResetSkin(e); - e->SkinFetchState = 0; + e->SkinFetchState = SKIN_FETCH_UNCHECKED; } void Entity_SetSkin(struct Entity* e, const cc_string* skin) { @@ -425,9 +471,11 @@ void Entity_SetSkin(struct Entity* e, const cc_string* skin) { if (Utils_IsUrlPrefix(skin)) { tmp = *skin; + e->NonHumanSkin = true; } else { String_InitArray(tmp, tmpBuffer); String_AppendColorless(&tmp, skin); + e->NonHumanSkin = false; } String_CopyToRawArray(e->SkinRaw, &tmp); } diff --git a/src/Entity.h b/src/Entity.h index 2542be3ed..3c719475d 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -85,10 +85,14 @@ struct EntityVTABLE { cc_bool (*ShouldRenderName)(struct Entity* e); }; -/* Skin is still being downloaded asynchronously */ -#define SKIN_FETCH_DOWNLOADING 1 -/* Skin was downloaded or copied from another entity with the same skin. */ -#define SKIN_FETCH_COMPLETED 2 +/* Entity's skin has not been checked yet */ +#define SKIN_FETCH_UNCHECKED 0 +/* Waiting for another entity with the same skin to finish downloading it */ +#define SKIN_FETCH_WAITINGFOR 1 +/* Entity's skin is currently being downloaded asynchronously */ +#define SKIN_FETCH_DOWNLOADING 2 +/* Entity's skin has been downloaded or copied from another entity with the same skin. */ +#define SKIN_FETCH_COMPLETED 3 /* true to restrict model scale (needed for local player, giant model collisions are too costly) */ #define ENTITY_FLAG_MODEL_RESTRICTED_SCALE 0x01