blob: f0fd1c0b028d85a2258c9849bbb3fe28145d8553 [file] [log] [blame]
#if defined(_WIN32) && !defined(WIN32)
#define WIN32
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
#include "SDL.h"
#include <iostream>
#include "Input.hpp"
#include "Multiplayer.hpp"
#include "System.hpp"
#include "Renderer.hpp"
#include "Audio.hpp"
#include "UserCode.hpp"
#include "contrib.hpp"
#ifdef VIDEO_CAPTURE
#include "VideoCapture.hpp"
#endif
static bool running = true;
SDL_Window* window = nullptr;
System *blit_system;
Input *blit_input;
Multiplayer *blit_multiplayer;
Renderer *blit_renderer;
Audio *blit_audio;
const char *launch_path = nullptr;
#ifdef VIDEO_CAPTURE
VideoCapture *blit_capture;
unsigned int last_record_startstop = 0;
#endif
void handle_event(SDL_Event &event) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
blit_renderer->resize(event.window.data1, event.window.data2);
}
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
blit_input->handle_mouse(event.button.button, event.type == SDL_MOUSEBUTTONDOWN, event.button.x, event.button.y);
break;
case SDL_MOUSEMOTION:
if (event.motion.state & SDL_BUTTON_LMASK) {
blit_input->handle_mouse(SDL_BUTTON_LEFT, event.motion.state & SDL_MOUSEBUTTONDOWN, event.motion.x, event.motion.y);
}
break;
case SDL_KEYDOWN: // fall-though
case SDL_KEYUP:
if (!blit_input->handle_keyboard(event.key.keysym.sym, event.type == SDL_KEYDOWN)) {
#ifdef VIDEO_CAPTURE
switch (event.key.keysym.sym) {
case SDLK_r:
if (event.type == SDL_KEYDOWN && SDL_GetTicks() - last_record_startstop > 1000) {
if (blit_capture->recording()) blit_capture->stop();
else blit_capture->start();
last_record_startstop = SDL_GetTicks();
}
}
#endif
}
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
blit_input->handle_controller_button(event.cbutton.button, event.type == SDL_CONTROLLERBUTTONDOWN);
break;
case SDL_CONTROLLERAXISMOTION:
blit_input->handle_controller_motion(event.caxis.axis, event.caxis.value);
break;
case SDL_CONTROLLERDEVICEADDED:
blit_input->handle_controller_added(event.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMOVED:
blit_input->handle_controller_removed(event.cdevice.which);
break;
#if SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLERSENSORUPDATE:
if(event.csensor.sensor == SDL_SENSOR_ACCEL)
blit_input->handle_controller_accel(event.csensor.data);
break;
#endif
case SDL_RENDER_TARGETS_RESET:
std::cout << "Targets reset" << std::endl;
break;
case SDL_RENDER_DEVICE_RESET:
std::cout << "Device reset" << std::endl;
break;
default:
if(event.type == System::loop_event) {
blit_renderer->update(blit_system);
blit_system->notify_redraw();
blit_renderer->present();
#ifdef VIDEO_CAPTURE
if (blit_capture->recording()) blit_capture->capture(blit_renderer);
#endif
} else if (event.type == System::timer_event) {
switch(event.user.code) {
case 0:
SDL_SetWindowTitle(window, metadata_title);
break;
case 1:
SDL_SetWindowTitle(window, (std::string(metadata_title) + " [SLOW]").c_str());
break;
case 2:
SDL_SetWindowTitle(window, (std::string(metadata_title) + " [FROZEN]").c_str());
break;
}
}
break;
}
}
#ifdef __EMSCRIPTEN__
void em_loop() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
handle_event(event);
}
blit_multiplayer->update();
blit_system->loop();
blit_renderer->update(blit_system);
blit_renderer->present();
}
#endif
int main(int argc, char *argv[]) {
int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
bool fullscreen = false;
std::cout << metadata_title << " " << metadata_version << std::endl;
std::cout << "Powered by 32Blit SDL2 runtime - github.com/32blit/32blit-sdk" << std::endl << std::endl;
auto mp_mode = Multiplayer::Mode::Auto;
std::string mp_address = "localhost";
for(int i = 1; i < argc; i++) {
std::string arg_str(argv[i]);
if(arg_str == "--connect" && i + 1 < argc) {
mp_mode = Multiplayer::Mode::Connect;
mp_address = std::string(argv[i + 1]);
i++;
}
else if(arg_str == "--launch_path" && i + 1 < argc) {
launch_path = argv[++i];
}
else if(arg_str == "--listen")
mp_mode = Multiplayer::Mode::Listen;
else if(arg_str == "--position") {
SDL_sscanf(argv[i+1], "%d,%d", &x, &y);
} else if(arg_str == "--size" && i + 1 < argc) {
int w, h;
if(SDL_sscanf(argv[i+1], "%d,%d", &w, &h) == 2) {
if(w * y < System::max_width * System::max_height) {
System::width = w;
System::height = h;
}
}
i++;
} else if(arg_str == "--fullscreen")
fullscreen = true;
else if(arg_str == "--credits") {
std::cout << "32Blit was made possible by:" << std::endl;
std::cout << std::endl;
for(auto name : contributors) {
if(name != nullptr) {
std::cout << " * " << name << std::endl;
}
}
std::cout << std::endl;
std::cout << "Special thanks to:" << std::endl;
std::cout << std::endl;
for(auto name : special_thanks) {
if(name != nullptr) {
std::cout << " * " << name << std::endl;
}
}
std::cout << std::endl;
SDL_Quit();
return 0;
}
else if(arg_str == "--info") {
std::cout << metadata_description << std::endl << std::endl;
std::cout << " Category: " << metadata_category << std::endl;
std::cout << " Author: " << metadata_author << std::endl;
std::cout << " URL: " << metadata_url << std::endl << std::endl;
SDL_Quit();
return 0;
}
else if(arg_str == "--help") {
std::cout << "Usage: " << argv[0] << " <options>" << std::endl << std::endl;
std::cout << " --connect <addr> -- Connect to a listening game instance." << std::endl;
std::cout << " --listen -- Listen for incoming connections." << std::endl;
std::cout << " --position x,y -- Set window position." << std::endl;
std::cout << " --size w,h -- Set display size. (max 320x240)" << std::endl;
std::cout << " --launch_path <file> -- Emulates the file associations on the console." << std::endl;
std::cout << " --credits -- Print contributor credits and exit." << std::endl;
std::cout << " --info -- Print metadata info and exit." << std::endl << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
}
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER|SDL_INIT_AUDIO) < 0) {
std::cerr << "could not initialize SDL2: " << SDL_GetError() << std::endl;
return 1;
}
window = SDL_CreateWindow(
metadata_title,
x, y,
System::width*2, System::height*2,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)
);
if (window == nullptr) {
std::cerr << "could not create window: " << SDL_GetError() << std::endl;
return 1;
}
SDL_SetWindowMinimumSize(window, System::width, System::height);
blit_system = new System();
blit_input = new Input(blit_system);
blit_multiplayer = new Multiplayer(mp_mode, mp_address);
blit_renderer = new Renderer(window, System::width, System::height);
blit_audio = new Audio();
#ifdef VIDEO_CAPTURE
blit_capture = new VideoCapture(argv[0]);
#endif
blit_system->run();
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(em_loop, 0, 1);
#else
SDL_Event event;
while (running && SDL_WaitEvent(&event)) {
handle_event(event);
}
#endif
if (running) {
std::cerr << "Main loop exited with error: " << SDL_GetError() << std::endl;
running = false; // ensure timer thread quits
}
#ifdef VIDEO_CAPTURE
if (blit_capture->recording()) blit_capture->stop();
delete blit_capture;
#endif
blit_system->stop();
delete blit_system;
delete blit_input;
delete blit_multiplayer;
delete blit_renderer;
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}