Try to abstract out the engine to make it more cross-platform.
This means you maybe can run it on linux, which is the goal for profiling and debugging purposes and it makes it easier to do that (even if the cpu is faster, i can still see expensive functions). Currently only hello.elf works on linux and hello.elf and cube.elf on the dreamcast. gl.elf is broken on both because of controller stuff.
This commit is contained in:
parent
23dd7ace18
commit
8f303eec6a
23 changed files with 547 additions and 95 deletions
89
.vscode/launch.json
vendored
89
.vscode/launch.json
vendored
|
@ -1,10 +1,58 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb, Linux) Launch hello.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/src/hello.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${fileDirname}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "(gdb, Linux) Launch gl.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/src/gl.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${fileDirname}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "(gdb) Launch gl.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/gl.elf",
|
||||
"program": "${workspaceFolder}/build/src/gl.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
@ -14,7 +62,7 @@
|
|||
"miDebuggerPath": "/opt/toolchains/dc/sh-elf/bin/sh-elf-gdb",
|
||||
"miDebuggerServerAddress": "localhost:3263",
|
||||
"debugServerPath": "/usr/bin/flycast",
|
||||
"debugServerArgs": "${workspaceFolder}/build/gl.elf",
|
||||
"debugServerArgs": "${workspaceFolder}/build/src/gl.elf",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
|
@ -33,7 +81,7 @@
|
|||
"name": "(gdb) Launch cube.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/cube.elf",
|
||||
"program": "${workspaceFolder}/build/src/cube.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
@ -43,7 +91,7 @@
|
|||
"miDebuggerPath": "/opt/toolchains/dc/sh-elf/bin/sh-elf-gdb",
|
||||
"miDebuggerServerAddress": "localhost:3263",
|
||||
"debugServerPath": "/usr/bin/flycast",
|
||||
"debugServerArgs": "${workspaceFolder}/build/cube.elf",
|
||||
"debugServerArgs": "${workspaceFolder}/build/src/cube.elf",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
|
@ -62,7 +110,7 @@
|
|||
"name": "(gdb, lxdream-nitro) Launch cube.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/cube.elf",
|
||||
"program": "${workspaceFolder}/build/src/cube.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
@ -72,7 +120,36 @@
|
|||
"miDebuggerPath": "/opt/toolchains/dc/sh-elf/bin/sh-elf-gdb",
|
||||
"miDebuggerServerAddress": "localhost:3263",
|
||||
"debugServerPath": "/home/user/Downloads/lxdream-nitro/builddir/lxdream-nitro",
|
||||
"debugServerArgs": "-d -g 3263 -e ${workspaceFolder}/build/cube.elf",
|
||||
"debugServerArgs": "-d -g 3263 -e ${workspaceFolder}/build/src/cube.elf",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set SuperH architechture",
|
||||
"text": "set architecture sh4"
|
||||
}
|
||||
],
|
||||
"avoidWindowsConsoleRedirection": false,
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"name": "(gdb, lxdream-nitro) Launch gl.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/src/gl.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/opt/toolchains/dc/sh-elf/bin/sh-elf-gdb",
|
||||
"miDebuggerServerAddress": "localhost:3263",
|
||||
"debugServerPath": "/home/user/Downloads/lxdream-nitro/builddir/lxdream-nitro",
|
||||
"debugServerArgs": "-d -g 3263 -e ${workspaceFolder}/build/src/gl.elf",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
|
|
37
meson.build
37
meson.build
|
@ -1,40 +1,5 @@
|
|||
project('dreamcast-opengl', 'c', 'cpp', default_options: ['cpp_std=c++20'])
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
kosinc = include_directories('/opt/toolchains/dc/kos/include')
|
||||
koskernelinc = include_directories('/opt/toolchains/dc/kos/kernel/arch/dreamcast/include')
|
||||
kosaddonsinc = include_directories('/opt/toolchains/dc/kos/addons/include')
|
||||
kosportsinc = include_directories('/opt/toolchains/dc/kos-ports/include')
|
||||
|
||||
GL = cc.find_library('GL', required: true)
|
||||
math = cc.find_library('m', required: true)
|
||||
stb_image = cc.find_library('stb_image', required: true)
|
||||
subdir('romdisk')
|
||||
tinyobjloader = subproject('tinyobjloader')
|
||||
tinyobjloader_dep = tinyobjloader.get_variable('tinyobjloader_dep')
|
||||
# pcx = cc.find_library('pcx', required: true)
|
||||
# kosutils = cc.find_library('kosutils', required: true)
|
||||
|
||||
deps = [
|
||||
GL,
|
||||
math,
|
||||
stb_image,
|
||||
tinyobjloader_dep
|
||||
]
|
||||
|
||||
incdirs = [
|
||||
kosinc,
|
||||
koskernelinc,
|
||||
kosaddonsinc,
|
||||
kosportsinc
|
||||
]
|
||||
|
||||
engine = static_library('engine', ['engine.cc'], dependencies: deps, include_directories: incdirs)
|
||||
engine_dep = declare_dependency(link_with: engine, include_directories: incdirs)
|
||||
|
||||
deps += [engine_dep]
|
||||
|
||||
executable('hello.elf', ['hello.cc'], dependencies: deps, include_directories: incdirs)
|
||||
executable('gl.elf', ['gl.cc'], dependencies: deps, include_directories: incdirs)
|
||||
executable('cube.elf', ['cube.cc', romdsk_o], dependencies: deps, include_directories: incdirs)
|
||||
subdir('src')
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
# Blender 4.0.2 MTL File: 'None'
|
||||
# www.blender.org
|
||||
|
||||
newmtl Material.002
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.033988 0.604769 0.801009
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
|
|
@ -31,6 +31,7 @@ vt 0.875000 0.500000
|
|||
vt 0.625000 1.000000
|
||||
vt 0.875000 0.750000
|
||||
s 0
|
||||
usemtl Material.002
|
||||
f 2/1/1 3/2/1 1/3/1
|
||||
f 4/4/2 7/5/2 3/2/2
|
||||
f 8/6/3 5/7/3 7/5/3
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
#ifdef _arch_dreamcast
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glkos.h>
|
||||
#include <GL/glu.h>
|
||||
#include <stb_image/stb_image.h>
|
||||
#else
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GL/glu.h>
|
||||
#include <stb/stb_image.h>
|
||||
#endif
|
||||
|
||||
#include <tiny_obj_loader.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include "engine.hh"
|
||||
#include <vector>
|
||||
#include "engine/engine.hh"
|
||||
|
||||
class Cube : public Engine {
|
||||
unsigned int texture;
|
||||
|
@ -31,10 +40,14 @@ void Cube::model() {
|
|||
for (size_t s = 0; s < shapes.size(); s++) {
|
||||
// Loop over faces(polygon)
|
||||
size_t index_offset = 0;
|
||||
std::vector<Vector3> vertexes {};
|
||||
std::vector<Vector3> normals {};
|
||||
std::vector<Vector3> textureCoords {};
|
||||
|
||||
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
|
||||
size_t fv = size_t(shapes[s].mesh.num_face_vertices[f]);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
// glBegin(GL_TRIANGLES);
|
||||
// Loop over vertices in the face.
|
||||
for (size_t v = 0; v < fv; v++) {
|
||||
// access to vertex
|
||||
|
@ -45,8 +58,10 @@ void Cube::model() {
|
|||
attrib.vertices[3 * size_t(idx.vertex_index) + 1];
|
||||
tinyobj::real_t vz =
|
||||
attrib.vertices[3 * size_t(idx.vertex_index) + 2];
|
||||
glVertex3f(vx, vy, vz);
|
||||
drawCalls += 1;
|
||||
Vector3 vertex = {vx, vy, vz};
|
||||
vertexes.push_back(vertex);
|
||||
// glVertex3f(vx, vy, vz);
|
||||
// drawCalls += 1;
|
||||
|
||||
|
||||
// Check if `normal_index` is zero or positive. negative = no
|
||||
|
@ -58,8 +73,12 @@ void Cube::model() {
|
|||
attrib.normals[3 * size_t(idx.normal_index) + 1];
|
||||
tinyobj::real_t nz =
|
||||
attrib.normals[3 * size_t(idx.normal_index) + 2];
|
||||
glNormal3f(nx, ny, nz);
|
||||
drawCalls += 1;
|
||||
Vector3 normal = {nx, ny, nz};
|
||||
normals.push_back(normal);
|
||||
// glNormal3f(nx, ny, nz);
|
||||
// drawCalls += 1;
|
||||
} else {
|
||||
normals.push_back(Engine::Vector3::zero());
|
||||
}
|
||||
|
||||
// Check if `texcoord_index` is zero or positive. negative = no
|
||||
|
@ -69,14 +88,27 @@ void Cube::model() {
|
|||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 0];
|
||||
tinyobj::real_t ty =
|
||||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1];
|
||||
glTexCoord2f(tx, ty);
|
||||
drawCalls += 1;
|
||||
Vector3 textureCoord = {tx, ty, 0};
|
||||
textureCoords.push_back(textureCoord);
|
||||
// glTexCoord2f(tx, ty);
|
||||
// drawCalls += 1;
|
||||
} else {
|
||||
textureCoords.push_back(Vector3::zero());
|
||||
}
|
||||
}
|
||||
index_offset += fv;
|
||||
|
||||
glEnd();
|
||||
// glEnd();
|
||||
}
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, &vertexes[0]);
|
||||
glNormalPointer(GL_FLOAT, 0, &normals[0]);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, &textureCoords[0]);
|
||||
glDrawArrays(GL_TRIANGLES, 0, vertexes.size());
|
||||
// glDrawElements(GL_TRIANGLES, shapes[s].mesh.indices.size(), GL_UNSIGNED_INT, &shapes[s].mesh.indices[0]);
|
||||
drawCalls += 1;
|
||||
}
|
||||
printf("Draw Calls: %i\n", drawCalls);
|
||||
drawCalls = 0;
|
||||
|
@ -102,11 +134,10 @@ void Cube::displayStuff() {
|
|||
glTranslatef(0.0f, 0.0f, -5.0f);
|
||||
glRotatef(90, 0.0f, 1.0f, 0.5f);
|
||||
model();
|
||||
glKosSwapBuffers();
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
void Cube::initScreen() {
|
||||
glKosInit();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
@ -128,7 +159,9 @@ void Cube::initScreen() {
|
|||
if (data) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, data);
|
||||
#ifdef _arch_dreamcast
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
#endif
|
||||
} else {
|
||||
printf("Texture failed to load.\n");
|
||||
}
|
24
src/engine/controller/controller.hh
Normal file
24
src/engine/controller/controller.hh
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef CONTROLLER_HH
|
||||
#define CONTROLLER_HH
|
||||
class Controller {
|
||||
public:
|
||||
enum Button {
|
||||
A = (1 << 0),
|
||||
B = (1 << 1),
|
||||
X = (1 << 2),
|
||||
Y = (1 << 3),
|
||||
DPAD_UP = (1 << 4),
|
||||
DPAD_DOWN = (1 << 5),
|
||||
DPAD_LEFT = (1 << 6),
|
||||
DPAD_RIGHT = (1 << 7)
|
||||
};
|
||||
virtual bool InitializeController() { return false; };
|
||||
virtual void PollController(){};
|
||||
virtual bool IsButtonPressed(Button button) { return 0; };
|
||||
virtual float GetLeftJoystickXAxis() { return 0.0; };
|
||||
virtual float GetLeftJoystickYAxis() { return 0.0; };
|
||||
|
||||
protected:
|
||||
virtual int GetButtonMask(Button button) { return 0; }
|
||||
};
|
||||
#endif
|
54
src/engine/controller/dreamcastController.cc
Normal file
54
src/engine/controller/dreamcastController.cc
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "dreamcastController.hh"
|
||||
#include "controller.hh"
|
||||
|
||||
DreamcastController::DreamcastController() {
|
||||
}
|
||||
|
||||
bool DreamcastController::InitializeController() {
|
||||
controller = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||
if (this->controller) {
|
||||
controller_state = (cont_state_t*)maple_dev_status(controller);
|
||||
return true;
|
||||
} else {
|
||||
controller = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamcastController::PollController() {
|
||||
controller_state = (cont_state_t*)maple_dev_status(controller);
|
||||
}
|
||||
|
||||
bool DreamcastController::IsButtonPressed(Button button) {
|
||||
return controller_state->buttons & GetButtonMask(button);
|
||||
}
|
||||
|
||||
float DreamcastController::GetLeftJoystickXAxis() {
|
||||
return (controller_state->joyx / 127.0f);
|
||||
}
|
||||
|
||||
float DreamcastController::GetLeftJoystickYAxis() {
|
||||
return (controller_state->joyy / 127.0f);
|
||||
}
|
||||
|
||||
int DreamcastController::GetButtonMask(Button button) {
|
||||
switch (button) {
|
||||
case Button::A:
|
||||
return CONT_A;
|
||||
case Button::B:
|
||||
return CONT_B;
|
||||
case Button::X:
|
||||
return CONT_X;
|
||||
case Button::Y:
|
||||
return CONT_Y;
|
||||
case Button::DPAD_UP:
|
||||
return CONT_DPAD_UP;
|
||||
case Button::DPAD_DOWN:
|
||||
return CONT_DPAD_DOWN;
|
||||
case Button::DPAD_LEFT:
|
||||
return CONT_DPAD_LEFT;
|
||||
case Button::DPAD_RIGHT:
|
||||
return CONT_DPAD_RIGHT;
|
||||
}
|
||||
return 0;
|
||||
}
|
18
src/engine/controller/dreamcastController.hh
Normal file
18
src/engine/controller/dreamcastController.hh
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef DREAMCAST_CONTROLLER_HH
|
||||
#define DREAMCAST_CONTROLLER_HH
|
||||
#include <kos.h>
|
||||
|
||||
#include "controller.hh"
|
||||
class DreamcastController : public Controller {
|
||||
public:
|
||||
DreamcastController();
|
||||
bool InitializeController() override;
|
||||
void PollController() override;
|
||||
bool IsButtonPressed(Button button) override;
|
||||
float GetLeftJoystickXAxis() override;
|
||||
float GetLeftJoystickYAxis() override;
|
||||
int GetButtonMask(Button button) override;
|
||||
maple_device_t* controller = nullptr;
|
||||
cont_state_t* controller_state = nullptr;
|
||||
};
|
||||
#endif
|
48
src/engine/controller/linuxController.cc
Normal file
48
src/engine/controller/linuxController.cc
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "linuxController.hh"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
bool LinuxController::InitializeController() {
|
||||
if (glfwJoystickIsGamepad(GLFW_JOYSTICK_1)) {
|
||||
glfwGetGamepadState(GLFW_JOYSTICK_1, &controllerState);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinuxController::PollController() {
|
||||
glfwGetGamepadState(GLFW_JOYSTICK_1, &controllerState);
|
||||
}
|
||||
|
||||
bool LinuxController::IsButtonPressed(Button button) {
|
||||
return controllerState.buttons[GetButtonMask(button)];
|
||||
}
|
||||
|
||||
float LinuxController::GetLeftJoystickXAxis() {
|
||||
return controllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_X];
|
||||
}
|
||||
|
||||
float LinuxController::GetLeftJoystickYAxis() {
|
||||
return controllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y];
|
||||
}
|
||||
|
||||
int LinuxController::GetButtonMask(Button button) {
|
||||
switch (button) {
|
||||
case Button::A:
|
||||
return GLFW_GAMEPAD_BUTTON_A;
|
||||
case Button::B:
|
||||
return GLFW_GAMEPAD_BUTTON_B;
|
||||
case Button::X:
|
||||
return GLFW_GAMEPAD_BUTTON_X;
|
||||
case Button::Y:
|
||||
return GLFW_GAMEPAD_BUTTON_Y;
|
||||
case Button::DPAD_UP:
|
||||
return GLFW_GAMEPAD_BUTTON_DPAD_UP;
|
||||
case Button::DPAD_DOWN:
|
||||
return GLFW_GAMEPAD_BUTTON_DPAD_DOWN;
|
||||
case Button::DPAD_LEFT:
|
||||
return GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||
case Button::DPAD_RIGHT:
|
||||
return GLFW_GAMEPAD_BUTTON_DPAD_RIGHT;
|
||||
}
|
||||
}
|
17
src/engine/controller/linuxController.hh
Normal file
17
src/engine/controller/linuxController.hh
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef LINUX_CONTROLLER_HH
|
||||
#define LINUX_CONTROLLER_HH
|
||||
#include "controller.hh"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
class LinuxController : public Controller {
|
||||
public:
|
||||
bool InitializeController() override;
|
||||
void PollController() override;
|
||||
bool IsButtonPressed(Button button) override;
|
||||
float GetLeftJoystickXAxis() override;
|
||||
float GetLeftJoystickYAxis() override;
|
||||
int GetButtonMask(Button button) override;
|
||||
GLFWgamepadstate controllerState;
|
||||
};
|
||||
|
||||
#endif
|
12
src/engine/controller/meson.build
Normal file
12
src/engine/controller/meson.build
Normal file
|
@ -0,0 +1,12 @@
|
|||
sources = []
|
||||
incdirs = include_directories('.')
|
||||
|
||||
if host_machine.system() == 'dreamcast'
|
||||
sources += 'dreamcastController.cc'
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
sources += 'linuxController.cc'
|
||||
endif
|
||||
|
||||
controller = static_library('controller', sources)
|
24
src/engine/dreamcastEngine.cc
Normal file
24
src/engine/dreamcastEngine.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifdef _arch_dreamcast
|
||||
#include "dreamcastEngine.hh"
|
||||
#include <stdexcept>
|
||||
#include <GL/glkos.h>
|
||||
#include "controller/dreamcastController.hh"
|
||||
|
||||
void DreamcastEngine::initializeEngine() {
|
||||
glKosInit();
|
||||
// printSystemInformation();
|
||||
}
|
||||
|
||||
void DreamcastEngine::initializeController() {
|
||||
DreamcastController* dreamCont = new DreamcastController;
|
||||
if (dreamCont->InitializeController()) {
|
||||
controller = dreamCont;
|
||||
} else {
|
||||
throw std::runtime_error("Can't initialize the controller.");
|
||||
}
|
||||
}
|
||||
|
||||
void DreamcastEngine::SwapBuffers() {
|
||||
glKosSwapBuffers();
|
||||
}
|
||||
#endif
|
10
src/engine/dreamcastEngine.hh
Normal file
10
src/engine/dreamcastEngine.hh
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef DREAMCAST_ENGINE_HH
|
||||
#define DREAMCAST_ENGINE_HH
|
||||
#include "nativeEngine.hh"
|
||||
|
||||
class DreamcastEngine : public NativeEngine {
|
||||
void initializeController() override;
|
||||
void initializeEngine() override;
|
||||
void SwapBuffers() override;
|
||||
};
|
||||
#endif
|
|
@ -2,12 +2,34 @@
|
|||
|
||||
#include "engine.hh"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glkos.h>
|
||||
#include "dreamcastEngine.hh"
|
||||
#else
|
||||
#include "linuxEngine.hh"
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
|
||||
void Engine::initializeEngine() {
|
||||
#ifdef _arch_dreamcast
|
||||
engine = new DreamcastEngine;
|
||||
#else
|
||||
engine = new LinuxEngine;
|
||||
#endif
|
||||
engine->initializeEngine();
|
||||
initScreen();
|
||||
controller = engine->controller;
|
||||
}
|
||||
|
||||
void Engine::initializeController() {
|
||||
engine->initializeController();
|
||||
}
|
||||
void Engine::SwapBuffers() {
|
||||
engine->SwapBuffers();
|
||||
}
|
||||
|
||||
void Engine::initScreen() {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glViewport(0, 0, 640, 480);
|
||||
|
@ -25,12 +47,6 @@ void Engine::printSystemInformation() {
|
|||
printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
void Engine::initializeEngine() {
|
||||
glKosInit();
|
||||
initScreen();
|
||||
printSystemInformation();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Engine::deltaTimeLoop(T&& callback, struct timeval& beginningOfFrame,
|
||||
struct timeval& endOfFrame) {
|
||||
|
@ -52,16 +68,15 @@ void Engine::initializeGameLoop() {
|
|||
}
|
||||
}
|
||||
|
||||
void Engine::pressButton(cont_state_t* controller_state, int button,
|
||||
std::function<void()> callback) {
|
||||
if (controller_state->buttons & button) {
|
||||
void Engine::pressButton(Controller::Button button, std::function<void()> callback) {
|
||||
if (controller->IsButtonPressed(button)) {
|
||||
if (!(buttonsPressed & button)) {
|
||||
buttonsPressed |= button;
|
||||
|
||||
callback();
|
||||
}
|
||||
} else if ((buttonsPressed & button) &&
|
||||
~(controller_state->buttons & button)) {
|
||||
!controller->IsButtonPressed(button)) {
|
||||
buttonsPressed &= ~button;
|
||||
}
|
||||
}
|
||||
|
@ -71,3 +86,5 @@ void Engine::glVertex3fNormalized(float x, float y, float z) {
|
|||
|
||||
glVertex3f(x * xSize, y * ySize, z);
|
||||
}
|
||||
|
||||
Engine::Vector3 Engine::Vector3::zero() { return {0, 0, 0}; }
|
|
@ -1,11 +1,13 @@
|
|||
#ifndef ENGINE_HH
|
||||
#define ENGINE_HH
|
||||
|
||||
#include <kos.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "controller/controller.hh"
|
||||
#include "nativeEngine.hh"
|
||||
|
||||
class Engine {
|
||||
protected:
|
||||
static constexpr float microSecond = 0.000001f;
|
||||
|
@ -20,17 +22,26 @@ class Engine {
|
|||
virtual void initScreen();
|
||||
void printSystemInformation();
|
||||
virtual void gameLoop(){};
|
||||
void pressButton(cont_state_t* controller_state, int button,
|
||||
std::function<void()> callback);
|
||||
void pressButton(Controller::Button button, std::function<void()> callback);
|
||||
void glVertex3fNormalized(float x, float y, float z);
|
||||
void SwapBuffers();
|
||||
Controller* controller = nullptr;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void deltaTimeLoop(T&& callback, struct timeval& beginningOfFrame,
|
||||
struct timeval& endOfFrame);
|
||||
NativeEngine* engine = nullptr;
|
||||
|
||||
public:
|
||||
void initializeController();
|
||||
void initializeEngine();
|
||||
void initializeGameLoop();
|
||||
struct Vector3 {
|
||||
static Vector3 zero();
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
};
|
||||
#endif
|
44
src/engine/linuxEngine.cc
Normal file
44
src/engine/linuxEngine.cc
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifdef __linux__
|
||||
|
||||
#include "linuxEngine.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "linuxController.hh"
|
||||
|
||||
void LinuxEngine::initializeEngine() {
|
||||
glfwInit();
|
||||
// Set OpenGL version to 1.2.
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
|
||||
// Create a GLFW window.
|
||||
window = glfwCreateWindow(640, 480, "DC Engine", nullptr, nullptr);
|
||||
|
||||
// Fail if the window has failed to create.
|
||||
if (window == nullptr) {
|
||||
const char* description;
|
||||
glfwGetError(&description);
|
||||
std::cout << "Failed to create GLFW window.\n"
|
||||
<< description << std::endl;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
// printSystemInformation();
|
||||
}
|
||||
|
||||
void LinuxEngine::initializeController() {
|
||||
LinuxController* linuxCont = new LinuxController;
|
||||
if (linuxCont->InitializeController()) {
|
||||
controller = linuxCont;
|
||||
} else {
|
||||
throw std::runtime_error("No controller detected");
|
||||
}
|
||||
}
|
||||
|
||||
void LinuxEngine::SwapBuffers() {
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
#endif
|
13
src/engine/linuxEngine.hh
Normal file
13
src/engine/linuxEngine.hh
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef LINUX_ENGINE_HH
|
||||
#define LINUX_ENGINE_HH
|
||||
#include "nativeEngine.hh"
|
||||
#include <epoxy/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
class LinuxEngine : public NativeEngine {
|
||||
void initializeController() override;
|
||||
void initializeEngine() override;
|
||||
void SwapBuffers() override;
|
||||
GLFWwindow* window = nullptr;
|
||||
};
|
||||
#endif
|
14
src/engine/meson.build
Normal file
14
src/engine/meson.build
Normal file
|
@ -0,0 +1,14 @@
|
|||
engine_deps = [
|
||||
GL,
|
||||
math,
|
||||
]
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
engine_deps += dependency('glfw3')
|
||||
engine_deps += dependency('epoxy')
|
||||
endif
|
||||
|
||||
subdir('controller')
|
||||
|
||||
engine = static_library('engine', ['dreamcastEngine.cc', 'linuxEngine.cc', 'engine.cc'], dependencies: engine_deps, include_directories: incdirs)
|
||||
engine_dep = declare_dependency(link_with: [engine, controller], include_directories: incdirs)
|
0
src/engine/nativeEngine.cc
Normal file
0
src/engine/nativeEngine.cc
Normal file
11
src/engine/nativeEngine.hh
Normal file
11
src/engine/nativeEngine.hh
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef NATIVE_ENGINE_HH
|
||||
#define NATIVE_ENGINE_HH
|
||||
#include "controller/controller.hh"
|
||||
class NativeEngine {
|
||||
public:
|
||||
virtual void initializeController(){};
|
||||
virtual void initializeEngine(){};
|
||||
virtual void SwapBuffers(){};
|
||||
Controller* controller = nullptr;
|
||||
};
|
||||
#endif
|
|
@ -1,10 +1,14 @@
|
|||
#ifdef _arch_dreamcast
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glkos.h>
|
||||
|
||||
#include <kos.h>
|
||||
#else
|
||||
#include <GLFW/glfw3.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
#include "engine.hh"
|
||||
#include "engine/engine.hh"
|
||||
|
||||
class Glcc : public Engine {
|
||||
void process_input();
|
||||
|
@ -39,43 +43,31 @@ void Glcc::displayStuff() {
|
|||
glPopMatrix();
|
||||
// clang-format on
|
||||
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
if (thirtyfps) {
|
||||
vid_waitvbl();
|
||||
vid_waitvbl();
|
||||
}
|
||||
#endif
|
||||
|
||||
glKosSwapBuffers();
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
void Glcc::process_input() {
|
||||
maple_device_t* controller;
|
||||
cont_state_t* controller_state;
|
||||
|
||||
controller = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||
|
||||
if (controller) {
|
||||
controller_state = (cont_state_t*)maple_dev_status(controller);
|
||||
|
||||
if (!controller_state) {
|
||||
printf(
|
||||
"An error has occured while trying to read the "
|
||||
"controller.\n");
|
||||
}
|
||||
|
||||
pressButton(controller_state, CONT_DPAD_LEFT, [&]() { speed -= 1.0f; });
|
||||
pressButton(controller_state, CONT_DPAD_RIGHT,
|
||||
[&]() { speed += 1.0f; });
|
||||
pressButton(controller_state, CONT_A,
|
||||
[&]() { thirtyfps = !thirtyfps; });
|
||||
pressButton(Controller::Button::DPAD_LEFT, [&]() { speed -= 1.0f; });
|
||||
pressButton(Controller::Button::DPAD_RIGHT, [&]() { speed += 1.0f; });
|
||||
pressButton(Controller::Button::A, [&]() { thirtyfps = !thirtyfps; });
|
||||
|
||||
speed = std::clamp(speed, 1.0f, 10.0f);
|
||||
|
||||
angle += (controller_state->joyx / 127.0f) * deltaTime * speed;
|
||||
}
|
||||
angle += controller->GetLeftJoystickXAxis() * deltaTime * speed;
|
||||
printf("%f\n", speed);
|
||||
}
|
||||
|
||||
int main() {
|
||||
Glcc* engine = new Glcc;
|
||||
engine->initializeEngine();
|
||||
engine->initializeController();
|
||||
engine->initializeGameLoop();
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
#ifdef _arch_dreamcast
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glkos.h>
|
||||
#include "engine.hh"
|
||||
#else
|
||||
#include <GLFW/glfw3.h>
|
||||
#endif
|
||||
#include "engine/engine.hh"
|
||||
|
||||
class Hello : public Engine {
|
||||
void triangle();
|
||||
|
||||
void gameLoop() override {
|
||||
triangle();
|
||||
glKosSwapBuffers();
|
||||
SwapBuffers();
|
||||
}
|
||||
};
|
||||
|
54
src/meson.build
Normal file
54
src/meson.build
Normal file
|
@ -0,0 +1,54 @@
|
|||
cc = meson.get_compiler('c')
|
||||
|
||||
kosinc = include_directories('/opt/toolchains/dc/kos/include')
|
||||
koskernelinc = include_directories('/opt/toolchains/dc/kos/kernel/arch/dreamcast/include')
|
||||
kosaddonsinc = include_directories('/opt/toolchains/dc/kos/addons/include')
|
||||
kosportsinc = include_directories('/opt/toolchains/dc/kos-ports/include')
|
||||
|
||||
GL = cc.find_library('GL', required: true)
|
||||
math = cc.find_library('m', required: true)
|
||||
# pcx = cc.find_library('pcx', required: true)
|
||||
# kosutils = cc.find_library('kosutils', required: true)
|
||||
|
||||
tinyobjloader = subproject('tinyobjloader')
|
||||
tinyobjloader_dep = tinyobjloader.get_variable('tinyobjloader_dep')
|
||||
|
||||
deps = [
|
||||
GL,
|
||||
math,
|
||||
tinyobjloader_dep
|
||||
]
|
||||
|
||||
incdirs = []
|
||||
|
||||
if host_machine.system() == 'dreamcast'
|
||||
stb_image = cc.find_library('stb_image', required: true)
|
||||
deps += stb_image
|
||||
incdirs += [
|
||||
kosinc,
|
||||
koskernelinc,
|
||||
kosaddonsinc,
|
||||
kosportsinc
|
||||
]
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
deps += dependency('glfw3')
|
||||
deps += dependency('glu')
|
||||
endif
|
||||
|
||||
subdir('engine')
|
||||
|
||||
deps += [engine_dep]
|
||||
|
||||
cube_sources = [
|
||||
'cube.cc'
|
||||
]
|
||||
|
||||
if host_machine.system() == 'dreamcast'
|
||||
cube_sources += romdsk_o
|
||||
endif
|
||||
|
||||
executable('hello.elf', ['hello.cc'], dependencies: deps, include_directories: incdirs)
|
||||
executable('gl.elf', ['gl.cc'], dependencies: deps, include_directories: incdirs)
|
||||
executable('cube.elf', cube_sources, dependencies: deps, include_directories: incdirs)
|
Loading…
Reference in a new issue