mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-21 19:45:10 +00:00
Added headless server compile mode
This commit is contained in:
parent
777b9287e6
commit
addd16721f
15 changed files with 305 additions and 20 deletions
17
Makefile
17
Makefile
|
@ -64,11 +64,11 @@ NO_LDIV ?= 0
|
|||
|
||||
# Backend selection
|
||||
|
||||
# Renderers: GL, GL_LEGACY, D3D11, D3D12
|
||||
# Renderers: GL, GL_LEGACY, D3D11, D3D12, DUMMY
|
||||
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
|
||||
# Audio backends: SDL1, SDL2
|
||||
# Audio backends: SDL1, SDL2, DUMMY
|
||||
AUDIO_API ?= SDL2
|
||||
# Controller backends (can have multiple, space separated): SDL2, SDL1
|
||||
CONTROLLER_API ?= SDL2
|
||||
|
@ -242,6 +242,17 @@ else
|
|||
ifeq ($(WINDOW_API),DXGI)
|
||||
$(error DXGI can only be used with DirectX renderers)
|
||||
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
|
||||
|
||||
################### Universal Dependencies ###################
|
||||
|
|
2
developer/dummy.sh
Normal file
2
developer/dummy.sh
Normal 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/
|
|
@ -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) {
|
||||
if (gNetworkType == NT_NONE && m == &gMarioStates[0]) { return TRUE; }
|
||||
|
||||
if (m->action == ACT_BUBBLED) { return FALSE; }
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[m->playerIndex];
|
||||
if (np == gNetworkPlayerServer && gServerSettings.headlessServer) { return FALSE; }
|
||||
if (np->type != NPT_LOCAL) {
|
||||
if (!np->connected) { return FALSE; }
|
||||
if (gNetworkPlayerLocal == NULL) { return FALSE; }
|
||||
|
|
|
@ -11,6 +11,15 @@
|
|||
// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors
|
||||
// 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[] = {
|
||||
&controller_recorded_tas,
|
||||
#if defined(CAPI_SDL2) || defined(CAPI_SDL1)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "controller_api.h"
|
||||
#include "controller_sdl.h"
|
||||
#include "controller_mouse.h"
|
||||
#include "../configfile.h"
|
||||
#include "../platform.h"
|
||||
#include "../fs/fs.h"
|
||||
|
@ -41,13 +42,6 @@ enum {
|
|||
MAX_AXES,
|
||||
};
|
||||
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
|
||||
int mouse_window_buttons;
|
||||
int mouse_window_x;
|
||||
int mouse_window_y;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
extern u8 newcam_mouse;
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "controller_api.h"
|
||||
#include "controller_sdl.h"
|
||||
#include "controller_mouse.h"
|
||||
#include "../configfile.h"
|
||||
#include "../platform.h"
|
||||
#include "../fs/fs.h"
|
||||
|
@ -31,13 +32,6 @@
|
|||
#define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers
|
||||
#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
|
||||
extern u8 newcam_mouse;
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,12 @@ static void playerlist_update_row(u8 i, struct NetworkPlayer* np) {
|
|||
if (charIndex >= CT_MAX) { charIndex = 0; }
|
||||
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);
|
||||
djui_base_set_color(&djuiTextNames[i]->base, rgb[0], rgb[1], rgb[2], 255);
|
||||
|
|
240
src/pc/gfx/gfx_dummy.c
Normal file
240
src/pc/gfx/gfx_dummy.c
Normal 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
10
src/pc/gfx/gfx_dummy.h
Normal 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
|
|
@ -43,6 +43,7 @@ struct ServerSettings gServerSettings = {
|
|||
.shareLives = 0,
|
||||
.enableCheats = 0,
|
||||
.bubbleDeath = 1,
|
||||
.headlessServer = 0,
|
||||
};
|
||||
|
||||
void network_set_system(enum NetworkSystemType nsType) {
|
||||
|
@ -70,6 +71,11 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
gServerSettings.shareLives = configShareLives;
|
||||
gServerSettings.enableCheats = configEnableCheats;
|
||||
gServerSettings.bubbleDeath = configBubbleDeath;
|
||||
#if defined(RAPI_DUMMY) || defined(WAPI_DUMMY)
|
||||
gServerSettings.headlessServer = (inNetworkType == NT_SERVER);
|
||||
#else
|
||||
gServerSettings.headlessServer = 0;
|
||||
#endif
|
||||
Cheats.EnableCheats = gServerSettings.enableCheats;
|
||||
|
||||
// initialize the network system
|
||||
|
|
|
@ -89,6 +89,7 @@ struct ServerSettings {
|
|||
u8 shareLives;
|
||||
u8 enableCheats;
|
||||
u8 bubbleDeath;
|
||||
u8 headlessServer;
|
||||
};
|
||||
|
||||
// Networking-specific externs
|
||||
|
|
|
@ -90,6 +90,7 @@ void network_send_join(struct Packet* joinRequestPacket) {
|
|||
packet_write(&p, &gServerSettings.shareLives, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.enableCheats, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.bubbleDeath, sizeof(u8));
|
||||
packet_write(&p, &gServerSettings.headlessServer, sizeof(u8));
|
||||
packet_write(&p, eeprom, sizeof(u8) * 512);
|
||||
|
||||
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.enableCheats, 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, &modCount, sizeof(u8));
|
||||
|
||||
|
|
|
@ -360,5 +360,9 @@ void network_receive_player(struct Packet* p) {
|
|||
|
||||
void network_update_player(void) {
|
||||
if (!network_player_any_connected()) { return; }
|
||||
|
||||
u8 localIsHeadless = (&gNetworkPlayers[0] == gNetworkPlayerServer && gServerSettings.headlessServer);
|
||||
if (!localIsHeadless) {
|
||||
network_send_player(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "gfx/gfx_dxgi.h"
|
||||
#include "gfx/gfx_sdl.h"
|
||||
#include "gfx/gfx_dummy.h"
|
||||
|
||||
#include "audio/audio_api.h"
|
||||
#include "audio/audio_sdl.h"
|
||||
|
@ -231,6 +232,8 @@ void main_func(void) {
|
|||
wm_api = &gfx_sdl;
|
||||
#elif defined(WAPI_DXGI)
|
||||
wm_api = &gfx_dxgi;
|
||||
#elif defined(WAPI_DUMMY)
|
||||
wm_api = &gfx_dummy_wm_api;
|
||||
#else
|
||||
#error No window API!
|
||||
#endif
|
||||
|
@ -248,6 +251,8 @@ void main_func(void) {
|
|||
# else
|
||||
# define RAPI_NAME "OpenGL"
|
||||
# endif
|
||||
#elif defined(RAPI_DUMMY)
|
||||
rendering_api = &gfx_dummy_renderer_api;
|
||||
#else
|
||||
#error No rendering API!
|
||||
#endif
|
||||
|
|
|
@ -162,7 +162,9 @@ static void sys_fatal_impl(const char *msg) {
|
|||
|
||||
#else
|
||||
|
||||
#ifndef WAPI_DUMMY
|
||||
#warning "You might want to implement these functions for your platform"
|
||||
#endif
|
||||
|
||||
const char *sys_user_path(void) {
|
||||
return ".";
|
||||
|
|
Loading…
Reference in a new issue