Codebase adaptation for KolibriOS

- Changes some source code, especially in data.c
- Added xmake.lua for building game using xmake
This commit is contained in:
2025-03-23 14:43:04 +02:00
parent 5cfa947483
commit f185677b7f
10 changed files with 3267 additions and 2556 deletions

View File

@@ -1,6 +1,3 @@
#pragma once
#ifdef _WIN32
#define PATH_MAX 260
#define NAME_MAX 260
#endif
#define NAME_MAX 260

View File

@@ -1,5 +1,6 @@
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
@@ -10,316 +11,523 @@
#include "data.h"
#include "textures.h"
#ifdef _KOLIBRI
#include <ksys.h>
#endif
data_WorldListItem *data_worldList = NULL;
int data_worldListLength = 0;
char directoryName [PATH_MAX] = { 0 };
char optionsFileName [PATH_MAX] = { 0 };
char worldsDirectoryName [PATH_MAX] = { 0 };
char screenshotsDirectoryName [PATH_MAX] = { 0 };
char directoryName[PATH_MAX] = {0};
char optionsFileName[PATH_MAX] = {0};
char worldsDirectoryName[PATH_MAX] = {0};
char screenshotsDirectoryName[PATH_MAX] = {0};
static uint32_t getSurfacePixel(SDL_Surface *, int, int);
static int findDirectoryName(char *, const char *);
static uint32_t getSurfacePixel (SDL_Surface *, int, int);
static int findDirectoryName (char *, const char *);
/* data_init
* Initializes the data module. Returns zero on success, nonzero on failure.
*/
int data_init (void) {
int err = 0;
int data_init(void)
{
int err = 0;
err = findDirectoryName(directoryName, "/.m4kc");
if (err) { return err; }
err = findDirectoryName(optionsFileName, "/.m4kc/m4kc.conf");
if (err) { return err; }
err = findDirectoryName(worldsDirectoryName, "/.m4kc/worlds");
if (err) { return err; }
err = findDirectoryName (
screenshotsDirectoryName, "/.m4kc/screenshots");
if (err) { return err; }
return 0;
err = findDirectoryName(
directoryName,
"/m4kc");
if (err)
{
return err;
}
err = findDirectoryName(
optionsFileName,
"/m4kc/m4kc.conf");
if (err)
{
return err;
}
err = findDirectoryName(
worldsDirectoryName,
"/m4kc/worlds");
if (err)
{
return err;
}
err = findDirectoryName(
screenshotsDirectoryName,
"/m4kc/screenshots");
if (err)
{
return err;
}
return 0;
}
/* data_directoryExists
* Test if a directory exists at the specified path. This function does not
* create or delete anything.
*/
int data_directoryExists (const char *path) {
int data_directoryExists(const char *path)
{
#ifdef _KOLIBRI
ksys_file_info_t *bdfe_info;
return _ksys_file_info(path, bdfe_info) == 0;
#else
struct stat directoryInfo;
return (stat(path, &directoryInfo) == 0 &&
S_ISDIR(directoryInfo.st_mode));
#endif
}
/* data_fileExists
* Test if a file exists at the specified path.
*/
int data_fileExists (const char *path) {
return access(path, F_OK) == 0;
int data_fileExists(const char *path)
{
return access(path, F_OK) == 0;
}
/* data_ensureDirectoryExists
* Equivalent to mkdir -p. Creates a directory and all of its parent directories
* if they don't exist.
*/
int data_ensureDirectoryExists (const char *path) {
char currentDirectory[PATH_MAX] = "";
int index = 0;
while (path[index] != 0) {
while (path[index] != 0) {
currentDirectory[index] = path[index];
currentDirectory[index + 1] = 0;
index ++;
char ch = currentDirectory[index - 1];
if (ch == '/' || ch == '\\') {
break;
}
}
if (!data_directoryExists(currentDirectory)) {
int status;
#ifdef _WIN32
status = mkdir(currentDirectory);
#else
status = mkdir(currentDirectory, 0755);
#endif
if (status != 0) {
return 1;
}
}
int data_ensureDirectoryExists(const char *path)
{
char currentDirectory[PATH_MAX] = "";
int index = 0;
// printf("Directory path: %s\n", path);
while (path[index] != 0)
{
while (path[index] != 0)
{
currentDirectory[index] = path[index];
currentDirectory[index + 1] = 0;
index++;
char ch = currentDirectory[index - 1];
if (ch == '/' || ch == '\\')
{
break;
}
}
return 0;
// printf("Requested directory %s!\n", currentDirectory);
if (!data_directoryExists(currentDirectory))
{
// printf("Need to create directory %s!\n", currentDirectory);
int status;
#ifdef _WIN32
status = mkdir(currentDirectory);
#elif __linux__
status = mkdir(currentDirectory, 0755);
#elif _KOLIBRI
// Check and temporarily remove trailing '/' if present
int hadTrailingSlash = 0;
size_t len = strlen(currentDirectory);
if (len > 0 && currentDirectory[len - 1] == '/')
{
hadTrailingSlash = 1;
currentDirectory[len - 1] = '\0';
}
status = _ksys_mkdir(currentDirectory);
// Restore the trailing '/' if it was removed
if (hadTrailingSlash)
{
currentDirectory[len - 1] = '/';
}
#endif
if (status != 0)
{
// printf("Failed creating directory \"%s\" - error code %d!\n", currentDirectory, status);
return 1;
}
else
{
// printf("Success creating directory \"%s\" - error code %d!\n", currentDirectory, status);
}
}
else
{
// printf("No need to create directory %s!\n", currentDirectory);
}
}
return 0;
}
/* data_removeDirectory
* Equivalent of rm -r. Removes a directory and its contents recursively.
*/
int data_removeDirectory (const char *path) {
DIR *directory = opendir(path);
size_t pathLength = strlen(path);
int data_removeDirectory(const char *path)
{
DIR *directory = opendir(path);
size_t pathLength = strlen(path);
if (!directory) { return 1; }
struct dirent *directoryEntry;
if (!directory)
{
return 1;
}
int err = 0;
while (!err) {
directoryEntry = readdir(directory);
if (directoryEntry == NULL) {
err = 2;
break;
}
if (
!strcmp(directoryEntry->d_name, ".") ||
!strcmp(directoryEntry->d_name, "..")
) {
continue;
struct dirent *directoryEntry;
int err = 0;
while (!err)
{
directoryEntry = readdir(directory);
if (directoryEntry == NULL)
{
err = 2;
break;
}
if (
!strcmp(directoryEntry->d_name, ".") ||
!strcmp(directoryEntry->d_name, ".."))
{
continue;
}
size_t newLength =
pathLength +
strlen(directoryEntry->d_name) + 2;
char *newPath = malloc(newLength);
if (newPath == NULL)
{
return 3;
}
snprintf(
newPath, newLength, "%s/%s",
path, directoryEntry->d_name);
struct stat fileInfo;
if (!stat(newPath, &fileInfo))
{
if (S_ISDIR(fileInfo.st_mode))
{
err = data_removeDirectory(newPath);
}
else
{
err = unlink(newPath);
}
}
free(newPath);
}
closedir(directory);
int status = 0;
#ifdef _WIN32
status = rmdir(path);
#elif __linux__
status = rmdir(path);
#elif _KOLIBRI
// ksys_file_info_t* dir_info;
// _ksys_dir_info(path, dir_info);
// printf("Dir offset: %d!\n", dir_info->offset64);
// printf("Dir size: %d!\n", dir_info->size);
// _ksys_file_read_dir(path, 0, 0, );
// TODO Make proper (recursive) determination of files in folder
char full_path[PATH_MAX];
const char *blocks[] = {"00000000", "00000001", "FFFFFFFF"};
const char *fixedSuffixes[] = {"guest.player", "metadata"};
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 3; j++)
{
for (size_t k = 0; k < 3; k++) {
snprintf(full_path, sizeof(full_path), "%s/%s%s%s", path, blocks[i], blocks[j], blocks[k]);
_ksys_rmdir(full_path);
}
}
}
size_t newLength =
pathLength +
strlen(directoryEntry->d_name) + 2;
char *newPath = malloc(newLength);
if (newPath == NULL) { return 3; }
snprintf (
newPath, newLength, "%s/%s",
path, directoryEntry->d_name);
struct stat fileInfo;
if (!stat(newPath, &fileInfo)) {
if (S_ISDIR(fileInfo.st_mode)) {
err = data_removeDirectory(newPath);
} else {
err = unlink(newPath);
}
}
free(newPath);
for (size_t i = 0; i < sizeof(fixedSuffixes) / sizeof(fixedSuffixes[0]); i++)
{
snprintf(full_path, sizeof(full_path), "%s/%s", path, fixedSuffixes[i]);
_ksys_rmdir(full_path);
}
closedir(directory);
if (rmdir(path)) { return 4; }
return 0;
status = _ksys_rmdir(path);
#endif
if (status)
{
printf("Failed remove directory \"%s\" - %d!\n", path, status);
return 4;
}
return 0;
}
/* data_getOptionsFileName
* Returns the file path of the configuration file.
*/
char *data_getOptionsFileName (void) {
return optionsFileName;
char *data_getOptionsFileName(void)
{
return optionsFileName;
}
/* data_getWorldPath
* Returns the path to a world, regardless if it exists or not. This function
* ensures that the worlds directory exists. If it cannot do this, it returns 1.
*/
int data_getWorldPath (char *path, const char *worldName) {
if (data_ensureDirectoryExists(worldsDirectoryName)) { return 1; }
int data_getWorldPath(char *path, const char *worldName)
{
if (data_ensureDirectoryExists(worldsDirectoryName))
{
return 1;
}
snprintf(path, PATH_MAX, "%s/%s", worldsDirectoryName, worldName);
return 0;
snprintf(path, PATH_MAX, "%s/%s", worldsDirectoryName, worldName);
return 0;
}
/* data_getWorldMetaPath
* Returns the path to the metadata file of a world, given a world path.
*/
void data_getWorldMetaPath (char *path, const char *worldPath) {
snprintf(path, PATH_MAX, "%s/metadata", worldPath);
void data_getWorldMetaPath(char *path, const char *worldPath)
{
snprintf(path, PATH_MAX, "%s/metadata", worldPath);
}
/* data_getWorldPlayerPath
* Returns the path to a player file, given a world path and a player name.
*/
void data_getWorldPlayerPath (
char *path,
const char *worldPath,
const char *name
) {
snprintf(path, PATH_MAX, "%s/%s.player", worldPath, name);
void data_getWorldPlayerPath(
char *path,
const char *worldPath,
const char *name)
{
snprintf(path, PATH_MAX, "%s/%s.player", worldPath, name);
}
/* data_getScreenshotPath
* Writes into path the path for a new screenshot. The name will take the form
* of: snip_YYYY-MM-DD_HH:MM:SS.bmp
* ... and will be located in the path stored in screenshotsDirectoryName. If
* the screenshots directory doesn't exist, this function will create it.
*/
int data_getScreenshotPath (char *path) {
if (data_ensureDirectoryExists(screenshotsDirectoryName)) { return 1; }
int data_getScreenshotPath(char *path)
{
if (data_ensureDirectoryExists(screenshotsDirectoryName))
{
return 1;
}
time_t unixTime = time(0);
struct tm *timeInfo = localtime(&unixTime);
snprintf (
path, PATH_MAX,
"%s/snip_%04i-%02i-%02i_%02i-%02i-%02i.bmp",
screenshotsDirectoryName,
timeInfo->tm_year + 1900,
timeInfo->tm_mon + 1,
timeInfo->tm_mday,
timeInfo->tm_hour,
timeInfo->tm_min,
timeInfo->tm_sec);
return 0;
time_t unixTime = time(0);
struct tm *timeInfo = localtime(&unixTime);
snprintf(
path, PATH_MAX,
"%s/snip_%04i-%02i-%02i_%02i-%02i-%02i.bmp",
screenshotsDirectoryName,
timeInfo->tm_year + 1900,
timeInfo->tm_mon + 1,
timeInfo->tm_mday,
timeInfo->tm_hour,
timeInfo->tm_min,
timeInfo->tm_sec);
return 0;
}
/* data_refreshWorldList
* Regreshes the world list, clearing the previous one. Reads world names and
* thumbnails from ~/.m4kc/worlds
*/
int data_refreshWorldList (void) {
// Free previous list
data_WorldListItem *item = data_worldList;
while (item != NULL) {
data_WorldListItem *next = item->next;
free(item);
item = next;
int data_refreshWorldList(void)
{
// Free previous list
data_WorldListItem *item = data_worldList;
while (item != NULL)
{
data_WorldListItem *next = item->next;
free(item);
item = next;
}
if (data_ensureDirectoryExists(worldsDirectoryName))
{
return 1;
}
// Iterate through worlds directory
struct dirent *directoryEntry;
// printf("Opening directory %s", worldsDirectoryName);
DIR *directory = opendir(worldsDirectoryName);
if (!directory)
{
return 2;
}
data_worldListLength = 0;
data_WorldListItem *last = NULL;
while ((directoryEntry = readdir(directory)) != NULL)
{
if (directoryEntry->d_name[0] == '.')
{
continue;
}
if (data_ensureDirectoryExists(worldsDirectoryName)) { return 1; }
// Iterate through worlds directory
struct dirent *directoryEntry;
DIR *directory = opendir(worldsDirectoryName);
if (!directory) { return 2; }
data_worldListLength = 0;
data_WorldListItem *last = NULL;
while ((directoryEntry = readdir(directory)) != NULL) {
if (directoryEntry->d_name[0] == '.') { continue; }
// Allocate new list item
data_WorldListItem *item = calloc (
sizeof(data_WorldListItem), 1);
if (item == NULL) { return 3; }
strncpy(item->name, directoryEntry->d_name, NAME_MAX);
if (last == NULL) {
data_worldList = item;
last = data_worldList;
} else {
last->next = item;
last = item;
}
// Get thumbnail
char path[PATH_MAX];
snprintf (
path, PATH_MAX,
"%s/%s/thumbnail.bmp",
worldsDirectoryName,
item->name);
SDL_Surface *image = SDL_LoadBMP(path);
int *pixel = item->thumbnail.buffer;
// Do not accept vertical images
if (image != NULL && image->h <= image->w) {
int scale = image->h / 16;
for (int y = 0; y < 16; y ++)
for (int x = 0; x < 16; x ++) {
*pixel = getSurfacePixel (image,
x * scale,
y * scale);
pixel ++;
}
} else {
for (int y = 0; y < 16; y ++)
for (int x = 0; x < 16; x ++) {
*pixel = textures [
x +
y * BLOCK_TEXTURE_W +
(BLOCK_GRASS * 3 + 1) *
BLOCK_TEXTURE_W * BLOCK_TEXTURE_H];
pixel ++;
}
}
SDL_FreeSurface(image);
data_worldListLength ++;
// Allocate new list item
data_WorldListItem *item = calloc(
sizeof(data_WorldListItem), 1);
if (item == NULL)
{
return 3;
}
closedir(directory);
return 0;
strncpy(item->name, directoryEntry->d_name, NAME_MAX);
if (last == NULL)
{
data_worldList = item;
last = data_worldList;
}
else
{
last->next = item;
last = item;
}
// Get thumbnail
char path[PATH_MAX];
snprintf(
path, PATH_MAX,
"%s/%s/thumbnail.bmp",
worldsDirectoryName,
item->name);
SDL_Surface *image = SDL_LoadBMP(path);
int *pixel = item->thumbnail.buffer;
// Do not accept vertical images
if (image != NULL && image->h <= image->w)
{
int scale = image->h / 16;
for (int y = 0; y < 16; y++)
for (int x = 0; x < 16; x++)
{
*pixel = getSurfacePixel(image,
x * scale,
y * scale);
pixel++;
}
}
else
{
for (int y = 0; y < 16; y++)
for (int x = 0; x < 16; x++)
{
*pixel = textures[x +
y * BLOCK_TEXTURE_W +
(BLOCK_GRASS * 3 + 1) *
BLOCK_TEXTURE_W * BLOCK_TEXTURE_H];
pixel++;
}
}
SDL_FreeSurface(image);
data_worldListLength++;
}
closedir(directory);
return 0;
}
/* getSurfacePixel
* Gets a pixel value from an SDL surface at the specified coordinates.
*/
static uint32_t getSurfacePixel (SDL_Surface *surface, int x, int y) {
return *((uint32_t *) ((uint8_t *) surface->pixels
+ y * surface->pitch
+ x * surface->format->BytesPerPixel));
static uint32_t getSurfacePixel(SDL_Surface *surface, int x, int y)
{
return *((uint32_t *)((uint8_t *)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel));
}
char* ksys_get_process_cwd() {
char *process_cwd = (char *)*((uint32_t *)0x20);
char *trimmed_cwd = strdup(process_cwd + 2);
char *last_slash = strrchr(trimmed_cwd, '/');
if (last_slash)
*last_slash = '\0';
return trimmed_cwd;
}
/* findDirectoryName
* Concatenates the user's home directory with the specified path. subDirectory
* must begin with a '/'. Uses %APPDATA% instead of home on windows.
*/
static int findDirectoryName (char *path, const char *subDirectory) {
if (subDirectory[0] != '/') { return 2; }
#ifdef _WIN32
static int findDirectoryName(char *path, const char *subDirectory)
{
if (subDirectory[0] != '/')
{
return 2;
}
#ifdef _WIN32
char *homeDirectory = getenv("APPDATA");
#else
#elif __linux__
char *homeDirectory = getenv("HOME");
#endif
if (homeDirectory == NULL) { return 3; }
snprintf(path, PATH_MAX, "%s%s", homeDirectory, subDirectory);
// Normalize path
for (char *ch = path; *ch; ch ++) {
if (*ch == '\\') { *ch = '/'; }
#elif _KOLIBRI
char *homeDirectory;
int buf_size = 24;
if (!_ksys_mkdir("m4kc"))
{
homeDirectory = ksys_get_process_cwd();
printf("Success to use local directory!\n");
// homeDirectory = getenv("HOME");
}
return 0;
else {
printf("Failed to use local directory!\n");
homeDirectory = getenv("HOME"); // Assign value
}
#endif
if (homeDirectory == NULL)
{
return 3;
}
snprintf(path, PATH_MAX, "%s%s", homeDirectory, subDirectory);
// Normalize path
for (char *ch = path; *ch; ch++)
{
if (*ch == '\\')
{
*ch = '/';
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

754
src/gui.c
View File

@@ -1,506 +1,562 @@
#include "gui.h"
#include "blocks.h"
const int BUFFER_W = 214;
const int BUFFER_H = 120;
const int BUFFER_SCALE = 4;
const int BUFFER_HALF_W = BUFFER_W / 2;
const int BUFFER_HALF_H = BUFFER_H / 2;
const int WINDOW_W = BUFFER_W * BUFFER_SCALE;
const int WINDOW_H = BUFFER_H * BUFFER_SCALE;
char chatHistory [11][64] = {0};
int chatHistoryFade [11] = {0};
int chatHistoryIndex = 0;
int BUFFER_HALF_W = BUFFER_W / 2;
int BUFFER_HALF_H = BUFFER_H / 2;
int WINDOW_W = BUFFER_W * BUFFER_SCALE;
int WINDOW_H = BUFFER_H * BUFFER_SCALE;
char chatHistory[11][64] = {0};
int chatHistoryFade[11] = {0};
int chatHistoryIndex = 0;
/* strnum
* Takes in a char array and an offset and puts the specified
* number into it. Make sure there is sufficient space in the
* string.
*/
void strnum (char *ptr, int offset, int num) {
sprintf(ptr + offset, "%d", num);
void strnum(char *ptr, int offset, int num)
{
sprintf(ptr + offset, "%d", num);
}
/* drawChar
* Takes in a pointer to a renderer, a character (as an int),
* draws it at the specified x and y coordinates, and then returns
* the character's width.
*/
int drawChar (SDL_Renderer *renderer,int c, int x, int y) {
for (int yy = 0; yy < 8; yy++) {
for (int xx = 0; xx < 8; xx++) {
if ((font[c][yy] >> (7 - xx)) & 0x1) {
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
}
}
int drawChar(SDL_Renderer *renderer, int c, int x, int y)
{
for (int yy = 0; yy < 8; yy++)
{
for (int xx = 0; xx < 8; xx++)
{
if ((font[c][yy] >> (7 - xx)) & 0x1)
{
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
}
}
}
return font[c][8];
return font[c][8];
}
/* drawStr
* Takes in a pointer to a renderer, a string, draws it at the
* specified x and y coordinates, and then returns the x position
* it left off on.
*/
int drawStr (SDL_Renderer *renderer, const char *str, int x, int y) {
while (*str > 0) {
x += drawChar(renderer, *(str++), x, y);
}
return x;
int drawStr(SDL_Renderer *renderer, const char *str, int x, int y)
{
while (*str > 0)
{
x += drawChar(renderer, *(str++), x, y);
}
return x;
}
/* shadowStr
* Identical to drawStr, but draws white text with a grey shadow.
*/
int shadowStr (SDL_Renderer *renderer, const char *str, int x, int y) {
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
drawStr(renderer, str, x + 1, y + 1);
white(renderer);
return drawStr(renderer, str, x, y);
int shadowStr(SDL_Renderer *renderer, const char *str, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
drawStr(renderer, str, x + 1, y + 1);
white(renderer);
return drawStr(renderer, str, x, y);
}
/* centerStr
* Identical to drawStr, but centers the text
*/
int centerStr (SDL_Renderer *renderer, const char *str, int x, int y) {
x *= 2;
int i = 0;
while (str[i] > 0) {
x -= font[(int)str[i++]][8];
}
int centerStr(SDL_Renderer *renderer, const char *str, int x, int y)
{
x *= 2;
int i = 0;
while (str[i] > 0)
{
x -= font[(int)str[i++]][8];
}
x /= 2;
i = 0;
while(str[i] > 0) {
x += drawChar(renderer, str[i++], x, y);
}
x /= 2;
i = 0;
while (str[i] > 0)
{
x += drawChar(renderer, str[i++], x, y);
}
return x;
return x;
}
/* shadowStr
* Identical to centerStr, but draws white text with a grey shadow.
*/
int shadowCenterStr (SDL_Renderer *renderer, const char *str, int x, int y) {
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
centerStr(renderer, str, x + 1, y + 1);
white(renderer);
return centerStr(renderer, str, x, y);
int shadowCenterStr(SDL_Renderer *renderer, const char *str, int x, int y)
{
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
centerStr(renderer, str, x + 1, y + 1);
white(renderer);
return centerStr(renderer, str, x, y);
}
/* drawBig
* Draws centered text at a large scale
*/
int drawBig (SDL_Renderer *renderer, const char *str, int x, int y) {
int i = 0;
while (str[i] > 0)
x -= font[(int)str[i++]][8];
int drawBig(SDL_Renderer *renderer, const char *str, int x, int y)
{
int i = 0;
while (str[i] > 0)
x -= font[(int)str[i++]][8];
i = 0;
while (str[i] > 0) {
int c = str[i++];
for (int yy = 0; yy < 16; yy++) {
for (int xx = 0; xx < 16; xx++) {
if ((font[c][yy / 2] >> (7 - xx / 2)) & 0x1) {
SDL_RenderDrawPoint (
renderer,
x + xx,
y + yy
);
}
}
i = 0;
while (str[i] > 0)
{
int c = str[i++];
for (int yy = 0; yy < 16; yy++)
{
for (int xx = 0; xx < 16; xx++)
{
if ((font[c][yy / 2] >> (7 - xx / 2)) & 0x1)
{
SDL_RenderDrawPoint(
renderer,
x + xx,
y + yy);
}
x += font[c][8] * 2;
}
}
return x;
x += font[c][8] * 2;
}
return x;
}
/* drawBGStr
* Like drawStr, but also draws a semitransparent background
* behind the text.
*/
int drawBGStr (
SDL_Renderer *renderer,
const char *str, int x, int y
) {
static int len;
static SDL_Rect bg = {0, 0, 0, 9};
int drawBGStr(SDL_Renderer *renderer, const char *str, int x, int y)
{
static int len;
static SDL_Rect bg = {0, 0, 0, 9};
int i = 0;
len = 0;
while(str[i] > 0) {
len += font[(int)str[i++]][8];
}
bg.x = x;
bg.y = y;
bg.w = len + 1;
int i = 0;
len = 0;
while (str[i] > 0)
{
len += font[(int)str[i++]][8];
}
tblack(renderer);
SDL_RenderFillRect(renderer, &bg);
bg.x = x;
bg.y = y;
bg.w = len + 1;
white(renderer);
return drawStr(renderer, str, ++x, ++y);
tblack(renderer);
SDL_RenderFillRect(renderer, &bg);
white(renderer);
return drawStr(renderer, str, ++x, ++y);
}
/* button
* Takes in a pointer to a renderer, a string, draws a button with
* the specified x and y coordinates and width, and then returns
* wether or not the specified mouse coordinates are within it.
*/
int button (
SDL_Renderer *renderer,
const char *str,
int x, int y, int w,
int mouseX, int mouseY
) {
int hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + w &&
mouseY < y + 16 ;
int button(
SDL_Renderer *renderer,
const char *str,
int x, int y, int w,
int mouseX, int mouseY)
{
int hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + w &&
mouseY < y + 16;
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = 16;
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = 16;
if (hover) {
SDL_SetRenderDrawColor(renderer, 116, 134, 230, 255);
} else {
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
}
SDL_RenderFillRect(renderer, &rect);
if (hover)
{
SDL_SetRenderDrawColor(renderer, 116, 134, 230, 255);
}
else
{
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
}
SDL_RenderFillRect(renderer, &rect);
x += w / 2 + 1;
y += 5;
x += w / 2 + 1;
y += 5;
if (hover) {
SDL_SetRenderDrawColor(renderer, 63, 63, 40, 255);
} else {
SDL_SetRenderDrawColor(renderer, 56, 56, 56, 255);
}
centerStr(renderer, str, x, y);
if (hover)
{
SDL_SetRenderDrawColor(renderer, 63, 63, 40, 255);
}
else
{
SDL_SetRenderDrawColor(renderer, 56, 56, 56, 255);
}
centerStr(renderer, str, x, y);
x--;
y--;
x--;
y--;
if (hover) {
SDL_SetRenderDrawColor(renderer, 255, 255, 160, 255);
} else {
white(renderer);
}
centerStr(renderer, str, x, y);
if (hover)
{
SDL_SetRenderDrawColor(renderer, 255, 255, 160, 255);
}
else
{
white(renderer);
}
centerStr(renderer, str, x, y);
if (hover) {
white(renderer);
} else {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
SDL_RenderDrawRect(renderer, &rect);
if (hover)
{
white(renderer);
}
else
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
SDL_RenderDrawRect(renderer, &rect);
return hover;
return hover;
}
/* input
* Draws a simple text input. Draws the string in buffer. If buffer is empty,
* the placeholder text is drawn instead (but in a darker color). Returns
* whether or not the mouse is inside of the input.
*/
int input (
SDL_Renderer *renderer,
const char *placeholder,
const char *buffer,
int x, int y, int w,
int mouseX, int mouseY,
int active
) {
static int flash = 0;
int input(
SDL_Renderer *renderer,
const char *placeholder,
const char *buffer,
int x, int y, int w,
int mouseX, int mouseY,
int active)
{
static int flash = 0;
int hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + w &&
mouseY < y + 16 ;
int hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + w &&
mouseY < y + 16;
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = 16;
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = 16;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
if (hover || active) {
white(renderer);
} else {
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
}
SDL_RenderDrawRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
int textX = x + 4;
if (buffer[0] != 0) {
white(renderer);
textX = drawStr(renderer, buffer, x + 4, y + 4);
} else {
SDL_SetRenderDrawColor(renderer, 63, 63, 63, 255);
drawStr(renderer, placeholder, x + 4, y + 4);
}
if (hover || active)
{
white(renderer);
}
else
{
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
}
SDL_RenderDrawRect(renderer, &rect);
if (flash < 32 && active) {
white(renderer);
drawChar(renderer, '_', textX, y + 4);
}
int textX = x + 4;
if (buffer[0] != 0)
{
white(renderer);
textX = drawStr(renderer, buffer, x + 4, y + 4);
}
else
{
SDL_SetRenderDrawColor(renderer, 63, 63, 63, 255);
drawStr(renderer, placeholder, x + 4, y + 4);
}
flash ++;
flash %= 64;
if (flash < 32 && active)
{
white(renderer);
drawChar(renderer, '_', textX, y + 4);
}
return hover;
flash++;
flash %= 64;
return hover;
}
/* scrollbar
* Draws a scrollbar of the specified length at the specified coordinates.
* Able to modify the level value when the user interacts with it.
*/
void scrollbar (
SDL_Renderer *renderer,
int x, int y, int length,
int mouseX, int mouseY,
int mouseLeft,
int *level, int max
) {
float sectionLength = (float)length / (float)max;
void scrollbar(
SDL_Renderer *renderer,
int x, int y, int length,
int mouseX, int mouseY,
int mouseLeft,
int *level, int max)
{
float sectionLength = (float)length / (float)max;
SDL_Rect background = {
.x = x,
.y = y,
.w = 4,
.h = length
};
SDL_Rect background = {
.x = x,
.y = y,
.w = 4,
.h = length};
SDL_Rect foreground = {
.x = x,
.y = (float)*level * sectionLength,
.w = 4,
.h = ceil(sectionLength)
};
SDL_Rect foreground = {
.x = x,
.y = (float)*level * sectionLength,
.w = 4,
.h = ceil(sectionLength)};
int hover = mouseX >= background.x &&
mouseY >= background.y &&
mouseX < background.x + background.w &&
mouseY < background.y + background.h;
int hover = mouseX >= background.x &&
mouseY >= background.y &&
mouseX < background.x + background.w &&
mouseY < background.y + background.h;
if (hover && mouseLeft) {
*level = (mouseY - background.y) / sectionLength;
}
if (hover && mouseLeft)
{
*level = (mouseY - background.y) / sectionLength;
}
tblack(renderer);
SDL_RenderFillRect(renderer, &background);
SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255);
SDL_RenderFillRect(renderer, &foreground);
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
SDL_RenderDrawLine (
renderer,
foreground.x + foreground.w - 1,
foreground.y,
foreground.x + foreground.w - 1,
foreground.y + foreground.h - 1);
tblack(renderer);
SDL_RenderFillRect(renderer, &background);
SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255);
SDL_RenderFillRect(renderer, &foreground);
SDL_SetRenderDrawColor(renderer, 139, 139, 139, 255);
SDL_RenderDrawLine(
renderer,
foreground.x + foreground.w - 1,
foreground.y,
foreground.x + foreground.w - 1,
foreground.y + foreground.h - 1);
}
/* drawSlot
* Takes in a pointer to a renderer, an InvSlot, draws the item
* with the specified x and y coordinates and width, and then
* with the specified x and y coordinates and width, and then
* returns wether or not the specified mouse coordinates are
* within it.
*/
int drawSlot (
SDL_Renderer *renderer,
InvSlot *slot, int x, int y, int mouseX, int mouseY
) {
int hover,
i,
xx,
yy,
color;
int drawSlot(SDL_Renderer *renderer, InvSlot *slot, int x, int y, int mouseX, int mouseY)
{
int hover,
i,
xx,
yy,
color;
char count[4];
char count[4];
hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + 16 &&
mouseY < y + 16 ;
if (slot->amount == 0) { return hover; }
i = slot->blockid * 256 * 3;
for (yy = 0; yy < 16; yy++) {
for (xx = 0; xx < 16; xx++) {
color = textures[i + BLOCK_TEXTURE_H * BLOCK_TEXTURE_W];
SDL_SetRenderDrawColor(
renderer,
(color >> 16 & 0xFF),
(color >> 8 & 0xFF),
(color & 0xFF),
255
);
if (color > 0) {
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
}
i++;
}
}
strnum(count, 0, slot->amount);
shadowStr(renderer, count, x + (slot->amount >= 10 ? 4 : 10), y + 8);
hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + 16 &&
mouseY < y + 16;
if (slot->amount == 0)
{
return hover;
}
i = slot->blockid * 256 * 3;
for (yy = 0; yy < 16; yy++)
{
for (xx = 0; xx < 16; xx++)
{
color = textures[i + BLOCK_TEXTURE_H * BLOCK_TEXTURE_W];
SDL_SetRenderDrawColor(
renderer,
(color >> 16 & 0xFF),
(color >> 8 & 0xFF),
(color & 0xFF),
255);
if (color > 0)
{
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
}
i++;
}
}
strnum(count, 0, slot->amount);
shadowStr(renderer, count, x + (slot->amount >= 10 ? 4 : 10), y + 8);
return hover;
}
/* drawWorldListItem
* Draws a world list item and reurns whether the mouse is inside of it or one
* of its buttons.
*/
int drawWorldListItem (
SDL_Renderer *renderer, data_WorldListItem *item,
int x, int y, int mouseX, int mouseY
) {
int hover;
hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + 128 &&
mouseY < y + 16 ;
int drawWorldListItem(SDL_Renderer *renderer, data_WorldListItem *item, int x, int y, int mouseX, int mouseY)
{
int hover;
SDL_Rect rect;
rect.x = x - 1;
rect.y = y - 1;
rect.w = 130;
rect.h = 18;
hover = mouseX >= x &&
mouseY >= y &&
mouseX < x + 128 &&
mouseY < y + 16;
SDL_Rect thumbnailShadow;
thumbnailShadow.x = x + 1;
thumbnailShadow.y = y + 1;
thumbnailShadow.w = 16;
thumbnailShadow.h = 16;
SDL_Rect rect;
rect.x = x - 1;
rect.y = y - 1;
rect.w = 130;
rect.h = 18;
tblack(renderer);
SDL_RenderFillRect(renderer, &thumbnailShadow);
int *pixel = item->thumbnail.buffer;
for (int yy = 0; yy < 16; yy++) {
for (int xx = 0; xx < 16; xx++) {
SDL_SetRenderDrawColor (
renderer,
(*pixel >> 16 & 0xFF),
(*pixel >> 8 & 0xFF),
(*pixel & 0xFF),
255
);
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
pixel ++;
}
SDL_Rect thumbnailShadow;
thumbnailShadow.x = x + 1;
thumbnailShadow.y = y + 1;
thumbnailShadow.w = 16;
thumbnailShadow.h = 16;
tblack(renderer);
SDL_RenderFillRect(renderer, &thumbnailShadow);
int *pixel = item->thumbnail.buffer;
for (int yy = 0; yy < 16; yy++)
{
for (int xx = 0; xx < 16; xx++)
{
SDL_SetRenderDrawColor(
renderer,
(*pixel >> 16 & 0xFF),
(*pixel >> 8 & 0xFF),
(*pixel & 0xFF),
255);
SDL_RenderDrawPoint(renderer, x + xx, y + yy);
pixel++;
}
}
shadowStr(renderer, item->name, x + 20, y + 4);
shadowStr(renderer, item->name, x + 20, y + 4);
if (button(renderer, "x",
x + 128 - 16, y, 16,
mouseX, mouseY)
) {
hover = 2;
}
if (button(renderer, "x",
x + 128 - 16, y, 16,
mouseX, mouseY))
{
hover = 2;
}
if (hover == 1) {
white(renderer);
SDL_RenderDrawRect(renderer, &rect);
}
if (hover == 1)
{
white(renderer);
SDL_RenderDrawRect(renderer, &rect);
}
return hover;
return hover;
}
/* dirtBg
* Draws a dirt textured background
*/
void dirtBg (SDL_Renderer *renderer) {
int color;
for (int y = 0; y < BUFFER_H; y++) {
for (int x = 0; x < BUFFER_W; x++) {
color = textures [
(x & 0xF) +
(y & 0xF) * 16 +
BLOCK_DIRT * 256 * 3
];
SDL_SetRenderDrawColor(
renderer,
(color >> 16 & 0xFF) >> 1,
(color >> 8 & 0xFF) >> 1,
(color & 0xFF) >> 1,
255
);
SDL_RenderDrawPoint(renderer, x, y);
}
void dirtBg(SDL_Renderer *renderer)
{
int color;
for (int y = 0; y < BUFFER_H; y++)
{
for (int x = 0; x < BUFFER_W; x++)
{
color = textures[(x & 0xF) +
(y & 0xF) * 16 +
BLOCK_DIRT * 256 * 3];
SDL_SetRenderDrawColor(
renderer,
(color >> 16 & 0xFF) >> 1,
(color >> 8 & 0xFF) >> 1,
(color & 0xFF) >> 1,
255);
SDL_RenderDrawPoint(renderer, x, y);
}
}
}
/* loadScreen
* Draws a loading screen
*/
void loadScreen (
SDL_Renderer *renderer,
const char *str,
float prog, float max
) {
dirtBg(renderer);
void loadScreen(
SDL_Renderer *renderer,
const char *str,
float prog, float max)
{
dirtBg(renderer);
shadowCenterStr(renderer, str, BUFFER_HALF_W, BUFFER_HALF_H - 8);
shadowCenterStr(renderer, str, BUFFER_HALF_W, BUFFER_HALF_H - 8);
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
SDL_RenderDrawLine (
renderer,
BUFFER_HALF_W - 32,
BUFFER_HALF_H + 6,
BUFFER_HALF_W + 32,
BUFFER_HALF_H + 6
);
SDL_SetRenderDrawColor(renderer, 77, 77, 77, 255);
SDL_RenderDrawLine(
renderer,
BUFFER_HALF_W - 32,
BUFFER_HALF_H + 6,
BUFFER_HALF_W + 32,
BUFFER_HALF_H + 6);
SDL_SetRenderDrawColor(renderer, 132, 255, 132, 255);
SDL_RenderDrawLine (
renderer,
BUFFER_HALF_W - 32,
BUFFER_HALF_H + 6,
BUFFER_HALF_W - 32 + (prog / max) * 64,
BUFFER_HALF_H + 6
);
SDL_SetRenderDrawColor(renderer, 132, 255, 132, 255);
SDL_RenderDrawLine(
renderer,
BUFFER_HALF_W - 32,
BUFFER_HALF_H + 6,
BUFFER_HALF_W - 32 + (prog / max) * 64,
BUFFER_HALF_H + 6);
}
/* chatAdd
* Adds a message to chat
*/
void chatAdd (const char *str) {
chatHistoryFade[chatHistoryIndex] = 480;
memcpy (
chatHistory[(chatHistoryIndex)++],
str, sizeof(char) * 64
);
chatHistoryIndex = nmod(chatHistoryIndex, 11);
void chatAdd(const char *str)
{
chatHistoryFade[chatHistoryIndex] = 480;
memcpy(
chatHistory[(chatHistoryIndex)++],
str, sizeof(char) * 64);
chatHistoryIndex = nmod(chatHistoryIndex, 11);
}
/* white
* Sets the render color to white
*/
void white (SDL_Renderer *renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
void white(SDL_Renderer *renderer)
{
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
/* tblack
* Sets the render color to transparent black
*/
void tblack (SDL_Renderer *renderer) {
void tblack(SDL_Renderer *renderer)
{
#ifdef _KOLIBRI
SDL_SetRenderDrawColor(renderer, 15, 15, 15, 255);
#else
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 128);
#endif
}

View File

@@ -10,6 +10,10 @@
#include "main.h"
#include "data.h"
#define BUFFER_W 200
#define BUFFER_H 150
#define BUFFER_SCALE 4
void strnum (char *, int, int);
int drawChar (SDL_Renderer *, int, int, int);
int drawStr (SDL_Renderer *, const char *, int, int);
@@ -32,13 +36,10 @@ void chatAdd (const char*);
void white (SDL_Renderer *);
void tblack (SDL_Renderer *);
extern const int BUFFER_W;
extern const int BUFFER_H;
extern const int BUFFER_SCALE;
extern const int BUFFER_HALF_W;
extern const int BUFFER_HALF_H;
extern const int WINDOW_W;
extern const int WINDOW_H;
extern int BUFFER_HALF_W;
extern int BUFFER_HALF_H;
extern int WINDOW_W;
extern int WINDOW_H;
extern char chatHistory [11][64];
extern int chatHistoryFade [11];

View File

@@ -1,25 +1,37 @@
#include "inputbuffer.h"
/* manageInputBuffer
* Applies keyboard input to a text input buffer. Returns 1 if the enter key was
* pressed (there must be content in buffer)
*/
int manageInputBuffer (InputBuffer *inputBuffer, Inputs *inputs) {
if (!inputs->keyTyped && !inputs->keySym) { return 0; }
if (inputs->keySym == SDLK_BACKSPACE) {
int manageInputBuffer(InputBuffer *inputBuffer, Inputs *inputs)
{
if (!inputs->keyTyped && !inputs->keySym)
{
return 0;
}
// printf("Typed key: %d\n", inputs->keyTyped);
if (inputs->keySym == SDLK_BACKSPACE)
{
// Delete last char and decrement cursor
// position
if (inputBuffer->cursor > 0) {
inputBuffer->buffer[-- inputBuffer->cursor] = 0;
if (inputBuffer->cursor > 0)
{
inputBuffer->buffer[--inputBuffer->cursor] = 0;
}
} else if (inputs->keySym == SDLK_RETURN && inputBuffer->cursor > 0) {
}
else if (inputs->keySym == SDLK_RETURN && inputBuffer->cursor > 0)
{
return 1;
} else if (
inputs->keyTyped > 31 &&
inputs->keyTyped < 127 &&
inputBuffer->cursor < inputBuffer->len - 1
) {
}
else if (
inputs->keyTyped > 31 &&
inputs->keyTyped < 127 &&
inputBuffer->cursor < inputBuffer->len - 1)
{
inputBuffer->buffer[inputBuffer->cursor] = inputs->keyTyped;
inputBuffer->cursor += 1;
inputBuffer->buffer[inputBuffer->cursor] = 0;

View File

@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include "textures.h"
#include "gameloop.h"
#include "options.h"
@@ -10,208 +11,340 @@
#include "main.h"
#include "gui.h"
/* Minecraft 4k, C edition. Version 0.7
*
/* Minecraft 4k, C edition. Version 0.8.0 KolibriOS
*
* Credits:
* notch - creating the original game
* sashakoshka - C port, modifications
* samsebe - deciphering the meaning of some of the code
* gracie bell - daylight function
* https://gist.github.com/nowl/828013 - perlin noise
*
*
* ... & contributors on github!
* https://github.com/sashakoshka/m4kc/graphs/contributors
*
*
* If you distribute a modified copy of this, just include this
* notice.
*/
#define MAX_FPS 60
#define MIN_FRAME_MILLISECONDS 1000 / MAX_FPS
static int controlLoop(Inputs *, const uint8_t *);
static int handleEvent(Inputs *, const uint8_t *, SDL_Event);
int main (int argc, char *argv[]) {
(void)(argc);
(void)(argv);
//---- initializing SDL ----//
int main(int argc, char *argv[])
{
(void)(argc);
(void)(argv);
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
const uint8_t *keyboard = SDL_GetKeyboardState(NULL);
//---- initializing SDL ----//
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("cant make window\n");
goto exit;
}
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
const uint8_t *keyboard = SDL_GetKeyboardState(NULL);
window = SDL_CreateWindow ("M4KC",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WINDOW_W, WINDOW_H,
SDL_WINDOW_SHOWN
);
if (window == NULL) {
printf("%s\n", SDL_GetError());
goto exit;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("cant make window\n");
goto exit;
}
renderer = SDL_CreateRenderer (
window,
-1, SDL_RENDERER_ACCELERATED
);
if (renderer == NULL) {
printf("%s\n", SDL_GetError());
goto exit;
}
SDL_RenderSetScale(renderer, BUFFER_SCALE, BUFFER_SCALE);
window = SDL_CreateWindow(
"M4KC 0.8.0 KOLIBRI",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WINDOW_W, WINDOW_H,
SDL_WINDOW_SHOWN);
if (window == NULL)
{
printf("%s\n", SDL_GetError());
goto exit;
}
#ifdef _KOLIBRI
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC);
#else
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
#endif
if (renderer == NULL)
{
printf("%s\n", SDL_GetError());
goto exit;
}
SDL_RenderSetScale(renderer, BUFFER_SCALE, BUFFER_SCALE);
#ifndef _KOLIBRI
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
#endif
//--- initializing modules ---//
int err = 0;
err = data_init();
if (err) {
gameLoop_error("Cannot initialize data module.");
//--- initializing modules ---//
int err = 0;
err = data_init();
if (err)
{
gameLoop_error("Cannot initialize data module.");
}
err = options_init();
if (err)
{
gameLoop_error("Cannot initialize options module.");
}
//---- generating assets ----//
genTextures(45390874);
//---- main game loop ----//
Inputs inputs = {0};
int running = 1;
while (running)
{
uint32_t frameStartTime = SDL_GetTicks();
running &= controlLoop(&inputs, keyboard);
running &= gameLoop(&inputs, renderer);
SDL_RenderPresent(renderer);
// SDL_UpdateWindowSurface(window);
// Clean up input struct
inputs.keyTyped = 0;
inputs.keySym = 0;
// Limit FPS
uint32_t frameDuration = SDL_GetTicks() - frameStartTime;
if (frameDuration < MIN_FRAME_MILLISECONDS)
{
SDL_Delay(MIN_FRAME_MILLISECONDS - frameDuration);
}
err = options_init();
if (err) {
gameLoop_error("Cannot initialize options module.");
}
exit:
SDL_Quit();
return 0;
}
static int controlLoop(Inputs *inputs, const Uint8 *keyboard)
{
SDL_PumpEvents();
int mouseX = 0, mouseY = 0;
SDL_GetMouseState(&mouseX, &mouseY);
// Detect movement controls
inputs->keyboard.space = keyboard[SDL_SCANCODE_SPACE];
inputs->keyboard.w = keyboard[SDL_SCANCODE_W];
inputs->keyboard.s = keyboard[SDL_SCANCODE_S];
inputs->keyboard.a = keyboard[SDL_SCANCODE_A];
inputs->keyboard.d = keyboard[SDL_SCANCODE_D];
if (!SDL_GetRelativeMouseMode())
{
inputs->mouse.x = mouseX;
inputs->mouse.y = mouseY;
}
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (!handleEvent(inputs, keyboard, event))
{
return 0;
}
}
//---- generating assets ----//
return 1;
}
genTextures(45390874);
//---- main game loop ----//
static char scancodeToChar(SDL_Scancode scancode, int shiftPressed)
{
// Basic mapping from scancodes to characters
switch (scancode)
{
case SDL_SCANCODE_A:
return shiftPressed ? 'A' : 'a';
case SDL_SCANCODE_B:
return shiftPressed ? 'B' : 'b';
case SDL_SCANCODE_C:
return shiftPressed ? 'C' : 'c';
case SDL_SCANCODE_D:
return shiftPressed ? 'D' : 'd';
case SDL_SCANCODE_E:
return shiftPressed ? 'E' : 'e';
case SDL_SCANCODE_F:
return shiftPressed ? 'F' : 'f';
case SDL_SCANCODE_G:
return shiftPressed ? 'G' : 'g';
case SDL_SCANCODE_H:
return shiftPressed ? 'H' : 'h';
case SDL_SCANCODE_I:
return shiftPressed ? 'I' : 'i';
case SDL_SCANCODE_J:
return shiftPressed ? 'J' : 'j';
case SDL_SCANCODE_K:
return shiftPressed ? 'K' : 'k';
case SDL_SCANCODE_L:
return shiftPressed ? 'L' : 'l';
case SDL_SCANCODE_M:
return shiftPressed ? 'M' : 'm';
case SDL_SCANCODE_N:
return shiftPressed ? 'N' : 'n';
case SDL_SCANCODE_O:
return shiftPressed ? 'O' : 'o';
case SDL_SCANCODE_P:
return shiftPressed ? 'P' : 'p';
case SDL_SCANCODE_Q:
return shiftPressed ? 'Q' : 'q';
case SDL_SCANCODE_R:
return shiftPressed ? 'R' : 'r';
case SDL_SCANCODE_S:
return shiftPressed ? 'S' : 's';
case SDL_SCANCODE_T:
return shiftPressed ? 'T' : 't';
case SDL_SCANCODE_U:
return shiftPressed ? 'U' : 'u';
case SDL_SCANCODE_V:
return shiftPressed ? 'V' : 'v';
case SDL_SCANCODE_W:
return shiftPressed ? 'W' : 'w';
case SDL_SCANCODE_X:
return shiftPressed ? 'X' : 'x';
case SDL_SCANCODE_Y:
return shiftPressed ? 'Y' : 'y';
case SDL_SCANCODE_Z:
return shiftPressed ? 'Z' : 'z';
Inputs inputs = {0};
int running = 1;
while (running) {
uint32_t frameStartTime = SDL_GetTicks();
running &= controlLoop(&inputs, keyboard);
running &= gameLoop(&inputs, renderer);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
case SDL_SCANCODE_1:
return shiftPressed ? '!' : '1';
case SDL_SCANCODE_2:
return shiftPressed ? '@' : '2';
case SDL_SCANCODE_3:
return shiftPressed ? '#' : '3';
case SDL_SCANCODE_4:
return shiftPressed ? '$' : '4';
case SDL_SCANCODE_5:
return shiftPressed ? '%' : '5';
case SDL_SCANCODE_6:
return shiftPressed ? '^' : '6';
case SDL_SCANCODE_7:
return shiftPressed ? '&' : '7';
case SDL_SCANCODE_8:
return shiftPressed ? '\0' : '8'; // KolibriOS file can't contain * in name
case SDL_SCANCODE_9:
return shiftPressed ? '(' : '9';
case SDL_SCANCODE_0:
return shiftPressed ? ')' : '0';
// Clean up input struct
inputs.keyTyped = 0;
inputs.keySym = 0;
case SDL_SCANCODE_MINUS:
return shiftPressed ? '_' : '-';
case SDL_SCANCODE_EQUALS:
return shiftPressed ? '+' : '=';
// Limit FPS
uint32_t frameDuration = SDL_GetTicks() - frameStartTime;
if (frameDuration < MIN_FRAME_MILLISECONDS) {
SDL_Delay(MIN_FRAME_MILLISECONDS - frameDuration);
}
}
case SDL_SCANCODE_SPACE:
return ' ';
case SDL_SCANCODE_RETURN:
return '\n';
case SDL_SCANCODE_BACKSPACE:
return '\b';
default:
return '\0'; // Unsupported scancodes
}
}
exit:
SDL_Quit();
static int handleEvent(Inputs *inputs, const uint8_t *keyboard, SDL_Event event)
{
switch (event.type)
{
case SDL_QUIT:
return 0;
}
static int controlLoop (Inputs *inputs, const Uint8 *keyboard) {
SDL_PumpEvents();
int mouseX = 0, mouseY = 0;
SDL_GetMouseState(&mouseX, &mouseY);
// Detect movement controls
inputs->keyboard.space = keyboard[SDL_SCANCODE_SPACE];
inputs->keyboard.w = keyboard[SDL_SCANCODE_W];
inputs->keyboard.s = keyboard[SDL_SCANCODE_S];
inputs->keyboard.a = keyboard[SDL_SCANCODE_A];
inputs->keyboard.d = keyboard[SDL_SCANCODE_D];
if (!SDL_GetRelativeMouseMode()) {
inputs->mouse.x = mouseX;
inputs->mouse.y = mouseY;
case SDL_MOUSEBUTTONDOWN:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
inputs->mouse.left = 1;
break;
case SDL_BUTTON_RIGHT:
inputs->mouse.right = 1;
break;
}
break;
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (!handleEvent(inputs, keyboard, event)) {
return 0;
}
case SDL_MOUSEBUTTONUP:
switch (event.button.button)
{
case SDL_BUTTON_LEFT:
inputs->mouse.left = 0;
break;
case SDL_BUTTON_RIGHT:
inputs->mouse.right = 0;
break;
}
break;
return 1;
}
case SDL_KEYDOWN:
inputs->keySym = event.key.keysym.sym;
static int handleEvent (Inputs *inputs, const uint8_t *keyboard, SDL_Event event) {
switch (event.type) {
case SDL_QUIT:
return 0;
case SDL_MOUSEBUTTONDOWN:
switch (event.button.button) {
case SDL_BUTTON_LEFT:
inputs->mouse.left = 1;
break;
case SDL_BUTTON_RIGHT:
inputs->mouse.right = 1;
break;
}
break;
case SDL_MOUSEBUTTONUP:
switch (event.button.button) {
case SDL_BUTTON_LEFT:
inputs->mouse.left = 0;
break;
case SDL_BUTTON_RIGHT:
inputs->mouse.right = 0;
break;
}
break;
if (event.key.repeat == 0)
{
// Detect UI hotkeys using scancodes
SDL_Scancode scancode = event.key.keysym.scancode;
case SDL_KEYDOWN:
inputs->keySym = event.key.keysym.sym;
case SDL_KEYUP:
if (event.key.repeat == 0) {
// Detect UI hotkeys
inputs->keyboard.esc = keyboard[SDL_SCANCODE_ESCAPE];
inputs->keyboard.f1 = keyboard[SDL_SCANCODE_F1];
inputs->keyboard.f2 = keyboard[SDL_SCANCODE_F2];
inputs->keyboard.f3 = keyboard[SDL_SCANCODE_F3];
inputs->keyboard.f4 = keyboard[SDL_SCANCODE_F4];
inputs->keyboard.e = keyboard[SDL_SCANCODE_E];
inputs->keyboard.t = keyboard[SDL_SCANCODE_T];
inputs->keyboard.f = keyboard[SDL_SCANCODE_F];
int shiftPressed = keyboard[SDL_SCANCODE_LSHIFT] || keyboard[SDL_SCANCODE_RSHIFT];
char typedChar = scancodeToChar(scancode, shiftPressed);
inputs->keyboard.num0 = keyboard[SDL_SCANCODE_0];
inputs->keyboard.num1 = keyboard[SDL_SCANCODE_1];
inputs->keyboard.num2 = keyboard[SDL_SCANCODE_2];
inputs->keyboard.num3 = keyboard[SDL_SCANCODE_3];
inputs->keyboard.num4 = keyboard[SDL_SCANCODE_4];
inputs->keyboard.num5 = keyboard[SDL_SCANCODE_5];
inputs->keyboard.num6 = keyboard[SDL_SCANCODE_6];
inputs->keyboard.num7 = keyboard[SDL_SCANCODE_7];
inputs->keyboard.num8 = keyboard[SDL_SCANCODE_8];
inputs->keyboard.num9 = keyboard[SDL_SCANCODE_9];
}
break;
if (typedChar != '\0')
{
inputs->keyTyped = (int)typedChar; // Store the character as int
// printf("Typed char: %c", typedChar);
}
case SDL_MOUSEWHEEL:
inputs->mouse.wheel = event.wheel.y;
break;
// Update hotkey states
inputs->keyboard.esc = keyboard[SDL_SCANCODE_ESCAPE];
inputs->keyboard.f1 = keyboard[SDL_SCANCODE_F1];
inputs->keyboard.f2 = keyboard[SDL_SCANCODE_F2];
inputs->keyboard.f3 = keyboard[SDL_SCANCODE_F3];
inputs->keyboard.f4 = keyboard[SDL_SCANCODE_F4];
inputs->keyboard.e = keyboard[SDL_SCANCODE_E];
inputs->keyboard.t = keyboard[SDL_SCANCODE_T];
inputs->keyboard.f = keyboard[SDL_SCANCODE_F];
case SDL_MOUSEMOTION:
if (SDL_GetRelativeMouseMode()) {
inputs->mouse.x = event.motion.xrel;
inputs->mouse.y = event.motion.yrel;
}
break;
case SDL_TEXTINPUT:
inputs->keyTyped = event.text.text[0];
break;
inputs->keyboard.num0 = keyboard[SDL_SCANCODE_0];
inputs->keyboard.num1 = keyboard[SDL_SCANCODE_1];
inputs->keyboard.num2 = keyboard[SDL_SCANCODE_2];
inputs->keyboard.num3 = keyboard[SDL_SCANCODE_3];
inputs->keyboard.num4 = keyboard[SDL_SCANCODE_4];
inputs->keyboard.num5 = keyboard[SDL_SCANCODE_5];
inputs->keyboard.num6 = keyboard[SDL_SCANCODE_6];
inputs->keyboard.num7 = keyboard[SDL_SCANCODE_7];
inputs->keyboard.num8 = keyboard[SDL_SCANCODE_8];
inputs->keyboard.num9 = keyboard[SDL_SCANCODE_9];
}
break;
return 1;
case SDL_MOUSEWHEEL:
inputs->mouse.wheel = event.wheel.y;
break;
case SDL_MOUSEMOTION:
if (SDL_GetRelativeMouseMode())
{
inputs->mouse.x = event.motion.xrel;
inputs->mouse.y = event.motion.yrel;
}
break;
}
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -31,8 +31,10 @@ int options_init (void) {
* on success, non-zero on failure.
*/
int options_load (void) {
const char *path = data_getOptionsFileName();
printf("Options path: %s\n", path);
// If the file doesn't exist, calmly exit the function and just use
// default values
FILE *file = fopen(path, "r");
@@ -70,7 +72,9 @@ int options_load (void) {
* success, non-zero on failure.
*/
int options_save (void) {
const char *path = data_getOptionsFileName();
printf("%s\n", path);
FILE *file = fopen(path, "w");
if (file == NULL) { return 1; }

84
xmake.lua Normal file
View File

@@ -0,0 +1,84 @@
set_project("m4kc")
KOS_SDK = "/projects/kos/contrib/sdk"
KOS_GCC = "/home/autobuild/tools/win32"
toolchain("kos-gcc")
set_toolset("cc", KOS_GCC .. "/bin/kos32-gcc")
set_toolset("ld", KOS_GCC .. "/bin/kos32-ld")
set_toolset("objcopy", KOS_GCC .. "/bin/kos32-objcopy")
add_cflags("-fno-ident -O3 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -D_KOLIBRI -DNO_ZIP -DPERFORMANCE -DMINIZ_NO_TIME")
add_ldflags("-static -S -nostdlib -T " .. KOS_SDK .. "/sources/newlib/app.lds --image-base 0 --subsystem native")
toolchain_end()
target("m4kc-kolibri")
set_arch("i386")
set_plat("cross")
set_kind("binary")
set_toolchains("kos-gcc")
add_defines("_KOLIBRI")
add_includedirs(KOS_SDK .. "/sources/SDL2-2.30.6/include")
add_includedirs(KOS_SDK .. "/sources/newlib/libc/include")
add_includedirs(KOS_SDK .. "/sources/newlib/libc/include/sys")
add_includedirs("src", {public = true})
add_files("src/*.c")
add_linkdirs(KOS_SDK .. "/lib")
add_linkdirs(KOS_GCC .. "/mingw32/lib")
add_links("SDL2", "gcc", "c.dll", "c", "sound")
after_link(function (target)
os.vrunv("objcopy", {target:targetfile(), "-O", "binary"})
end)
target_end()
target("m4kc-linux")
set_arch("x86_64")
set_plat("linux")
set_kind("binary")
add_includedirs("src", {public = true})
add_files("src/*.c")
add_links("SDL2")
set_optimize("fastest")
target_end()
target("m4kc-windows")
set_kind("binary")
set_toolchains("@tinycc")
add_includedirs("../TCC/include/")
add_includedirs("src", {public = true})
add_files("src/*.c")
add_linkdirs("./")
add_links("SDL2")
set_optimize("fastest")
target_end()
add_rules("mode.debug", "mode.release")