405 lines
10 KiB
C++
405 lines
10 KiB
C++
/*
|
|
* Mr. 4th Dimention - Allen Webster
|
|
*
|
|
* 14.11.2015
|
|
*
|
|
* Linux layer for project codename "4ed"
|
|
*
|
|
*/
|
|
|
|
// TOP
|
|
|
|
#ifdef FRED_NOT_PACKAGE
|
|
|
|
#define FRED_INTERNAL 1
|
|
#define FRED_SLOW 1
|
|
|
|
#define FRED_PRINT_DEBUG 1
|
|
#define FRED_PRINT_DEBUG_FILE_LINE 0
|
|
#define FRED_PROFILING 1
|
|
#define FRED_PROFILING_OS 0
|
|
#define FRED_FULL_ERRORS 0
|
|
|
|
#else
|
|
|
|
#define FRED_SLOW 0
|
|
#define FRED_INTERNAL 0
|
|
|
|
#define FRED_PRINT_DEBUG 0
|
|
#define FRED_PRINT_DEBUG_FILE_LINE 0
|
|
#define FRED_PROFILING 0
|
|
#define FRED_PROFILING_OS 0
|
|
#define FRED_FULL_ERRORS 0
|
|
|
|
#endif
|
|
|
|
#define SOFTWARE_RENDER 0
|
|
|
|
#if FRED_INTERNAL == 0
|
|
# undef FRED_PRINT_DEBUG
|
|
# define FRED_PRINT_DEBUG 0
|
|
# undef FRED_PROFILING
|
|
# define FRED_PROFILING 0
|
|
# undef FRED_PROFILING_OS
|
|
# define FRED_PROFILING_OS 0
|
|
#endif
|
|
|
|
#if FRED_PRINT_DEBUG == 0
|
|
# undef FRED_PRINT_DEBUG_FILE_LINE
|
|
# define FRED_PRINT_DEBUG_FILE_LINE 0
|
|
# undef FRED_PRINT_DEBUG_FILE_LINE
|
|
# define FRED_PROFILING_OS 0
|
|
#endif
|
|
|
|
#define FPS 30
|
|
#define frame_useconds (1000000 / FPS)
|
|
|
|
#include "4ed_meta.h"
|
|
|
|
#define FCPP_FORBID_MALLOC
|
|
|
|
#include "4cpp_types.h"
|
|
#define FCPP_STRING_IMPLEMENTATION
|
|
#include "4cpp_string.h"
|
|
|
|
#include "4ed_mem.cpp"
|
|
|
|
#include "4ed_math.cpp"
|
|
#include "4coder_custom.h"
|
|
#include "4ed_system.h"
|
|
#include "4ed.h"
|
|
#include "4ed_rendering.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <SDL/SDL.h>
|
|
#include <GL/gl.h>
|
|
|
|
#include "4ed_internal.h"
|
|
#include "4ed_linux_keyboard.cpp"
|
|
|
|
#define printe(m) printf("%s:%d: %s\n", __FILE__, __LINE__, #m)
|
|
|
|
struct Linux_Vars{
|
|
Application_Memory mem;
|
|
Key_Input_Data input;
|
|
b32 keep_going;
|
|
|
|
Clipboard_Contents clipboard;
|
|
|
|
void *app_code, *custom;
|
|
|
|
System_Functions *system;
|
|
App_Functions app;
|
|
Config_API config_api;
|
|
};
|
|
|
|
Linux_Vars linuxvars;
|
|
|
|
internal
|
|
Sys_Get_Memory_Sig(system_get_memory_){
|
|
void *ptr = 0;
|
|
i32 prot = PROT_READ | PROT_WRITE;
|
|
i32 flags = MAP_PRIVATE | MAP_ANON;
|
|
|
|
#if FRED_INTERNAL
|
|
ptr = mmap(0, size + sizeof(Sys_Bubble), prot, flags, -1, 0);
|
|
|
|
Sys_Bubble *bubble = (Sys_Bubble*)ptr;
|
|
bubble->flags = MEM_BUBBLE_SYS_DEBUG;
|
|
bubble->line_number = line_number;
|
|
bubble->file_name = file_name;
|
|
bubble->size = size;
|
|
//WaitForSingleObject(win32vars.DEBUG_sysmem_lock, INFINITE);
|
|
insert_bubble(&win32vars.internal_bubble, bubble);
|
|
//ReleaseSemaphore(win32vars.DEBUG_sysmem_lock, 1, 0);
|
|
ptr = bubble + 1;
|
|
#else
|
|
ptr = mmap(0, size + sizeof(i32), prot, flags, -1, 0);
|
|
|
|
i32 *size_ptr = (i32*)ptr;
|
|
*size_ptr = size;
|
|
ptr = size_ptr + 1;
|
|
#endif
|
|
|
|
return ptr;
|
|
}
|
|
|
|
#define system_get_memory(size) system_get_memory_(size, __LINE__, __FILE__)
|
|
|
|
internal
|
|
Sys_Free_Memory_Sig(system_free_memory){
|
|
if (block){
|
|
#if FRED_INTERNAL
|
|
Sys_Bubble *bubble = ((Sys_Bubble*)block) - 1;
|
|
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_SYS_DEBUG);
|
|
//WaitForSingleObject(win32vars.DEBUG_sysmem_lock, INFINITE);
|
|
remove_bubble(bubble);
|
|
//ReleaseSemaphore(win32vars.DEBUG_sysmem_lock, 1, 0);
|
|
munmap(bubble, bubble->size);
|
|
#else
|
|
i32 *size_ptr = (i32*)block - 1;
|
|
munmap(size_ptr, *size_ptr);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
internal
|
|
Sys_Time_Sig(system_time){
|
|
i64 result = 0;
|
|
struct timespec tp;
|
|
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0){
|
|
result = tp.tv_sec*1000000 + tp.tv_nsec/1000;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal
|
|
Sys_Load_File_Sig(system_load_file){
|
|
File_Data result = {};
|
|
i32 prot = PROT_READ;
|
|
i32 flags = MAP_PRIVATE | MAP_ANON;
|
|
|
|
struct stat sb;
|
|
if (stat(filename, &sb) == 0){
|
|
result.size = sb.st_size;
|
|
result.data = system_get_memory(result.size);
|
|
if (result.data){
|
|
i32 file = open(filename, O_RDONLY);
|
|
i32 result_size = read(file, result.data, result.size);
|
|
Assert(result_size == result.size);
|
|
close(file);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal
|
|
Sys_Save_File_Sig(system_save_file){
|
|
i32 file = open(filename, O_CREAT | O_WRONLY);
|
|
if (!file) return 0;
|
|
|
|
i32 result_size = write(file, data, size);
|
|
Assert(result_size == size);
|
|
|
|
close(file);
|
|
return 1;
|
|
}
|
|
|
|
internal b32
|
|
LinuxLoadAppCode(){
|
|
b32 result = 0;
|
|
|
|
char app_code_file[] = "4ed_app.so";
|
|
i32 app_code_file_len = sizeof(app_code_file) - 1;
|
|
|
|
char path[1024];
|
|
i32 size = readlink("/proc/self/exe", path,
|
|
1024 - app_code_file_len - 1);
|
|
|
|
for (--size;
|
|
path[size] != '/' && size > 0;
|
|
--size);
|
|
memcpy(path + size + 1, app_code_file, app_code_file_len + 1);
|
|
|
|
linuxvars.app_code = SDL_LoadObject(path);
|
|
if (linuxvars.app_code){
|
|
result = 1;
|
|
linuxvars.app.init = (App_Init*)
|
|
SDL_LoadFunction(linuxvars.app_code, "app_init");
|
|
linuxvars.app.step = (App_Step*)
|
|
SDL_LoadFunction(linuxvars.app_code, "app_step");
|
|
}
|
|
else{
|
|
// TODO(allen): initialization failure
|
|
printe(app_code);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal
|
|
Sys_Acquire_Lock_Sig(system_acquire_lock){
|
|
AllowLocal(id);
|
|
}
|
|
|
|
internal
|
|
Sys_Release_Lock_Sig(system_release_lock){
|
|
AllowLocal(id);
|
|
}
|
|
|
|
internal void
|
|
LinuxLoadSystemCode(){
|
|
linuxvars.system->get_memory_full = system_get_memory_;
|
|
linuxvars.system->free_memory = system_free_memory;
|
|
|
|
linuxvars.system->load_file = system_load_file;
|
|
linuxvars.system->save_file = system_save_file;
|
|
|
|
#if 0
|
|
linuxvars.system->file_time_stamp = system_file_time_stamp;
|
|
linuxvars.system->time_stamp_now = system_time_stamp_now;
|
|
linuxvars.system->free_file = system_free_file;
|
|
|
|
linuxvars.system->get_current_directory = system_get_current_directory;
|
|
linuxvars.system->get_easy_directory = system_get_easy_directory;
|
|
|
|
linuxvars.system->get_file_list = system_get_file_list;
|
|
linuxvars.system->free_file_list = system_free_file_list;
|
|
|
|
linuxvars.system->post_clipboard = system_post_clipboard;
|
|
linuxvars.system->time = system_time;
|
|
|
|
linuxvars.system->cli_call = system_cli_call;
|
|
linuxvars.system->cli_begin_update = system_cli_begin_update;
|
|
linuxvars.system->cli_update_step = system_cli_update_step;
|
|
linuxvars.system->cli_end_update = system_cli_end_update;
|
|
|
|
linuxvars.system->thread_get_id = system_thread_get_id;
|
|
linuxvars.system->thread_current_job_id = system_thread_current_job_id;
|
|
linuxvars.system->post_job = system_post_job;
|
|
linuxvars.system->cancel_job = system_cancel_job;
|
|
linuxvars.system->job_is_pending = system_job_is_pending;
|
|
linuxvars.system->grow_thread_memory = system_grow_thread_memory;
|
|
linuxvars.system->acquire_lock = system_acquire_lock;
|
|
linuxvars.system->release_lock = system_release_lock;
|
|
|
|
linuxvars.system->force_redraw = system_force_redraw;
|
|
|
|
linuxvars.system->internal_sentinel = INTERNAL_system_sentinel;
|
|
linuxvars.system->internal_get_thread_states = INTERNAL_get_thread_states;
|
|
#endif
|
|
}
|
|
|
|
int main(){
|
|
linuxvars = {};
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO)){
|
|
// TODO(allen): initialization failure
|
|
printe(SDL_Init);
|
|
return(1);
|
|
}
|
|
SDL_EnableUNICODE(1);
|
|
|
|
if (!LinuxLoadAppCode()){
|
|
return(1);
|
|
}
|
|
|
|
System_Functions system_;
|
|
System_Functions *system = &system_;
|
|
linuxvars.system = system;
|
|
LinuxLoadSystemCode();
|
|
|
|
const SDL_VideoInfo *info = SDL_GetVideoInfo();
|
|
if (!info){
|
|
// TODO(allen): initialization failure
|
|
printe(info);
|
|
return(1);
|
|
}
|
|
|
|
{
|
|
void *base;
|
|
#if FRED_INTERNAL
|
|
base = (void*)Mbytes(128);
|
|
#else
|
|
base = (void*)0;
|
|
#endif
|
|
|
|
i32 prot = PROT_READ | PROT_WRITE;
|
|
i32 flags = MAP_PRIVATE | MAP_ANON;
|
|
|
|
linuxvars.mem.vars_memory_size = Mbytes(2);
|
|
linuxvars.mem.vars_memory = mmap(base, linuxvars.mem.vars_memory_size,
|
|
prot, flags, -1, 0);
|
|
|
|
#if FRED_INTERNAL
|
|
base = (void*)Mbytes(160);
|
|
#else
|
|
base = (void*)0;
|
|
#endif
|
|
|
|
linuxvars.mem.target_memory_size = Mbytes(64);
|
|
linuxvars.mem.target_memory = mmap(base, linuxvars.mem.target_memory_size,
|
|
prot, flags, -1, 0);
|
|
}
|
|
|
|
i32 width = 800;
|
|
i32 height = 600;
|
|
i32 bpp = info->vfmt->BitsPerPixel;
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
|
|
i32 flags = SDL_OPENGL;
|
|
|
|
if (SDL_SetVideoMode(width, height, bpp, flags) == 0){
|
|
// TODO(allen): initialization failure
|
|
printe(SDL_SetVideoMode);
|
|
return(1);
|
|
}
|
|
|
|
SDL_WM_SetCaption("4coder-window", 0);
|
|
|
|
system_acquire_lock(FRAME_LOCK);
|
|
b32 first = 1;
|
|
linuxvars.keep_going = 1;
|
|
|
|
SDL_Event event;
|
|
for (;linuxvars.keep_going && SDL_WaitEvent(&event);){
|
|
b32 pass_to_app = 0;
|
|
|
|
linuxvars.input = {};
|
|
linuxvars.clipboard = {};
|
|
switch (event.type){
|
|
case SDL_ACTIVEEVENT:
|
|
{
|
|
if ((event.active.state & SDL_APPACTIVE) && event.active.gain)
|
|
pass_to_app = 1;
|
|
}break;
|
|
|
|
case SDL_KEYDOWN:
|
|
{
|
|
pass_to_app = 1;
|
|
linuxvars.input.press[linuxvars.input.press_count++] =
|
|
get_key_event(&event);
|
|
}break;
|
|
|
|
case SDL_QUIT:
|
|
{
|
|
linuxvars.keep_going = 0;
|
|
}break;
|
|
|
|
}
|
|
|
|
if (pass_to_app){
|
|
Application_Step_Result app_result =
|
|
linuxvars.app.step(linuxvars.system,
|
|
0,
|
|
0,
|
|
&linuxvars.input,
|
|
0,
|
|
1,
|
|
0,
|
|
&linuxvars.mem,
|
|
linuxvars.clipboard,
|
|
first, 1);
|
|
|
|
|
|
|
|
SDL_GL_SwapBuffers();
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
// BOTTOM
|
|
|