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:
UnknownShadow200 2023-11-20 19:30:36 +11:00
parent 7bbfd61f63
commit 39b09a9202
7 changed files with 95 additions and 39 deletions

View File

@ -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.

View File

@ -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 = {

View File

@ -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) {

View File

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

View File

@ -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");

View File

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

View File

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