Added headless server compile mode

This commit is contained in:
MysterD 2022-01-21 19:13:41 -08:00
parent 777b9287e6
commit addd16721f
15 changed files with 305 additions and 20 deletions

View file

@ -64,11 +64,11 @@ NO_LDIV ?= 0
# Backend selection # Backend selection
# Renderers: GL, GL_LEGACY, D3D11, D3D12 # Renderers: GL, GL_LEGACY, D3D11, D3D12, DUMMY
RENDER_API ?= GL RENDER_API ?= GL
# Window managers: SDL1, SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API) # Window managers: SDL1, SDL2, DXGI (forced if D3D11 or D3D12 in RENDER_API), DUMMY (forced if RENDER_API is DUMMY)
WINDOW_API ?= SDL2 WINDOW_API ?= SDL2
# Audio backends: SDL1, SDL2 # Audio backends: SDL1, SDL2, DUMMY
AUDIO_API ?= SDL2 AUDIO_API ?= SDL2
# Controller backends (can have multiple, space separated): SDL2, SDL1 # Controller backends (can have multiple, space separated): SDL2, SDL1
CONTROLLER_API ?= SDL2 CONTROLLER_API ?= SDL2
@ -242,6 +242,17 @@ else
ifeq ($(WINDOW_API),DXGI) ifeq ($(WINDOW_API),DXGI)
$(error DXGI can only be used with DirectX renderers) $(error DXGI can only be used with DirectX renderers)
endif endif
ifneq ($(WINDOW_API),DUMMY)
ifeq ($(RENDER_API),DUMMY)
$(warning Dummy renderer requires dummy window API, forcing WINDOW_API value)
WINDOW_API := DUMMY
endif
else
ifneq ($(RENDER_API),DUMMY)
$(warning Dummy window API requires dummy renderer, forcing RENDER_API value)
RENDER_API := DUMMY
endif
endif
endif endif
################### Universal Dependencies ################### ################### Universal Dependencies ###################

2
developer/dummy.sh Normal file
View file

@ -0,0 +1,2 @@
#!/bin/bash
make RENDER_API=DUMMY AUDIO_API=DUMMY CONTROLLER_API= DEBUG=1 DEVELOPMENT=1 STRICT=1 -j && ./build/us_pc/sm64.us.f3dex2e.exe --server 7777 --savepath ./build/us_pc/

View file

@ -518,9 +518,9 @@ s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
u8 is_player_active(struct MarioState* m) { u8 is_player_active(struct MarioState* m) {
if (gNetworkType == NT_NONE && m == &gMarioStates[0]) { return TRUE; } if (gNetworkType == NT_NONE && m == &gMarioStates[0]) { return TRUE; }
if (m->action == ACT_BUBBLED) { return FALSE; } if (m->action == ACT_BUBBLED) { return FALSE; }
struct NetworkPlayer* np = &gNetworkPlayers[m->playerIndex]; struct NetworkPlayer* np = &gNetworkPlayers[m->playerIndex];
if (np == gNetworkPlayerServer && gServerSettings.headlessServer) { return FALSE; }
if (np->type != NPT_LOCAL) { if (np->type != NPT_LOCAL) {
if (!np->connected) { return FALSE; } if (!np->connected) { return FALSE; }
if (gNetworkPlayerLocal == NULL) { return FALSE; } if (gNetworkPlayerLocal == NULL) { return FALSE; }

View file

@ -11,6 +11,15 @@
// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors // Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors
// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera // Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera
// moved these from sdl controller implementations
int mouse_x;
int mouse_y;
int mouse_window_buttons;
int mouse_window_x;
int mouse_window_y;
static struct ControllerAPI *controller_implementations[] = { static struct ControllerAPI *controller_implementations[] = {
&controller_recorded_tas, &controller_recorded_tas,
#if defined(CAPI_SDL2) || defined(CAPI_SDL1) #if defined(CAPI_SDL2) || defined(CAPI_SDL1)

View file

@ -18,6 +18,7 @@
#include "controller_api.h" #include "controller_api.h"
#include "controller_sdl.h" #include "controller_sdl.h"
#include "controller_mouse.h"
#include "../configfile.h" #include "../configfile.h"
#include "../platform.h" #include "../platform.h"
#include "../fs/fs.h" #include "../fs/fs.h"
@ -41,13 +42,6 @@ enum {
MAX_AXES, MAX_AXES,
}; };
int mouse_x;
int mouse_y;
int mouse_window_buttons;
int mouse_window_x;
int mouse_window_y;
#ifdef BETTERCAMERA #ifdef BETTERCAMERA
extern u8 newcam_mouse; extern u8 newcam_mouse;
#endif #endif

View file

@ -18,6 +18,7 @@
#include "controller_api.h" #include "controller_api.h"
#include "controller_sdl.h" #include "controller_sdl.h"
#include "controller_mouse.h"
#include "../configfile.h" #include "../configfile.h"
#include "../platform.h" #include "../platform.h"
#include "../fs/fs.h" #include "../fs/fs.h"
@ -31,13 +32,6 @@
#define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers #define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers
#define AXIS_THRESHOLD (30 * 256) #define AXIS_THRESHOLD (30 * 256)
int mouse_x;
int mouse_y;
int mouse_window_buttons;
int mouse_window_x;
int mouse_window_y;
#ifdef BETTERCAMERA #ifdef BETTERCAMERA
extern u8 newcam_mouse; extern u8 newcam_mouse;
#endif #endif

View file

@ -20,7 +20,12 @@ static void playerlist_update_row(u8 i, struct NetworkPlayer* np) {
if (charIndex >= CT_MAX) { charIndex = 0; } if (charIndex >= CT_MAX) { charIndex = 0; }
djuiImages[i]->texture = gCharacters[charIndex].hudHeadTexture; djuiImages[i]->texture = gCharacters[charIndex].hudHeadTexture;
djui_base_set_visible(&djuiRow[i]->base, np->connected); u8 visible = np->connected;
if (np == gNetworkPlayerServer && gServerSettings.headlessServer) {
visible = false;
}
djui_base_set_visible(&djuiRow[i]->base, visible);
u8* rgb = get_player_color(np->paletteIndex, 0); u8* rgb = get_player_color(np->paletteIndex, 0);
djui_base_set_color(&djuiTextNames[i]->base, rgb[0], rgb[1], rgb[2], 255); djui_base_set_color(&djuiTextNames[i]->base, rgb[0], rgb[1], rgb[2], 255);

240
src/pc/gfx/gfx_dummy.c Normal file
View file

@ -0,0 +1,240 @@
#if defined(RAPI_DUMMY) || defined(WAPI_DUMMY)
#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h> // for nanosleep
#else
#include <unistd.h> // for usleep
#endif
#include <errno.h>
#include <stdbool.h>
#include <PR/ultratypes.h>
#include "macros.h"
#include "gfx_window_manager_api.h"
#include "gfx_rendering_api.h"
#include "pc/pc_main.h"
#include "pc/utils/misc.h"
#include "pc/debuglog.h"
// TODO: figure out if this shit even works
#ifdef VERSION_EU
# define FRAMERATE 25
#else
# define FRAMERATE 30
#endif
// time between consequtive game frames
static const f64 sFrameTime = 1.0 / ((double)FRAMERATE);
static f64 sFrameTargetTime = 0;
static void sleep_ms(int milliseconds) { // cross-platform sleep function
// from StackOverflow user Bernardo Ramos: https://stackoverflow.com/a/28827188
#ifdef WIN32
Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(&ts, NULL);
#else
if (milliseconds >= 1000)
sleep(milliseconds / 1000);
usleep((milliseconds % 1000) * 1000);
#endif
}
static void gfx_dummy_wm_init(UNUSED const char *game_name) {
}
static void gfx_dummy_wm_set_keyboard_callbacks(UNUSED kb_callback_t on_key_down, UNUSED kb_callback_t on_key_up, UNUSED void (*on_all_keys_up)(void), UNUSED void (*on_text_input)(char*)) {
}
static void gfx_dummy_wm_set_fullscreen_changed_callback(UNUSED void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
}
static void gfx_dummy_wm_set_fullscreen(UNUSED bool enable) {
}
static void gfx_dummy_wm_main_loop(void (*run_one_game_iter)(void)) {
while (1) {
run_one_game_iter();
}
}
static void gfx_dummy_wm_get_dimensions(uint32_t *width, uint32_t *height) {
*width = 320;
*height = 240;
}
static void gfx_dummy_wm_handle_events(void) {
}
static bool gfx_dummy_wm_start_frame(void) {
return true;
}
static inline void sync_framerate_with_timer(void) {
f64 curTime = clock_elapsed_f64();
if (curTime < sFrameTargetTime) {
u32 delayMs = (sFrameTargetTime - curTime) * 1000.0;
if (delayMs > 0) {
sleep_ms(delayMs);
}
}
f64 frameTime = config60Fps ? (sFrameTime / 2.0) : sFrameTime;
sFrameTargetTime += frameTime;
}
static void gfx_dummy_wm_swap_buffers_begin(void) {
sync_framerate_with_timer();
}
static void gfx_dummy_wm_swap_buffers_end(void) {
}
static double gfx_dummy_wm_get_time(void) {
return 0.0;
}
static char* gfx_dummy_wm_get_clipboard_text(void) {
return "";
}
static void gfx_dummy_wm_shutdown(void) {
}
static void gfx_dummy_wm_start_text_input(void) {
}
static void gfx_dummy_wm_stop_text_input(void) {
}
static void gfx_dummy_wm_set_clipboard_text(UNUSED char* text) {
}
static void gfx_dummy_wm_set_cursor_visible(UNUSED bool visible) {
}
static bool gfx_dummy_renderer_z_is_from_0_to_1(void) {
return false;
}
static void gfx_dummy_renderer_unload_shader(UNUSED struct ShaderProgram *old_prg) {
}
static void gfx_dummy_renderer_load_shader(UNUSED struct ShaderProgram *new_prg) {
}
static struct ShaderProgram *gfx_dummy_renderer_create_and_load_new_shader(UNUSED uint32_t shader_id) {
return NULL;
}
static struct ShaderProgram *gfx_dummy_renderer_lookup_shader(UNUSED uint32_t shader_id) {
return NULL;
}
static void gfx_dummy_renderer_shader_get_info(UNUSED struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = 0;
used_textures[0] = false;
used_textures[1] = false;
}
static uint32_t gfx_dummy_renderer_new_texture(void) {
return 0;
}
static void gfx_dummy_renderer_select_texture(UNUSED int tile, UNUSED uint32_t texture_id) {
}
static void gfx_dummy_renderer_upload_texture(UNUSED const uint8_t *rgba32_buf, UNUSED int width, UNUSED int height) {
}
static void gfx_dummy_renderer_set_sampler_parameters(UNUSED int tile, UNUSED bool linear_filter, UNUSED uint32_t cms, UNUSED uint32_t cmt) {
}
static void gfx_dummy_renderer_set_depth_test(UNUSED bool depth_test) {
}
static void gfx_dummy_renderer_set_depth_mask(UNUSED bool z_upd) {
}
static void gfx_dummy_renderer_set_zmode_decal(UNUSED bool zmode_decal) {
}
static void gfx_dummy_renderer_set_viewport(UNUSED int x, UNUSED int y, UNUSED int width, UNUSED int height) {
}
static void gfx_dummy_renderer_set_scissor(UNUSED int x, UNUSED int y, UNUSED int width, UNUSED int height) {
}
static void gfx_dummy_renderer_set_use_alpha(UNUSED bool use_alpha) {
}
static void gfx_dummy_renderer_draw_triangles(UNUSED float buf_vbo[], UNUSED size_t buf_vbo_len, UNUSED size_t buf_vbo_num_tris) {
}
static void gfx_dummy_renderer_init(void) {
}
static void gfx_dummy_renderer_on_resize(void) {
}
static void gfx_dummy_renderer_start_frame(void) {
}
static void gfx_dummy_renderer_end_frame(void) {
}
static void gfx_dummy_renderer_finish_render(void) {
}
static void gfx_dummy_renderer_shutdown(void) {
}
struct GfxWindowManagerAPI gfx_dummy_wm_api = {
gfx_dummy_wm_init,
gfx_dummy_wm_set_keyboard_callbacks,
gfx_dummy_wm_main_loop,
gfx_dummy_wm_get_dimensions,
gfx_dummy_wm_handle_events,
gfx_dummy_wm_start_frame,
gfx_dummy_wm_swap_buffers_begin,
gfx_dummy_wm_swap_buffers_end,
gfx_dummy_wm_get_time,
gfx_dummy_wm_shutdown,
gfx_dummy_wm_start_text_input,
gfx_dummy_wm_stop_text_input,
gfx_dummy_wm_get_clipboard_text,
gfx_dummy_wm_set_clipboard_text,
gfx_dummy_wm_set_cursor_visible
};
struct GfxRenderingAPI gfx_dummy_renderer_api = {
gfx_dummy_renderer_z_is_from_0_to_1,
gfx_dummy_renderer_unload_shader,
gfx_dummy_renderer_load_shader,
gfx_dummy_renderer_create_and_load_new_shader,
gfx_dummy_renderer_lookup_shader,
gfx_dummy_renderer_shader_get_info,
gfx_dummy_renderer_new_texture,
gfx_dummy_renderer_select_texture,
gfx_dummy_renderer_upload_texture,
gfx_dummy_renderer_set_sampler_parameters,
gfx_dummy_renderer_set_depth_test,
gfx_dummy_renderer_set_depth_mask,
gfx_dummy_renderer_set_zmode_decal,
gfx_dummy_renderer_set_viewport,
gfx_dummy_renderer_set_scissor,
gfx_dummy_renderer_set_use_alpha,
gfx_dummy_renderer_draw_triangles,
gfx_dummy_renderer_init,
gfx_dummy_renderer_on_resize,
gfx_dummy_renderer_start_frame,
gfx_dummy_renderer_end_frame,
gfx_dummy_renderer_finish_render,
gfx_dummy_renderer_shutdown
};
#endif

10
src/pc/gfx/gfx_dummy.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef GFX_DUMMY_H
#define GFX_DUMMY_H
#include "gfx_rendering_api.h"
#include "gfx_window_manager_api.h"
extern struct GfxRenderingAPI gfx_dummy_renderer_api;
extern struct GfxWindowManagerAPI gfx_dummy_wm_api;
#endif

View file

@ -43,6 +43,7 @@ struct ServerSettings gServerSettings = {
.shareLives = 0, .shareLives = 0,
.enableCheats = 0, .enableCheats = 0,
.bubbleDeath = 1, .bubbleDeath = 1,
.headlessServer = 0,
}; };
void network_set_system(enum NetworkSystemType nsType) { void network_set_system(enum NetworkSystemType nsType) {
@ -70,6 +71,11 @@ bool network_init(enum NetworkType inNetworkType) {
gServerSettings.shareLives = configShareLives; gServerSettings.shareLives = configShareLives;
gServerSettings.enableCheats = configEnableCheats; gServerSettings.enableCheats = configEnableCheats;
gServerSettings.bubbleDeath = configBubbleDeath; gServerSettings.bubbleDeath = configBubbleDeath;
#if defined(RAPI_DUMMY) || defined(WAPI_DUMMY)
gServerSettings.headlessServer = (inNetworkType == NT_SERVER);
#else
gServerSettings.headlessServer = 0;
#endif
Cheats.EnableCheats = gServerSettings.enableCheats; Cheats.EnableCheats = gServerSettings.enableCheats;
// initialize the network system // initialize the network system

View file

@ -89,6 +89,7 @@ struct ServerSettings {
u8 shareLives; u8 shareLives;
u8 enableCheats; u8 enableCheats;
u8 bubbleDeath; u8 bubbleDeath;
u8 headlessServer;
}; };
// Networking-specific externs // Networking-specific externs

View file

@ -90,6 +90,7 @@ void network_send_join(struct Packet* joinRequestPacket) {
packet_write(&p, &gServerSettings.shareLives, sizeof(u8)); packet_write(&p, &gServerSettings.shareLives, sizeof(u8));
packet_write(&p, &gServerSettings.enableCheats, sizeof(u8)); packet_write(&p, &gServerSettings.enableCheats, sizeof(u8));
packet_write(&p, &gServerSettings.bubbleDeath, sizeof(u8)); packet_write(&p, &gServerSettings.bubbleDeath, sizeof(u8));
packet_write(&p, &gServerSettings.headlessServer, sizeof(u8));
packet_write(&p, eeprom, sizeof(u8) * 512); packet_write(&p, eeprom, sizeof(u8) * 512);
u8 modCount = string_linked_list_count(&gRegisteredMods); u8 modCount = string_linked_list_count(&gRegisteredMods);
@ -152,6 +153,7 @@ void network_receive_join(struct Packet* p) {
packet_read(p, &gServerSettings.shareLives, sizeof(u8)); packet_read(p, &gServerSettings.shareLives, sizeof(u8));
packet_read(p, &gServerSettings.enableCheats, sizeof(u8)); packet_read(p, &gServerSettings.enableCheats, sizeof(u8));
packet_read(p, &gServerSettings.bubbleDeath, sizeof(u8)); packet_read(p, &gServerSettings.bubbleDeath, sizeof(u8));
packet_read(p, &gServerSettings.headlessServer, sizeof(u8));
packet_read(p, eeprom, sizeof(u8) * 512); packet_read(p, eeprom, sizeof(u8) * 512);
packet_read(p, &modCount, sizeof(u8)); packet_read(p, &modCount, sizeof(u8));

View file

@ -360,5 +360,9 @@ void network_receive_player(struct Packet* p) {
void network_update_player(void) { void network_update_player(void) {
if (!network_player_any_connected()) { return; } if (!network_player_any_connected()) { return; }
u8 localIsHeadless = (&gNetworkPlayers[0] == gNetworkPlayerServer && gServerSettings.headlessServer);
if (!localIsHeadless) {
network_send_player(0); network_send_player(0);
} }
}

View file

@ -22,6 +22,7 @@
#include "gfx/gfx_dxgi.h" #include "gfx/gfx_dxgi.h"
#include "gfx/gfx_sdl.h" #include "gfx/gfx_sdl.h"
#include "gfx/gfx_dummy.h"
#include "audio/audio_api.h" #include "audio/audio_api.h"
#include "audio/audio_sdl.h" #include "audio/audio_sdl.h"
@ -231,6 +232,8 @@ void main_func(void) {
wm_api = &gfx_sdl; wm_api = &gfx_sdl;
#elif defined(WAPI_DXGI) #elif defined(WAPI_DXGI)
wm_api = &gfx_dxgi; wm_api = &gfx_dxgi;
#elif defined(WAPI_DUMMY)
wm_api = &gfx_dummy_wm_api;
#else #else
#error No window API! #error No window API!
#endif #endif
@ -248,6 +251,8 @@ void main_func(void) {
# else # else
# define RAPI_NAME "OpenGL" # define RAPI_NAME "OpenGL"
# endif # endif
#elif defined(RAPI_DUMMY)
rendering_api = &gfx_dummy_renderer_api;
#else #else
#error No rendering API! #error No rendering API!
#endif #endif

View file

@ -162,7 +162,9 @@ static void sys_fatal_impl(const char *msg) {
#else #else
#ifndef WAPI_DUMMY
#warning "You might want to implement these functions for your platform" #warning "You might want to implement these functions for your platform"
#endif
const char *sys_user_path(void) { const char *sys_user_path(void) {
return "."; return ".";