From 7aba6260a9c08a5004026a55026bae0862b901b4 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 8 Oct 2023 14:47:56 +1100 Subject: [PATCH] sync with master again --- .github/workflows/build_ps3.yml | 1 + misc/dreamcast/Makefile | 2 +- misc/vita/colored_alpha_f.cg | 6 +- misc/vita/colored_f.cg | 6 +- misc/vita/textured_alpha_f.cg | 8 +- misc/vita/textured_f.cg | 8 +- misc/xbox/Makefile | 3 +- misc/xbox360/Makefile | 117 ++++++++ src/Animations.c | 4 +- src/Audio.c | 6 +- src/Bitmap.c | 7 +- src/Chat.c | 2 - src/Core.h | 10 +- src/EntityComponents.c | 2 +- src/ExtMath.c | 469 ++++++++++++++++++++++++++++++-- src/ExtMath.h | 13 +- src/Graphics_Dreamcast.c | 4 +- src/Graphics_PS3.c | 5 +- src/Graphics_Xbox.c | 6 +- src/PackedCol.h | 2 +- src/Particle.c | 2 +- src/Program.c | 2 +- src/Protocol.c | 3 +- src/SSL.c | 83 ++++-- src/SystemFonts.c | 265 +++++++++++++++--- src/TexturePack.c | 2 +- src/Vorbis.c | 2 +- src/_GraphicsBase.h | 2 +- 28 files changed, 898 insertions(+), 144 deletions(-) create mode 100644 misc/xbox360/Makefile diff --git a/.github/workflows/build_ps3.yml b/.github/workflows/build_ps3.yml index 67ffbf2..9cd2809 100644 --- a/.github/workflows/build_ps3.yml +++ b/.github/workflows/build_ps3.yml @@ -17,6 +17,7 @@ jobs: id: compile run: | pacman -S make --noconfirm + export PSL1GHT=/usr/local/ps3dev export PS3DEV=/usr/local/ps3dev make ps3 diff --git a/misc/dreamcast/Makefile b/misc/dreamcast/Makefile index 4536a77..9dbd60f 100644 --- a/misc/dreamcast/Makefile +++ b/misc/dreamcast/Makefile @@ -1,5 +1,5 @@ BUILD_DIR := build-dreamcast -SOURCE_DIRS := src +SOURCE_DIRS := src third_party/bearssl/src C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o))) diff --git a/misc/vita/colored_alpha_f.cg b/misc/vita/colored_alpha_f.cg index 928d710..5e6c57f 100644 --- a/misc/vita/colored_alpha_f.cg +++ b/misc/vita/colored_alpha_f.cg @@ -1,5 +1,7 @@ -float4 main( - float4 out_color: COLOR) : COLOR +float4 main +( + float4 out_color: COLOR +) : COLOR { if (out_color.a < 0.5) discard; diff --git a/misc/vita/colored_f.cg b/misc/vita/colored_f.cg index 7d23a71..3ea0623 100644 --- a/misc/vita/colored_f.cg +++ b/misc/vita/colored_f.cg @@ -1,5 +1,7 @@ -float4 main( - float4 out_color: COLOR) : COLOR +float4 main +( + float4 out_color : COLOR +) : COLOR { return out_color; } \ No newline at end of file diff --git a/misc/vita/textured_alpha_f.cg b/misc/vita/textured_alpha_f.cg index 1945904..4bed442 100644 --- a/misc/vita/textured_alpha_f.cg +++ b/misc/vita/textured_alpha_f.cg @@ -1,7 +1,9 @@ -float4 main( +float4 main +( uniform sampler2D tex, - float4 out_color: COLOR, - float2 out_texcoord : TEXCOORD0) : COLOR + float4 out_color : COLOR, + float2 out_texcoord : TEXCOORD0 +) : COLOR { float4 color = tex2D(tex, out_texcoord) * out_color; diff --git a/misc/vita/textured_f.cg b/misc/vita/textured_f.cg index 0386696..a78df88 100644 --- a/misc/vita/textured_f.cg +++ b/misc/vita/textured_f.cg @@ -1,7 +1,9 @@ -float4 main( +float4 main +( uniform sampler2D tex, - float4 out_color: COLOR, - float2 out_texcoord : TEXCOORD0) : COLOR + float4 out_color : COLOR, + float2 out_texcoord : TEXCOORD0 +) : COLOR { return tex2D(tex, out_texcoord) * out_color; } \ No newline at end of file diff --git a/misc/xbox/Makefile b/misc/xbox/Makefile index 2c650c7..a68f6f6 100644 --- a/misc/xbox/Makefile +++ b/misc/xbox/Makefile @@ -4,9 +4,10 @@ endif XBE_TITLE = ClassiCube GEN_XISO = ClassiCube-xbox.iso -SRCS = $(wildcard src/*.c) +SRCS = $(wildcard src/*.c) $(wildcard third_party/bearssl/src/*.c) SHADER_OBJS = misc/xbox/vs_coloured.inl misc/xbox/vs_textured.inl misc/xbox/ps_coloured.inl misc/xbox/ps_textured.inl NXDK_NET = y +NXDK_CFLAGS = -Ithird_party/bearssl/inc NXDK_LDFLAGS = -stack:131072 include $(NXDK_DIR)/Makefile \ No newline at end of file diff --git a/misc/xbox360/Makefile b/misc/xbox360/Makefile new file mode 100644 index 0000000..57811dd --- /dev/null +++ b/misc/xbox360/Makefile @@ -0,0 +1,117 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: + +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITXENON)),) +$(error "Please set DEVKITXENON in your environment. export DEVKITXENON=devkitPPC") +endif + +#--------------------------------------------------------------------------------- +export LIBXENON_INC := $(DEVKITXENON)/usr/include +export LIBXENON_LIB := $(DEVKITXENON)/usr/lib +LDSCRIPT := $(DEVKITXENON)/app.lds + +MACHDEP = -DXENON -m32 -maltivec -fno-pic -mpowerpc64 -mhard-float -L$(DEVKITXENON)/xenon/lib/32 + +export AS := xenon-as +export CC := xenon-gcc +export CXX := xenon-g++ +export AR := xenon-ar + + +#--------------------------------------------------------------------------------- +# 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 +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := ClassiCube-xbox360 +BUILD := build +SOURCES := src + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS= $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,--gc-sections -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lxenon -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) + +export LD := $(CC) +export OFILES := $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := -I$(LIBXENON_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := -L$(LIBXENON_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).elf32: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +default: $(BUILD) $(OUTPUT).elf32 + cp $(OUTPUT).elf32 /tftpboot/xenon + xenon-strip /tftpboot/xenon + + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).elf32 + +#--------------------------------------------------------------------------------- +%.o: %.c + @$(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.s + @$(CC) -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ + +%.o: %.S + @$(CC) -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ + +%.elf: + @echo linking ... $(notdir $@) + @$(LD) $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -n -T $(LDSCRIPT) -o $@ + +%.elf32: %.elf + @echo converting and stripping ... $(notdir $@) + @xenon-objcopy -O elf32-powerpc --adjust-vma 0x80000000 $< $@ + @xenon-strip $@ diff --git a/src/Animations.c b/src/Animations.c index 10d9b82..9c469dd 100644 --- a/src/Animations.c +++ b/src/Animations.c @@ -41,7 +41,7 @@ static void LavaAnimation_Tick(void) { size = min(Atlas2D.TileSize, LIQUID_ANIM_MAX); mask = size - 1; - shift = Math_Log2(size); + shift = Math_ilog2(size); if (!L_rndInited) { Random_SeedFromCurrentTime(&L_rnd); @@ -122,7 +122,7 @@ static void WaterAnimation_Tick(void) { size = min(Atlas2D.TileSize, LIQUID_ANIM_MAX); mask = size - 1; - shift = Math_Log2(size); + shift = Math_ilog2(size); if (!W_rndInited) { Random_SeedFromCurrentTime(&W_rnd); diff --git a/src/Audio.c b/src/Audio.c index b495730..4316802 100644 --- a/src/Audio.c +++ b/src/Audio.c @@ -1142,8 +1142,8 @@ static void Sounds_Play(cc_uint8 type, struct Soundboard* board) { data.rate = 100; data.volume = Audio_SoundsVolume; - /* https://minecraft.fandom.com/wiki/Block_of_Gold#Sounds */ - /* https://minecraft.fandom.com/wiki/Grass#Sounds */ + /* https://minecraft.wiki/w/Block_of_Gold#Sounds */ + /* https://minecraft.wiki/w/Grass#Sounds */ if (board == &digBoard) { if (type == SOUND_METAL) data.rate = 120; else data.rate = 80; @@ -1523,4 +1523,4 @@ static void OnFree(void) { struct IGameComponent Audio_Component = { OnInit, /* Init */ OnFree /* Free */ -}; \ No newline at end of file +}; diff --git a/src/Bitmap.c b/src/Bitmap.c index ec8797a..6e8dbe0 100644 --- a/src/Bitmap.c +++ b/src/Bitmap.c @@ -337,7 +337,7 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { cc_result res; /* header variables */ - static cc_uint32 samplesPerPixel[7] = { 1, 0, 3, 1, 2, 0, 4 }; + static const cc_uint32 samplesPerPixel[7] = { 1, 0, 3, 1, 2, 0, 4 }; cc_uint8 col, bitsPerSample, bytesPerPixel; Png_RowExpander rowExpander; cc_uint32 scanlineSize, scanlineBytes; @@ -395,7 +395,7 @@ cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream) { bitsPerSample = tmp[8]; col = tmp[9]; rowExpander = Png_GetExpander(col, bitsPerSample); - if (rowExpander == NULL) return PNG_ERR_INVALID_COL_BPP; + if (!rowExpander) return PNG_ERR_INVALID_COL_BPP; if (tmp[10] != 0) return PNG_ERR_COMP_METHOD; if (tmp[11] != 0) return PNG_ERR_FILTER; @@ -605,7 +605,8 @@ static void Png_MakeRow(const BitmapCol* src, cc_uint8* dst, int lineLen, cc_boo static void Png_EncodeRow(const cc_uint8* cur, const cc_uint8* prior, cc_uint8* best, int lineLen, cc_bool alpha) { cc_uint8* dst; - int bestFilter, bestEstimate = Int32_MaxValue; + int bestFilter = PNG_FILTER_SUB; + int bestEstimate = Int32_MaxValue; int x, filter, estimate; dst = best + 1; diff --git a/src/Chat.c b/src/Chat.c index 2e42621..df092e7 100644 --- a/src/Chat.c +++ b/src/Chat.c @@ -650,8 +650,6 @@ static struct ChatCommand TeleportCommand = { *------------------------------------------------------BlockEditCommand----------------------------------------------------* *#########################################################################################################################*/ static cc_bool BlockEditCommand_GetInt(const cc_string* str, const char* name, int* value, int min, int max) { - int maxTexs = ATLAS1D_MAX_ATLASES; - if (!Convert_ParseInt(str, value)) { Chat_Add1("&eBlockEdit: &e%c must be an integer", name); return false; diff --git a/src/Core.h b/src/Core.h index a89c559..0ceb504 100644 --- a/src/Core.h +++ b/src/Core.h @@ -128,6 +128,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOSOUNDS #define CC_BUILD_LOWMEM #define CC_BUILD_HTTPCLIENT + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #elif defined XENON /* libxenon also defines __linux__ (yes, really) */ @@ -266,29 +267,29 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_HTTPCLIENT #define CC_BUILD_OPENAL #define CC_BUILD_PSP - #define CC_BUILD_BEARSSL #define CC_BUILD_LOWMEM + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #elif defined __3DS__ #define CC_BUILD_HTTPCLIENT #define CC_BUILD_OPENAL #define CC_BUILD_3DS - #define CC_BUILD_BEARSSL #define CC_BUILD_LOWMEM + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #elif defined GEKKO #define CC_BUILD_HTTPCLIENT #define CC_BUILD_OPENAL #define CC_BUILD_GCWII - #define CC_BUILD_BEARSSL #define CC_BUILD_LOWMEM + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #elif defined __vita__ #define CC_BUILD_HTTPCLIENT #define CC_BUILD_OPENAL #define CC_BUILD_PSVITA - #define CC_BUILD_BEARSSL #define CC_BUILD_LOWMEM + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #elif defined _arch_dreamcast #define CC_BUILD_HTTPCLIENT @@ -301,6 +302,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_OPENAL #define CC_BUILD_PS3 #define CC_BUILD_LOWMEM + #define CC_BUILD_BEARSSL #undef CC_BUILD_FREETYPE #endif #endif diff --git a/src/EntityComponents.c b/src/EntityComponents.c index 9dbe988..81763da 100644 --- a/src/EntityComponents.c +++ b/src/EntityComponents.c @@ -1222,7 +1222,7 @@ static double PhysicsComp_YPosAt(int t, float u) { /* x(t, u) = Σv(t, u) from 0 to t (since we work in discrete timesteps) */ /* plugging into Wolfram Alpha gives 1 equation as */ /* (0.98^t) * (-49u - 196) - 4t + 50u + 196 */ - double a = Math_Exp(-0.0202027 * t); /* ~0.98^t */ + double a = Math_Exp2(-0.02914633510256746 * t); /* ~0.98^t */ return a * (-49 * u - 196) - 4 * t + 50 * u + 196; } diff --git a/src/ExtMath.c b/src/ExtMath.c index f4e94a5..7fdd028 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -1,13 +1,11 @@ #include "ExtMath.h" #include "Platform.h" #include "Utils.h" -#include /* For abs(x) function */ #include -/* TODO: Replace with own functions that don't rely on */ - #ifndef __GNUC__ +#include float Math_AbsF(float x) { return fabsf(x); /* MSVC intrinsic */ } float Math_SqrtF(float x) { return sqrtf(x); /* MSVC intrinsic */ } #endif @@ -15,12 +13,8 @@ float Math_SqrtF(float x) { return sqrtf(x); /* MSVC intrinsic */ } float Math_Mod1(float x) { return x - (int)x; /* fmodf(x, 1); */ } int Math_AbsI(int x) { return abs(x); /* MSVC intrinsic */ } -double Math_Sin(double x) { return sin(x); } -double Math_Cos(double x) { return cos(x); } - float Math_SinF(float x) { return (float)Math_Sin(x); } float Math_CosF(float x) { return (float)Math_Cos(x); } -double Math_Atan2(double x, double y) { return atan2(y, x); } int Math_Floor(float value) { int valueI = (int)value; @@ -32,7 +26,7 @@ int Math_Ceil(float value) { return valueI < value ? valueI + 1 : valueI; } -int Math_Log2(cc_uint32 value) { +int Math_ilog2(cc_uint32 value) { cc_uint32 r = 0; while (value >>= 1) r++; return r; @@ -80,25 +74,6 @@ cc_bool Math_IsPowOf2(int value) { return value != 0 && (value & (value - 1)) == 0; } -double Math_Log(double x) { - /* x = 2^exp * mantissa */ - /* so log(x) = log(2^exp) + log(mantissa) */ - /* so log(x) = exp*log(2) + log(mantissa) */ - /* now need to work out log(mantissa) */ - - return log(x); -} - -double Math_Exp(double x) { - /* let x = k*log(2) + f, where k is integer */ - /* so exp(x) = exp(k*log(2)) * exp(f) */ - /* so exp(x) = exp(log(2^k)) * exp(f) */ - /* so exp(x) = 2^k * exp(f) */ - /* now need to work out exp(f) */ - - return exp(x); -} - /*########################################################################################################################* *--------------------------------------------------Random number generator------------------------------------------------* @@ -140,3 +115,443 @@ float Random_Float(RNGState* seed) { raw = (int)(*seed >> (48 - 24)); return raw / ((float)(1 << 24)); } + +/***** Caleb's Math functions *****/ + +/* This code implements the math functions sine, cosine, arctangent, the + * exponential function, and the logarithmic function. The code uses techniques + * exclusively described in the book "Computer Approximations" by John Fraser + * Hart (1st Edition). Each function approximates their associated math function + * the same way: + * + * 1. First, the function uses properties of the associated math function to + * reduce the input range to a small finite interval, + * + * 2. Second, the function calculates a polynomial, rational, or similar + * function that approximates the associated math function on that small + * finite interval to the desired accuracy. These polynomial, rational, or + * similar functions were calculated by the authors of "Computer + * Approximations" using the Remez algorithm and exist in the book's + * appendix. + */ + +/* Global constants */ +#define PI 3.141592653589793238462643383279502884197169399 +#define DIV_2_PI (1.0 / (2.0 * PI)) + +static const cc_uint64 _DBL_NAN = 0x7FF8000000000000ULL; +#define DBL_NAN *((double*)&_DBL_NAN) +static const cc_uint64 _POS_INF = 0x7FF0000000000000ULL; +#define POS_INF *((double*)&_POS_INF) +static const cc_uint64 _NEG_INF = 0xFFF0000000000000ULL; +#define NEG_INF *((double*)&_NEG_INF) + +static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769; +static const double LOGE2 = 0.6931471805599453094172321214581765680755001343602; + +/* Calculates the floor of a double. + */ +static double Floord(double x) { + if (x >= 0) + return (double) ((int) x); + return (double) (((int) x) - 1); +} + +/************ + * Math_Sin * + ************/ + +/* Calculates the 5th degree polynomial function SIN 2922 listed in the book's + * appendix. + * + * Associated math function: sin(pi/6 * x) + * Allowed input range: [0, 1] + * Precision: 16.47 + */ +static double SinStage1(double x) { + const double A[] = { + .52359877559829885532, + -.2392459620393377657e-1, + .32795319441392666e-3, + -.214071970654441e-5, + .815113605169e-8, + -.2020852964e-10, + }; + + double P = A[5]; + double x_2 = x * x; + int i; + + for (i = 4; i >= 0; i--) { + P *= x_2; + P += A[i]; + } + P *= x; + return P; +} + +/* Uses the property + * sin(x) = sin(x/3) * (3 - 4 * (sin(x/3))^2) + * to reduce the input range of sin(x) to [0, pi/6]. + * + * Associated math function: sin(2 * pi * x) + * Allowed input range: [0, 0.25] + */ +static double SinStage2(double x) { + double sin_6 = SinStage1(x * 4.0); + return sin_6 * (3.0 - 4.0 * sin_6 * sin_6); +} + +/* Uses the properties of sine to reduce the input range from [0, 2*pi] to [0, + * pi/2]. + * + * Associated math function: sin(2 * pi * x) + * Allowed input range: [0, 1] + */ +static double SinStage3(double x) { + if (x < 0.25) + return SinStage2(x); + if (x < 0.5) + return SinStage2(0.5 - x); + if (x < 0.75) + return -SinStage2(x - 0.5); + return -SinStage2(1.0 - x); +} + +/* Since sine has a period of 2*pi, this function maps any real number to a + * number from [0, 2*pi]. + * + * Associated math function: sin(x) + * Allowed input range: anything + */ +double Math_Sin(double x) { + double x_div_pi; + + if (x == POS_INF || x == NEG_INF || x == DBL_NAN) + return DBL_NAN; + + x_div_pi = x * DIV_2_PI; + return SinStage3(x_div_pi - Floord(x_div_pi)); +} + +/************ + * Math_Cos * + ************/ + +/* This function works just like the above sine function, except it shifts the + * input by pi/2, using the property cos(x) = sin(x + pi/2). + * + * Associated math function: cos(x) + * Allowed input range: anything + */ +double Math_Cos(double x) { + double x_div_pi_shifted; + + if (x == POS_INF || x == NEG_INF || x == DBL_NAN) + return DBL_NAN; + + x_div_pi_shifted = x * DIV_2_PI + 0.25; + return SinStage3(x_div_pi_shifted - Floord(x_div_pi_shifted)); +} + +/************** + * Math_Atan2 * + **************/ + +/* Calculates the 5th degree polynomial ARCTN 4903 listed in the book's + * appendix. + * + * Associated math function: arctan(x) + * Allowed input range: [0, tan(pi/32)] + * Precision: 16.52 + */ +static double AtanStage1(double x) { + const double A[] = { + .99999999999969557, + -.3333333333318, + .1999999997276, + -.14285702288, + .11108719478, + -.8870580341e-1, + }; + + double P = A[5]; + double x_2 = x * x; + int i; + + for (i = 4; i >= 0; i--) { + P *= x_2; + P += A[i]; + } + P *= x; + return P; +} + +/* This function finds out in which partition the non-negative real number x + * resides out of 8 partitions, which are precomputed. It then uses the + * following law: + * + * t = x_i^{-1} - (x_i^{-2} + 1)/(x_i^{-1} + x) + * arctan(x) = arctan(x_i) + arctan(t) + * + * where x_i = tan((2i - 2)*pi/32) and i is the partition number. The value of t + * is guaranteed to be between [-tan(pi/32), tan(pi/32)]. + * + * Associated math function: arctan(x) + * Allowed input range: [0, infinity] + */ +static double AtanStage2(double x) { + const double X_i[] = { + 0.0, + 0.0984914033571642477671304050090839155018329620361328125, + 0.3033466836073424044428747947677038609981536865234375, + 0.53451113595079158269385288804187439382076263427734375, + 0.82067879082866024287312711749109439551830291748046875, + 1.218503525587976366040265929768793284893035888671875, + 1.8708684117893887854933154812897555530071258544921875, + 3.29655820893832096629694206058047711849212646484375, + (float)(1e+300 * 1e+300) /* Infinity */ + }; + + const double div_x_i[] = { + 0, + 0, + 5.02733949212584807497705696732737123966217041015625, + 2.41421356237309492343001693370752036571502685546875, + 1.496605762665489169904731170390732586383819580078125, + 1.0000000000000002220446049250313080847263336181640625, + 0.66817863791929898997778991542872972786426544189453125, + 0.414213562373095089963470627481001429259777069091796875, + 0.1989123673796580893391450217677629552781581878662109375, + }; + + const double div_x_i_2_plus_1[] = { + 0, + 0, + 26.2741423690881816810360760428011417388916015625, + 6.8284271247461898468600338674150407314300537109375, + 3.23982880884355051165357508580200374126434326171875, + 2.000000000000000444089209850062616169452667236328125, + 1.446462692171689656817079594475217163562774658203125, + 1.1715728752538099310953612075536511838436126708984375, + 1.0395661298965801488947136022034101188182830810546875, + }; + + int L = 0; + int R = 8; + double t; + + while (R - L > 1) { + int m = (L + R) / 2; + if (X_i[m] <= x) + L = m; + else if (X_i[m] > x) + R = m; + } + + if (R <= 1) + return AtanStage1(x); + + t = div_x_i[R] - div_x_i_2_plus_1[R] / (div_x_i[R] + x); + if (t >= 0) + return (2 * R - 2) * PI / 32.0 + AtanStage1(t); + + return (2 * R - 2) * PI / 32.0 - AtanStage1(-t); +} + +/* Uses the property arctan(x) = -arctan(-x). + * + * Associated math function: arctan(x) + * Allowed input range: anything + */ +static double Atan(double x) { + if (x == DBL_NAN) + return DBL_NAN; + if (x == NEG_INF) + return -PI / 2.0; + if (x == POS_INF) + return PI / 2.0; + if (x >= 0) + return AtanStage2(x); + return -AtanStage2(-x); +} + +/* Implements the function atan2 using Atan. + * + * Associated math function: atan2(y, x) + * Allowed input range: anything + */ +double Math_Atan2(double x, double y) { + if (x > 0) + return Atan(y / x); + if (x < 0) { + if (y >= 0) + return Atan(y / x) + PI; + return Atan(y / x) - PI; + } + if (y > 0) + return PI / 2.0; + if (y < 0) + return -PI / 2.0; + return DBL_NAN; +} + +/************ + * Math_Exp * + ************/ + +/* Calculates the function EXPB 1067 listed in the book's appendix. It is of the + * form + * (Q(x^2) + x*P(x^2)) / (Q(x^2) - x*P(x^2)) + * + * Associated math function: 2^x + * Allowed input range: [-1/2, 1/2] + * Precision: 18.08 + */ +static double Exp2Stage1(double x) { + const double A_P[] = { + .1513906799054338915894328e4, + .20202065651286927227886e2, + .23093347753750233624e-1, + }; + + const double A_Q[] = { + .4368211662727558498496814e4, + .233184211427481623790295e3, + 1.0, + }; + + double x_2 = x * x; + double P, Q; + int i; + + P = A_P[2]; + for (i = 1; i >= 0; i--) { + P *= x_2; + P += A_P[i]; + } + P *= x; + + Q = A_Q[2]; + for (i = 1; i >= 0; i--) { + Q *= x_2; + Q += A_Q[i]; + } + + return (Q + P) / (Q - P); +} + +/* Reduces the range of 2^x to [-1/2, 1/2] by using the property + * 2^x = 2^(integer value) * 2^(fractional part). + * 2^(integer value) can be calculated by directly manipulating the bits of the + * double-precision floating point representation. + * + * Associated math function: 2^x + * Allowed input range: anything + */ +double Math_Exp2(double x) { + int x_int; + union { double d; cc_uint64 i; } doi; + + if (x == POS_INF || x == DBL_NAN) + return x; + if (x == NEG_INF) + return 0.0; + + x_int = (int) x; + + if (x < 0) + x_int--; + + if (x_int < -1022) + return 0.0; + if (x_int > 1023) + return POS_INF; + + doi.i = x_int + 1023; + doi.i <<= 52; + + return doi.d * SQRT2 * Exp2Stage1(x - (double) x_int - 0.5); +} + +/************ + * Math_Log * + ************/ + +/* Calculates the 3rd/3rd degree rational function LOG2 2524 listed in the + * book's appendix. + * + * Associated math function: log_2(x) + * Allowed input range: [0.5, 1] + * Precision: 8.32 + */ +static double Log2Stage1(double x) { + const double A_P[] = { + -.205466671951e1, + -.88626599391e1, + .610585199015e1, + .481147460989e1, + }; + + const double A_Q[] = { + .353553425277, + .454517087629e1, + .642784209029e1, + 1.0, + }; + + double P, Q; + int i; + + P = A_P[3]; + for (i = 2; i >= 0; i--) { + P *= x; + P += A_P[i]; + } + + Q = A_Q[3]; + for (i = 2; i >= 0; i--) { + Q *= x; + Q += A_Q[i]; + } + + return P / Q; +} + +/* Reduces the range of log_2(x) by using the property that + * log_2(x) = (x's exponent part) + log_2(x's mantissa part) + * So, by manipulating the bits of the double-precision floating point number + * one can reduce the range of the logarithm function. + * + * Associated math function: log_2(x) + * Allowed input range: anything + */ +double Math_Log2(double x) { + union { double d; cc_uint64 i; } doi; + int exponent; + + if (x == POS_INF) + return POS_INF; + + if (x == NEG_INF || x == DBL_NAN || x <= 0.0) + return DBL_NAN; + + doi.d = x; + exponent = (doi.i >> 52); + exponent -= 1023; + + doi.i |= (((cc_uint64) 1023) << 52); + doi.i &= ~(((cc_uint64) 1024) << 52); + + return exponent + Log2Stage1(doi.d); +} + +/* Uses the property that + * log_e(x) = log_2(x) * log_e(2). + * + * Associated math function: log_e(x) + * Allowed input range: anything + */ +double Math_Log(double x) { + return Math_Log2(x) * LOGE2; +} diff --git a/src/ExtMath.h b/src/ExtMath.h index c7bafd3..9bae344 100644 --- a/src/ExtMath.h +++ b/src/ExtMath.h @@ -35,15 +35,18 @@ float Math_CosF(float x); double Math_Atan2(double x, double y); /* Computes loge(x). Can also be used to approximate logy(x). */ -/* e.g. for log3(x), use: Math_Log(x)/log(3) */ +/* e.g. for log3(x), use: Math_Log(x)/log(3) */ double Math_Log(double x); -/* Computes e^x. Can also be used to approximate y^x. */ -/* e.g. for 3^x, use: Math_Exp(log(3)*x) */ -double Math_Exp(double x); +/* Computes log2(x). Can also be used to approximate log2(x). */ +/* e.g. for log3(x), use: Math_Log2(x)/log2(3) */ +double Math_Log2(double x); +/* Computes 2^x. Can also be used to approximate y^x. */ +/* e.g. for 3^x, use: Math_Exp2(log2(3)*x) */ +double Math_Exp2(double x); int Math_Floor(float value); int Math_Ceil(float value); -int Math_Log2(cc_uint32 value); +int Math_ilog2(cc_uint32 value); int Math_CeilDiv(int a, int b); int Math_Sign(float value); diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index 4d0c6d8..ce13e58 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -254,7 +254,7 @@ static unsigned Interleave(unsigned x) { int min_dimension = Math.Min(w, h); int interleave_mask = min_dimension - 1; - int interleaved_bits = Math_Log2(min_dimension); + int interleaved_bits = Math_ilog2(min_dimension); int shifted_mask = (~0) & ~interleave_mask; // as lower interleaved bits contain both X and Y, need to adjust the @@ -280,7 +280,7 @@ static unsigned Interleave(unsigned x) { #define Twiddle_CalcFactors(w, h) \ min_dimension = min(w, h); \ interleave_mask = min_dimension - 1; \ - interleaved_bits = Math_Log2(min_dimension); \ + interleaved_bits = Math_ilog2(min_dimension); \ shifted_mask = 0xFFFFFFFFU & ~interleave_mask; \ shift_bits = interleaved_bits; diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c index 247fe9b..ca6cfd6 100644 --- a/src/Graphics_PS3.c +++ b/src/Graphics_PS3.c @@ -405,11 +405,10 @@ static void ResetFrameState(void) { rsxSetColorMaskMrt(context, 0); rsxSetClearColor(context, clearColor); rsxSetClearDepthStencil(context, 0xFFFFFFFF); - rsxSetFrontFace(context, GCM_FRONTFACE_CCW); rsxSetDepthFunc(context, GCM_LEQUAL); - rsxSetDepthWriteEnable(context, depth_write & depth_test); - rsxSetDepthTestEnable(context, depth_test); + rsxSetDepthWriteEnable(context, true); + rsxSetDepthTestEnable(context, true); rsxSetUserClipPlaneControl(context, GCM_USER_CLIP_PLANE_DISABLE, GCM_USER_CLIP_PLANE_DISABLE, diff --git a/src/Graphics_Xbox.c b/src/Graphics_Xbox.c index f9ea5f6..bbf63ff 100644 --- a/src/Graphics_Xbox.c +++ b/src/Graphics_Xbox.c @@ -164,7 +164,7 @@ static unsigned Interleave(unsigned x) { #define Twiddle_CalcFactors(w, h) \ min_dimension = min(w, h); \ interleave_mask = min_dimension - 1; \ - interleaved_bits = Math_Log2(min_dimension); \ + interleaved_bits = Math_ilog2(min_dimension); \ shifted_mask = 0xFFFFFFFFU & ~interleave_mask; \ shift_bits = interleaved_bits; @@ -251,8 +251,8 @@ void Gfx_BindTexture(GfxResourceID texId) { CCTexture* tex = (CCTexture*)texId; if (!tex) tex = white_square; - unsigned log_u = Math_Log2(tex->width); - unsigned log_v = Math_Log2(tex->height); + unsigned log_u = Math_ilog2(tex->width); + unsigned log_v = Math_ilog2(tex->height); uint32_t* p; p = pb_begin(); diff --git a/src/PackedCol.h b/src/PackedCol.h index c91208c..8990128 100644 --- a/src/PackedCol.h +++ b/src/PackedCol.h @@ -6,7 +6,7 @@ */ typedef cc_uint32 PackedCol; -#if defined CC_BUILD_D3D9 || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST || defined CC_BUILD_PS3 +#if defined CC_BUILD_D3D9 || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST #define PACKEDCOL_B_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 #define PACKEDCOL_R_SHIFT 16 diff --git a/src/Particle.c b/src/Particle.c index 41adf9a..a6f92c5 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -538,7 +538,7 @@ void Particles_CustomEffect(int effectID, float x, float y, float z, float origi /* See https://karthikkaranth.me/blog/generating-random-points-in-a-sphere/ */ /* 'Using normally distributed random numbers' */ d = Random_Float(&rnd); - d = Math_Exp(Math_Log(d) / 3.0); /* d^1/3 for better distribution */ + d = Math_Exp2(Math_Log2(d) / 3.0); /* d^1/3 for better distribution */ d *= e->spread; p->base.lastPos.X = x + offset.X * d; diff --git a/src/Program.c b/src/Program.c index e16043d..988e330 100644 --- a/src/Program.c +++ b/src/Program.c @@ -138,7 +138,7 @@ void android_main(void) { SetupProgram(0, NULL); for (;;) { RunProgram(0, NULL); } } -#elif defined CC_BUILD_3DS || defined CC_BUILD_PSP || defined CC_BUILD_GCWII || defined CC_BUILD_DREAMCAST || defined CC_BUILD_XBOX || defined CC_BUILD_PSVITA +#elif defined CC_BUILD_3DS || defined CC_BUILD_PSP || defined CC_BUILD_GCWII || defined CC_BUILD_DREAMCAST || defined CC_BUILD_XBOX || defined CC_BUILD_PSVITA || defined CC_BUILD_PS3 int main(int argc, char** argv) { SetupProgram(argc, argv); while (WindowInfo.Exists) { diff --git a/src/Protocol.c b/src/Protocol.c index f62cc96..d3e2362 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -1734,8 +1734,7 @@ static BlockID BlockDefs_DefineBlockCommonStart(cc_uint8** ptr, cc_bool uniqueSi Blocks.Collide[block] = *data++; speedLog2 = (*data++ - 128) / 64.0f; - #define LOG_2 0.693147180559945 - Blocks.SpeedMultiplier[block] = (float)Math_Exp(LOG_2 * speedLog2); /* pow(2, x) */ + Blocks.SpeedMultiplier[block] = (float)Math_Exp2(speedLog2); Block_Tex(block, FACE_YMAX) = BlockDefs_Tex(&data); if (uniqueSideTexs) { diff --git a/src/SSL.c b/src/SSL.c index 13e3126..b391229 100644 --- a/src/SSL.c +++ b/src/SSL.c @@ -429,6 +429,8 @@ typedef struct SSLContext { br_x509_minimal_context xc; unsigned char iobuf[BR_SSL_BUFSIZE_BIDI]; br_sslio_context ioc; + cc_result readError, writeError; + cc_socket socket; } SSLContext; static cc_bool _verifyCerts; @@ -438,7 +440,15 @@ void SSLBackend_Init(cc_bool verifyCerts) { _verifyCerts = verifyCerts; // TODO support } -cc_bool SSLBackend_DescribeError(cc_result res, cc_string* dst) { +cc_bool SSLBackend_DescribeError(cc_result res, cc_string* dst) { + switch (res) { + case SSL_ERROR_SHIFT | BR_ERR_X509_EXPIRED: + String_AppendConst(dst, "The website's SSL certificate is expired or not yet valid"); + return true; + case SSL_ERROR_SHIFT | BR_ERR_X509_NOT_TRUSTED: + String_AppendConst(dst, "The website's SSL certificate was issued by an authority that is not trusted"); + return true; + } return false; // TODO: error codes } @@ -446,49 +456,49 @@ cc_bool SSLBackend_DescribeError(cc_result res, cc_string* dst) { #include <3ds.h> static void InjectEntropy(SSLContext* ctx) { char buf[32]; - int res = PS_GenerateRandomBytes(buf, 32); - if (res == 0) return; // NOTE: Not implemented in Citra + PS_GenerateRandomBytes(buf, 32); + // NOTE: PS_GenerateRandomBytes isn't implemented in Citra br_ssl_engine_inject_entropy(&ctx->sc.eng, buf, 32); } -#elif defined CC_BUILD_GCWII +#else +#warning "Using uninitialised stack data for entropy. This should be replaced with actual cryptographic RNG data" static void InjectEntropy(SSLContext* ctx) { char buf[32]; - // TODO: Is there an actual API to retrieve random data? + // TODO: Use actual APIs to retrieve random data br_ssl_engine_inject_entropy(&ctx->sc.eng, buf, 32); } -#elif defined CC_BUILD_PSP -static void InjectEntropy(SSLContext* ctx) { - char buf[32]; - // TODO: Is there an actual API to retrieve random data? - - br_ssl_engine_inject_entropy(&ctx->sc.eng, buf, 32); -} -#elif defined CC_BUILD_VITA -static void InjectEntropy(SSLContext* ctx) { - char buf[32]; - // TODO: Is there an actual API to retrieve random data? +#endif - br_ssl_engine_inject_entropy(&ctx->sc.eng, buf, 32); +static void SetCurrentTime(SSLContext* ctx) { + cc_uint64 cur = DateTime_CurrentUTC_MS() / 1000; + uint32_t days = (uint32_t)(cur / 86400) + 366; + uint32_t secs = (uint32_t)(cur % 86400); + + br_x509_minimal_set_time(&ctx->xc, days, secs); + /* This matches bearssl's default time calculation + time_t x = time(NULL); + vd = (uint32_t)(x / 86400) + 719528; + vs = (uint32_t)(x % 86400); + */ } -#else -static void InjectEntropy(SSLContext* ctx) { } -#endif -static int sock_read(void *ctx, unsigned char *buf, size_t len) { +static int sock_read(void* ctx_, unsigned char* buf, size_t len) { + SSLContext* ctx = (SSLContext*)ctx_; cc_uint32 read; - cc_result res = Socket_Read((int)ctx, buf, len, &read); + cc_result res = Socket_Read(ctx->socket, buf, len, &read); - if (res) return -1; + if (res) { ctx->readError = res; return -1; } return read; } -static int sock_write(void *ctx, const unsigned char *buf, size_t len) { +static int sock_write(void* ctx_, const unsigned char* buf, size_t len) { + SSLContext* ctx = (SSLContext*)ctx_; cc_uint32 wrote; - cc_result res = Socket_Write((int)ctx, buf, len, &wrote); + cc_result res = Socket_Write(ctx->socket, buf, len, &wrote); - if (res) return -1; + if (res) { ctx->writeError = res; return -1; } return wrote; } @@ -507,13 +517,18 @@ cc_result SSL_Init(cc_socket socket, const cc_string* host_, void** out_ctx) { br_x509_minimal_set_ecdsa(&ctx->xc, &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); }*/ InjectEntropy(ctx); + SetCurrentTime(ctx); + ctx->socket = socket; br_ssl_engine_set_buffer(&ctx->sc.eng, ctx->iobuf, sizeof(ctx->iobuf), 1); br_ssl_client_reset(&ctx->sc, host, 0); br_sslio_init(&ctx->ioc, &ctx->sc.eng, - sock_read, (void*)socket, - sock_write, (void*)socket); + sock_read, ctx, + sock_write, ctx); + + ctx->readError = 0; + ctx->writeError = 0; return 0; } @@ -522,7 +537,11 @@ cc_result SSL_Read(void* ctx_, cc_uint8* data, cc_uint32 count, cc_uint32* read) SSLContext* ctx = (SSLContext*)ctx_; // TODO: just br_sslio_write ?? int res = br_sslio_read(&ctx->ioc, data, count); - if (res < 0) return SSL_ERROR_SHIFT + br_ssl_engine_last_error(&ctx->sc.eng); + + if (res < 0) { + if (ctx->readError) return ctx->readError; + return SSL_ERROR_SHIFT + br_ssl_engine_last_error(&ctx->sc.eng); + } br_sslio_flush(&ctx->ioc); *read = res; @@ -533,7 +552,11 @@ cc_result SSL_Write(void* ctx_, const cc_uint8* data, cc_uint32 count, cc_uint32 SSLContext* ctx = (SSLContext*)ctx_; // TODO: just br_sslio_write ?? int res = br_sslio_write_all(&ctx->ioc, data, count); - if (res < 0) return SSL_ERROR_SHIFT + br_ssl_engine_last_error(&ctx->sc.eng); + + if (res < 0) { + if (ctx->writeError) return ctx->writeError; + return SSL_ERROR_SHIFT + br_ssl_engine_last_error(&ctx->sc.eng); + } br_sslio_flush(&ctx->ioc); *wrote = res; diff --git a/src/SystemFonts.c b/src/SystemFonts.c index 048f339..a2d1478 100644 --- a/src/SystemFonts.c +++ b/src/SystemFonts.c @@ -721,38 +721,6 @@ int SysFont_TextWidth(struct DrawTextArgs* args) { void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { interop_SysTextDraw(args, bmp, x, y, shadow); } -#elif defined CC_BUILD_PSP -void SysFonts_Register(const cc_string* path) { } - -const cc_string* SysFonts_UNSAFE_GetDefault(void) { return &String_Empty; } - -void SysFonts_GetNames(struct StringsBuffer* buffer) { } - -cc_result SysFont_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags) { - desc->size = size; - desc->flags = flags; - desc->height = Drawer2D_AdjHeight(size); - - desc->handle = (void*)1; - - // TODO: Actually implement native font APIs - Font_MakeBitmapped(desc, size, flags); - return 0; -} - -void SysFont_MakeDefault(struct FontDesc* desc, int size, int flags) { - SysFont_Make(desc, NULL, size, flags); -} - -void SysFont_Free(struct FontDesc* desc) { -} - -int SysFont_TextWidth(struct DrawTextArgs* args) { - return 10; -} - -void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { -} #elif defined CC_BUILD_GCWII #include void SysFonts_Register(const cc_string* path) { } @@ -1313,7 +1281,7 @@ int SysFont_TextWidth(struct DrawTextArgs* args) { } width = TEXT_CEIL(width); - Platform_Log2("TEXT WIDTH: %i (%s)", &width, &args->text); + //Platform_Log2("TEXT WIDTH: %i (%s)", &width, &args->text); if (args->useShadow) width += 2; return max(1, width); } @@ -1367,7 +1335,7 @@ static int DrawGlyph(struct SysFont* font, int size, struct Bitmap* bmp, int x, //glyph.yPos64 = +charInfo.glyphMetrics.horizontalBearingY64; // TODO: use charInfo.glyphMetrics.horizontalBearingX64 and Y64 - Platform_Log1("ABOUT %r:", &c); + //Platform_Log1("ABOUT %r:", &c); int BX = charInfo.glyphMetrics.horizontalBearingX64, BX2 = TEXT_CEIL(BX); int BY = charInfo.glyphMetrics.horizontalBearingY64, BY2 = TEXT_CEIL(BY); //Platform_Log4(" Bitmap: %i,%i --> %i, %i", &charInfo.bitmapLeft, &charInfo.bitmapTop, &charInfo.bitmapWidth, &charInfo.bitmapHeight); @@ -1377,12 +1345,12 @@ static int DrawGlyph(struct SysFont* font, int size, struct Bitmap* bmp, int x, int A = charInfo.glyphMetrics.ascender64, A2 =TEXT_CEIL(A); int D = charInfo.glyphMetrics.descender64, D2 =TEXT_CEIL(D); - Platform_Log4(" Size: %i,%i (%i, %i)", &W, &H, &W2, &H2); - Platform_Log4(" Vert: %i,%i (%i, %i)", &A, &D, &A2, &D2); - Platform_Log4(" Bear: %i,%i (%i, %i)", &BX, &BY, &BX2, &BY2); + //Platform_Log4(" Size: %i,%i (%i, %i)", &W, &H, &W2, &H2); + //Platform_Log4(" Vert: %i,%i (%i, %i)", &A, &D, &A2, &D2); + //Platform_Log4(" Bear: %i,%i (%i, %i)", &BX, &BY, &BX2, &BY2); int CW = charRect.width, CH = charRect.height; - Platform_Log2(" CharSize: %i,%i", &CW, &CH); + //Platform_Log2(" CharSize: %i,%i", &CW, &CH); if (A2 < size) y += (size - A2); @@ -1402,7 +1370,7 @@ void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int int W = SysFont_TextWidth(args); int S = args->font->size; int H = args->font->height; - Platform_Log3("TOTAL: %i (%i/%i)", &W, &S, &H); + //Platform_Log3("TOTAL: %i (%i/%i)", &W, &S, &H); cc_string left = args->text, part; char colorCode = 'f'; @@ -1419,4 +1387,223 @@ void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int } } } +#else + +#define SysFont_ValidChar(c) ((c) > 32 && (c) < 127) +#define SysFont_ToIndex(c) ((c) - 33) /* First valid char is ! */ +#define SPACE_WIDTH 2 +#define CELL_SIZE 8 + +#define SysFont_GetRows(c) (SysFont_ValidChar(c) ? font_bitmap[SysFont_ToIndex(c)] : missing_cell) + +static cc_uint8 missing_cell[CELL_SIZE] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF +}; + +/* 8x8 font bitmap, represented with 1 bit for each pixel */ +/* Source: Goodly's texture pack for ClassiCube */ +static cc_uint8 font_bitmap[][CELL_SIZE] = { + { 0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x00 }, /* ! */ + { 0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00 }, /* " */ + { 0x0A,0x0A,0x1F,0x0A,0x1F,0x0A,0x0A,0x00 }, /* # */ + { 0x04,0x1F,0x01,0x1F,0x10,0x1F,0x04,0x00 }, /* $ */ + { 0x00,0x21,0x11,0x08,0x04,0x22,0x21,0x00 }, /* % */ + { 0x0C,0x12,0x0C,0x2E,0x19,0x11,0x2E,0x00 }, /* & */ + { 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00 }, /* ' */ + { 0x04,0x02,0x01,0x01,0x01,0x02,0x04,0x00 }, /* ( */ + { 0x01,0x02,0x04,0x04,0x04,0x02,0x01,0x00 }, /* ) */ + { 0x00,0x02,0x07,0x02,0x05,0x00,0x00,0x00 }, /* * */ + { 0x00,0x04,0x04,0x1F,0x04,0x04,0x00,0x00 }, /* + */ + { 0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x01 }, /* , */ + { 0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00 }, /* - */ + { 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00 }, /* . */ + { 0x08,0x08,0x04,0x04,0x02,0x02,0x01,0x00 }, /* / */ + { 0x06,0x09,0x0D,0x0B,0x09,0x09,0x06,0x00 }, /* 0 */ + { 0x02,0x03,0x02,0x02,0x02,0x02,0x07,0x00 }, /* 1 */ + { 0x06,0x09,0x08,0x04,0x02,0x09,0x0F,0x00 }, /* 2 */ + { 0x06,0x09,0x08,0x06,0x08,0x09,0x06,0x00 }, /* 3 */ + { 0x05,0x05,0x05,0x0F,0x04,0x04,0x04,0x00 }, /* 4 */ + { 0x0F,0x01,0x07,0x08,0x08,0x09,0x06,0x00 }, /* 5 */ + { 0x06,0x09,0x01,0x07,0x09,0x09,0x06,0x00 }, /* 6 */ + { 0x0F,0x08,0x08,0x04,0x04,0x02,0x02,0x00 }, /* 7 */ + { 0x06,0x09,0x09,0x06,0x09,0x09,0x06,0x00 }, /* 8 */ + { 0x06,0x09,0x09,0x0E,0x08,0x09,0x06,0x00 }, /* 9 */ + { 0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00 }, /* : */ + { 0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x01 }, /* ; */ + { 0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00 }, /* < */ + { 0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00 }, /* = */ + { 0x00,0x01,0x02,0x04,0x02,0x01,0x00,0x00 }, /* > */ + { 0x07,0x09,0x08,0x04,0x02,0x00,0x02,0x00 }, /* ? */ + { 0x0E,0x11,0x1D,0x1D,0x1D,0x01,0x0E,0x00 }, /* @ */ + { 0x06,0x09,0x09,0x0F,0x09,0x09,0x09,0x00 }, /* A */ + { 0x07,0x09,0x09,0x07,0x09,0x09,0x07,0x00 }, /* B */ + { 0x06,0x09,0x01,0x01,0x01,0x09,0x06,0x00 }, /* C */ + { 0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x00 }, /* D */ + { 0x0F,0x01,0x01,0x07,0x01,0x01,0x0F,0x00 }, /* E */ + { 0x0F,0x01,0x01,0x07,0x01,0x01,0x01,0x00 }, /* F */ + { 0x06,0x09,0x01,0x0D,0x09,0x09,0x06,0x00 }, /* G */ + { 0x09,0x09,0x09,0x0F,0x09,0x09,0x09,0x00 }, /* H */ + { 0x07,0x02,0x02,0x02,0x02,0x02,0x07,0x00 }, /* I */ + { 0x08,0x08,0x08,0x08,0x08,0x09,0x07,0x00 }, /* J */ + { 0x09,0x09,0x05,0x03,0x05,0x09,0x09,0x00 }, /* K */ + { 0x01,0x01,0x01,0x01,0x01,0x01,0x0F,0x00 }, /* L */ + { 0x11,0x1B,0x15,0x11,0x11,0x11,0x11,0x00 }, /* M */ + { 0x09,0x0B,0x0D,0x09,0x09,0x09,0x09,0x00 }, /* N */ + { 0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x00 }, /* O */ + { 0x07,0x09,0x09,0x07,0x01,0x01,0x01,0x00 }, /* P */ + { 0x06,0x09,0x09,0x09,0x09,0x05,0x0E,0x00 }, /* Q */ + { 0x07,0x09,0x09,0x07,0x09,0x09,0x09,0x00 }, /* R */ + { 0x06,0x09,0x01,0x06,0x08,0x09,0x06,0x00 }, /* S */ + { 0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x00 }, /* T */ + { 0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x00 }, /* U */ + { 0x11,0x11,0x11,0x11,0x11,0x0A,0x04,0x00 }, /* V */ + { 0x11,0x11,0x11,0x11,0x15,0x1B,0x11,0x00 }, /* W */ + { 0x11,0x11,0x0A,0x04,0x0A,0x11,0x11,0x00 }, /* X */ + { 0x11,0x11,0x0A,0x04,0x04,0x04,0x04,0x00 }, /* Y */ + { 0x0F,0x08,0x04,0x02,0x01,0x01,0x0F,0x00 }, /* Z */ + { 0x07,0x01,0x01,0x01,0x01,0x01,0x07,0x00 }, /* [ */ + { 0x01,0x01,0x02,0x02,0x04,0x04,0x08,0x00 }, /* \ */ + { 0x07,0x04,0x04,0x04,0x04,0x04,0x07,0x00 }, /* ] */ + { 0x04,0x0A,0x11,0x00,0x00,0x00,0x00,0x00 }, /* ^ */ + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F }, /* _ */ + { 0x01,0x01,0x02,0x00,0x00,0x00,0x00,0x00 }, /* ` */ + { 0x00,0x00,0x0E,0x09,0x09,0x0D,0x0B,0x00 }, /* a */ + { 0x01,0x01,0x07,0x09,0x09,0x09,0x07,0x00 }, /* b */ + { 0x00,0x00,0x06,0x09,0x01,0x09,0x06,0x00 }, /* c */ + { 0x08,0x08,0x0E,0x09,0x09,0x09,0x0E,0x00 }, /* d */ + { 0x00,0x00,0x06,0x09,0x0F,0x01,0x0E,0x00 }, /* e */ + { 0x06,0x01,0x07,0x01,0x01,0x01,0x01,0x00 }, /* f */ + { 0x00,0x00,0x0E,0x09,0x09,0x0E,0x08,0x07 }, /* g */ + { 0x01,0x01,0x07,0x09,0x09,0x09,0x09,0x00 }, /* h */ + { 0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x00 }, /* i */ + { 0x08,0x00,0x08,0x08,0x08,0x08,0x09,0x06 }, /* j */ + { 0x01,0x01,0x09,0x05,0x03,0x05,0x09,0x00 }, /* k */ + { 0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x00 }, /* l */ + { 0x00,0x00,0x0B,0x15,0x15,0x11,0x11,0x00 }, /* m */ + { 0x00,0x00,0x07,0x09,0x09,0x09,0x09,0x00 }, /* n */ + { 0x00,0x00,0x06,0x09,0x09,0x09,0x06,0x00 }, /* o */ + { 0x00,0x00,0x07,0x09,0x09,0x07,0x01,0x01 }, /* p */ + { 0x00,0x00,0x0E,0x09,0x09,0x0E,0x08,0x08 }, /* q */ + { 0x00,0x00,0x05,0x03,0x01,0x01,0x01,0x00 }, /* r */ + { 0x00,0x00,0x0E,0x01,0x06,0x08,0x07,0x00 }, /* s */ + { 0x02,0x02,0x07,0x02,0x02,0x02,0x02,0x00 }, /* t */ + { 0x00,0x00,0x09,0x09,0x09,0x09,0x0E,0x00 }, /* u */ + { 0x00,0x00,0x09,0x09,0x09,0x05,0x03,0x00 }, /* v */ + { 0x00,0x00,0x11,0x11,0x15,0x15,0x1A,0x00 }, /* w */ + { 0x00,0x00,0x05,0x05,0x02,0x05,0x05,0x00 }, /* x */ + { 0x00,0x00,0x09,0x09,0x09,0x0E,0x08,0x07 }, /* y */ + { 0x00,0x00,0x0F,0x08,0x04,0x02,0x0F,0x00 }, /* z */ + { 0x04,0x02,0x02,0x01,0x02,0x02,0x04,0x00 }, /* { */ + { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, /* | */ + { 0x01,0x02,0x02,0x04,0x02,0x02,0x01,0x00 }, /* } */ + { 0x00,0x00,0x26,0x19,0x00,0x00,0x00,0x00 }, /* ~ */ +}; + + +void SysFonts_Register(const cc_string* path) { } + +const cc_string* SysFonts_UNSAFE_GetDefault(void) { return &String_Empty; } + +void SysFonts_GetNames(struct StringsBuffer* buffer) { } + +cc_result SysFont_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags) { + desc->size = size; + desc->flags = flags; + desc->height = Drawer2D_AdjHeight(size); + + desc->handle = (void*)1; + return 0; +} + +void SysFont_MakeDefault(struct FontDesc* desc, int size, int flags) { + SysFont_Make(desc, NULL, size, flags); +} + +void SysFont_Free(struct FontDesc* desc) { +} + +static int CellWidth(cc_uint8* rows) { + int y, widest = 0; + + for (y = 0; y < CELL_SIZE; y++) + { + widest = max(widest, rows[y]); + } + return Math_ilog2(widest) + 2; /* add padding for next character */ +} + +int SysFont_TextWidth(struct DrawTextArgs* args) { + int width = 0; + cc_string left = args->text, part; + char colorCode = 'f'; + int i; + + while (Drawer2D_UNSAFE_NextPart(&left, &part, &colorCode)) + { + for (i = 0; i < part.length; i++) + { + cc_uint8 c = part.buffer[i]; + if (c == ' ') { + width += SPACE_WIDTH; + } else { + width += CellWidth(SysFont_GetRows(c)); + } + } + } + + width = max(1, width); + if (args->useShadow) width++; + return width; +} + +static void DrawCell(struct Bitmap* bmp, int x, int y, cc_uint8* rows, BitmapCol color) { + int srcX, srcY, dstX, dstY; + cc_uint8 row; + + for (srcY = 0; srcY < CELL_SIZE; srcY++) + { + dstY = y + srcY; + if (dstY < 0 || dstY >= bmp->height) continue; + + row = rows[srcY]; + for (srcX = 0; srcX < CELL_SIZE; srcX++) + { + dstX = x + srcX; + if (dstX < 0 || dstX >= bmp->width) continue; + + if (row & (1 << srcX)) { + Bitmap_GetPixel(bmp, dstX, dstY) = color; + } + } + } +} + +void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { + cc_string left = args->text, part; + char colorCode = 'f'; + cc_uint8* rows; + BitmapCol color; + int i; + + if (shadow) { x++; y++; } + + while (Drawer2D_UNSAFE_NextPart(&left, &part, &colorCode)) + { + color = Drawer2D_GetColor(colorCode); + if (shadow) color = GetShadowColor(color); + + for (i = 0; i < part.length; i++) + { + cc_uint8 c = part.buffer[i]; + if (c == ' ') { + x += SPACE_WIDTH; + } else { + rows = SysFont_GetRows(c); + + DrawCell(bmp, x, y, rows, color); + x += CellWidth(rows); + } + } + } +} #endif diff --git a/src/TexturePack.c b/src/TexturePack.c index 2562377..e297ff4 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -73,7 +73,7 @@ static void Atlas_Update1D(void) { Atlas1D.InvTileSize = 1.0f / Atlas1D.TilesPerAtlas; Atlas1D.Mask = Atlas1D.TilesPerAtlas - 1; - Atlas1D.Shift = Math_Log2(Atlas1D.TilesPerAtlas); + Atlas1D.Shift = Math_ilog2(Atlas1D.TilesPerAtlas); } /* Loads the given atlas and converts it into an array of 1D atlases. */ diff --git a/src/Vorbis.c b/src/Vorbis.c index d75c358..cb6dcb3 100644 --- a/src/Vorbis.c +++ b/src/Vorbis.c @@ -1018,7 +1018,7 @@ void imdct_init(struct imdct_state* state, int n) { float *A = state->a, *B = state->b, *C = state->c; cc_uint32* reversed; - log2_n = Math_Log2(n); + log2_n = Math_ilog2(n); reversed = state->reversed; state->n = n; state->log2_n = log2_n; diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index a39c26a..0687cbb 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -324,7 +324,7 @@ static void GenMipmaps(int width, int height, BitmapCol* dst, BitmapCol* src, in /* Returns the maximum number of mipmaps levels used for given size. */ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) { - int lvlsWidth = Math_Log2(width), lvlsHeight = Math_Log2(height); + int lvlsWidth = Math_ilog2(width), lvlsHeight = Math_ilog2(height); if (customMipmapsLevels) { int lvls = min(lvlsWidth, lvlsHeight); return min(lvls, 4);