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:
@@ -1,6 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATH_MAX 260
|
||||
#define NAME_MAX 260
|
||||
#endif
|
||||
#define NAME_MAX 260
|
||||
|
||||
638
src/data.c
638
src/data.c
@@ -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;
|
||||
}
|
||||
|
||||
1635
src/gameloop.c
1635
src/gameloop.c
File diff suppressed because it is too large
Load Diff
754
src/gui.c
754
src/gui.c
@@ -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
|
||||
}
|
||||
|
||||
15
src/gui.h
15
src/gui.h
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
449
src/main.c
449
src/main.c
@@ -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;
|
||||
}
|
||||
|
||||
2201
src/menus.c
2201
src/menus.c
File diff suppressed because it is too large
Load Diff
@@ -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
84
xmake.lua
Normal 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")
|
||||
Reference in New Issue
Block a user