mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 01:55:19 -04:00
Simplify altering default builtin colours, and loading options representing colours
Also improve String_Append to deliberately crash the game when attempting to append to an uninitialised string in MSVC debug builds
This commit is contained in:
parent
7bbfd61f63
commit
39b09a9202
@ -20,6 +20,29 @@ Some general guidelines to keep in mind when it comes to `cc_string` strings:
|
||||
- Strings are not garbage collected or reference counted<br>
|
||||
(i.e. you are responsible for managing the lifetime of strings)
|
||||
|
||||
## Usage examples
|
||||
|
||||
Initialisating a string from readonly text:
|
||||
```C
|
||||
cc_string str = String_FromConst("ABC");
|
||||
```
|
||||
|
||||
Initialising a string from temporary memory on the stack:
|
||||
```C
|
||||
// str will be able to store at most 200 characters in it
|
||||
char strBuffer[200];
|
||||
cc_string str = String_FromArray(strBuffer);
|
||||
```
|
||||
|
||||
Initialising a string from persistent memory on the heap:
|
||||
```C
|
||||
// str will be able to store at most 200 characters in it
|
||||
char* str = Mem_Alloc(1, 200, "String buffer");
|
||||
cc_string str = String_Init(str, 0, 200);
|
||||
```
|
||||
|
||||
# Converting to/from other string representations
|
||||
|
||||
## C String conversion
|
||||
|
||||
### C string -> cc_string
|
||||
@ -88,7 +111,7 @@ void SetWorkingDir(cc_string* title) {
|
||||
Platform_EncodeUtf16(&str, title);
|
||||
SetCurrentDirectoryW(str.uni);
|
||||
|
||||
// it's recommended that you DON'T use the ansi format whenever possible
|
||||
// it's recommended that you DON'T use the ansi format whenever possible
|
||||
//SetCurrentDirectoryA(str.ansi);
|
||||
}
|
||||
```
|
||||
@ -106,13 +129,15 @@ void SetWorkingDir(cc_string* title) {
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
# API
|
||||
|
||||
I'm lazy so I will just link to [String.h](/src/String.h)
|
||||
|
||||
If you'd rather I provided a more detailed reference here, please let me know.
|
||||
|
||||
# Extra details
|
||||
TODO
|
||||
|
||||
# Comparisons to other string implementations
|
||||
|
||||
## C comparison
|
||||
|
||||
@ -202,10 +227,7 @@ string::compare -> String_Compare
|
||||
std::sprintf -> String_Format1/2/3/4
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Lifetime examples
|
||||
# Detailed lifetime examples
|
||||
|
||||
Managing the lifetime of strings is important, as not properly managing them can cause issues.
|
||||
|
||||
|
23
src/Chat.c
23
src/Chat.c
@ -415,19 +415,18 @@ static struct ChatCommand GpuInfoCommand = {
|
||||
};
|
||||
|
||||
static void RenderTypeCommand_Execute(const cc_string* args, int argsCount) {
|
||||
int flags;
|
||||
if (!argsCount) {
|
||||
Chat_AddRaw("&e/client: &cYou didn't specify a new render type."); return;
|
||||
}
|
||||
char strBuffer[256];
|
||||
cc_string safeStr = String_FromArray(strBuffer);
|
||||
cc_string unsafeStr;
|
||||
|
||||
flags = EnvRenderer_CalcFlags(args);
|
||||
if (flags >= 0) {
|
||||
EnvRenderer_SetMode(flags);
|
||||
Options_Set(OPT_RENDER_TYPE, args);
|
||||
Chat_Add1("&e/client: &fRender type is now %s.", args);
|
||||
} else {
|
||||
Chat_Add1("&e/client: &cUnrecognised render type &f\"%s\"&c.", args);
|
||||
}
|
||||
Options_SetInt("xyz", 123456);
|
||||
Options_Get("xyz", &safeStr, "");
|
||||
Options_UNSAFE_Get("xyz", &unsafeStr);
|
||||
|
||||
Options_Reload();
|
||||
|
||||
Chat_Add1("Safe: %s", &safeStr);
|
||||
Chat_Add1("Unsafe: %s", &unsafeStr);
|
||||
}
|
||||
|
||||
static struct ChatCommand RenderTypeCommand = {
|
||||
|
@ -633,26 +633,39 @@ static void DefaultPngProcess(struct Stream* stream, const cc_string* name) {
|
||||
static struct TextureEntry default_entry = { "default.png", DefaultPngProcess };
|
||||
|
||||
|
||||
static void InitHexEncodedColor(int i, int hex, cc_uint8 lo, cc_uint8 hi) {
|
||||
Drawer2D.Colors[i] = BitmapColor_RGB(
|
||||
lo * ((hex >> 2) & 1) + hi * (hex >> 3),
|
||||
lo * ((hex >> 1) & 1) + hi * (hex >> 3),
|
||||
lo * ((hex >> 0) & 1) + hi * (hex >> 3));
|
||||
}
|
||||
/* The default 16 colours are the CGA 16 color palette (without special brown colour) */
|
||||
/* See https://en.wikipedia.org/wiki/Color_Graphics_Adapter#With_an_RGBI_monitor for reference */
|
||||
/* The 16 hex colours below were produced from the following formula: */
|
||||
/* R = 191 * ((hex >> 2) & 1) + 64 * (hex >> 3) */
|
||||
/* G = 191 * ((hex >> 1) & 1) + 64 * (hex >> 3) */
|
||||
/* B = 191 * ((hex >> 0) & 1) + 64 * (hex >> 3) */
|
||||
static const BitmapCol defaults_0_9[] = {
|
||||
BitmapColor_RGB( 0, 0, 0), /* 0 */
|
||||
BitmapColor_RGB( 0, 0, 191), /* 1 */
|
||||
BitmapColor_RGB( 0, 191, 0), /* 2 */
|
||||
BitmapColor_RGB( 0, 191, 191), /* 3 */
|
||||
BitmapColor_RGB(191, 0, 0), /* 4 */
|
||||
BitmapColor_RGB(191, 0, 191), /* 5 */
|
||||
BitmapColor_RGB(191, 191, 0), /* 6 */
|
||||
BitmapColor_RGB(191, 191, 191), /* 7 */
|
||||
BitmapColor_RGB( 64, 64, 64), /* 8 */
|
||||
BitmapColor_RGB( 64, 64, 255) /* 9 */
|
||||
};
|
||||
static const BitmapCol defaults_a_f[] = {
|
||||
BitmapColor_RGB( 64, 255, 64), /* A */
|
||||
BitmapColor_RGB( 64, 255, 255), /* B */
|
||||
BitmapColor_RGB(255, 64, 64), /* C */
|
||||
BitmapColor_RGB(255, 64, 255), /* D */
|
||||
BitmapColor_RGB(255, 255, 64), /* E */
|
||||
BitmapColor_RGB(255, 255, 255), /* F */
|
||||
};
|
||||
|
||||
static void OnReset(void) {
|
||||
int i;
|
||||
for (i = 0; i < DRAWER2D_MAX_COLORS; i++) {
|
||||
Drawer2D.Colors[i] = 0;
|
||||
}
|
||||
Mem_Set(Drawer2D.Colors, 0, sizeof(Drawer2D.Colors));
|
||||
|
||||
for (i = 0; i <= 9; i++) {
|
||||
InitHexEncodedColor('0' + i, i, 191, 64);
|
||||
}
|
||||
for (i = 10; i <= 15; i++) {
|
||||
InitHexEncodedColor('a' + (i - 10), i, 191, 64);
|
||||
InitHexEncodedColor('A' + (i - 10), i, 191, 64);
|
||||
}
|
||||
Mem_Copy(&Drawer2D.Colors['0'], defaults_0_9, sizeof(defaults_0_9));
|
||||
Mem_Copy(&Drawer2D.Colors['a'], defaults_a_f, sizeof(defaults_a_f));
|
||||
Mem_Copy(&Drawer2D.Colors['A'], defaults_a_f, sizeof(defaults_a_f));
|
||||
}
|
||||
|
||||
static void OnInit(void) {
|
||||
|
@ -328,9 +328,7 @@ const struct LauncherTheme Launcher_NordicTheme = {
|
||||
|
||||
CC_NOINLINE static void ParseColor(const char* key, BitmapCol* color) {
|
||||
cc_uint8 rgb[3];
|
||||
cc_string value;
|
||||
if (!Options_UNSAFE_Get(key, &value)) return;
|
||||
if (!PackedCol_TryParseHex(&value, rgb)) return;
|
||||
if (!Options_GetColor(key, rgb)) return;
|
||||
|
||||
*color = BitmapColor_RGB(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Errors.h"
|
||||
#include "Utils.h"
|
||||
#include "Logger.h"
|
||||
#include "PackedCol.h"
|
||||
|
||||
struct StringsBuffer Options;
|
||||
static struct StringsBuffer changedOpts;
|
||||
@ -137,6 +138,19 @@ int Options_GetEnum(const char* key, int defValue, const char* const* names, int
|
||||
return Utils_ParseEnum(&str, defValue, names, namesCount);
|
||||
}
|
||||
|
||||
cc_bool Options_GetColor(const char* key, cc_uint8* rgb) {
|
||||
cc_string value, parts[3];
|
||||
if (!Options_UNSAFE_Get(key, &value)) return false;
|
||||
if (PackedCol_TryParseHex(&value, rgb)) return true;
|
||||
|
||||
/* Try parsing as R,G,B instead */
|
||||
return String_UNSAFE_Split(&value, ',', parts, 3)
|
||||
&& Convert_ParseUInt8(&parts[0], &rgb[0])
|
||||
&& Convert_ParseUInt8(&parts[1], &rgb[1])
|
||||
&& Convert_ParseUInt8(&parts[2], &rgb[2]);
|
||||
}
|
||||
|
||||
|
||||
void Options_SetBool(const char* keyRaw, cc_bool value) {
|
||||
static const cc_string str_true = String_FromConst("True");
|
||||
static const cc_string str_false = String_FromConst("False");
|
||||
|
@ -123,6 +123,9 @@ CC_API float Options_GetFloat(const char* key, float min, float max, float defV
|
||||
/* Returns value of given option as an integer, or defalt value if could not be converted. */
|
||||
/* NOTE: Conversion is done by going through all elements of names, returning index of a match. */
|
||||
CC_API int Options_GetEnum(const char* key, int defValue, const char* const* names, int namesCount);
|
||||
/* Attempts to parse the value of the given option into an RGB (3 byte) colour. */
|
||||
/* Returns whether the option was actually found and could be parsed into a colour. */
|
||||
cc_bool Options_GetColor(const char* key, cc_uint8* rgb);
|
||||
|
||||
/* Sets value of given option to either "true" or "false". */
|
||||
CC_API void Options_SetBool(const char* keyRaw, cc_bool value);
|
||||
|
@ -146,6 +146,13 @@ int String_CaselessEqualsConst(const cc_string* a, const char* b) {
|
||||
|
||||
|
||||
void String_Append(cc_string* str, char c) {
|
||||
/* MSVC in debug mode will initialise all variables on the stack with 0xCC by default */
|
||||
/* So if a string is being passed with CC in all its fields, then it's probably invalid */
|
||||
#if _MSC_VER && _DEBUG
|
||||
if (str->length == 0xCCCC && str->capacity == 0xCCCC)
|
||||
Logger_Abort("String must be initialised before calling String_Append");
|
||||
#endif
|
||||
|
||||
if (str->length == str->capacity) return;
|
||||
str->buffer[str->length++] = c;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user