some stuff to get the dreamcast build working again (or at least compiling, reading from the CD through KOS in emulators broke so I can't test much)

This commit is contained in:
ecker 2025-08-04 17:51:43 -05:00
parent 4299be4646
commit c49dfb9b8c
28 changed files with 194 additions and 25 deletions

View File

@ -64,11 +64,11 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
DEPS +=
FLAGS += -DUF_DEBUG
ifneq (,$(findstring win64,$(ARCH)))
ifneq (,$(findstring -DUF_DEBUG,$(FLAGS)))
REQ_DEPS += meshoptimizer toml xatlas curl ffx:fsr cpptrace vall_e # ncurses openvr draco discord bullet ultralight-ux
FLAGS += -g
endif
ifneq (,$(findstring win64,$(ARCH)))
REQ_DEPS += $(RENDERER) json:nlohmann png zlib luajit reactphysics simd ctti gltf imgui fmt freetype openal ogg wav # meshoptimizer toml xatlas curl ffx:fsr cpptrace # ncurses openvr draco discord bullet ultralight-ux
FLAGS += -DUF_ENV_WINDOWS -DUF_ENV_WIN64 -DWIN32_LEAN_AND_MEAN
DEPS += -lgdi32 -ldwmapi
@ -76,7 +76,7 @@ ifneq (,$(findstring win64,$(ARCH)))
INCS := -I./dep/master/include $(INCS)
else ifneq (,$(findstring dreamcast,$(ARCH)))
FLAGS += -DUF_ENV_DREAMCAST
REQ_DEPS += simd opengl gldc json:nlohmann reactphysics png zlib ctti lua fmt imgui freetype openal aldc ogg # gltf bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
REQ_DEPS += simd opengl gldc json:nlohmann png zlib ctti reactphysics lua freetype fmt imgui openal aldc ogg wav gltf # bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
INCS := -I./dep/dreamcast/include $(INCS)
endif
ifneq (,$(findstring vulkan,$(REQ_DEPS)))
@ -90,7 +90,7 @@ ifneq (,$(findstring opengl,$(REQ_DEPS)))
ifneq (,$(findstring dreamcast,$(ARCH)))
ifneq (,$(findstring gldc,$(REQ_DEPS)))
DEPS += -lGLdc
DEPS += -lGL # kos-ports version saves it as libGL instead of libGLdc
FLAGS += -DUF_USE_OPENGL_GLDC
else
DEPS += -lGL
@ -109,6 +109,7 @@ endif
ifneq (,$(findstring fmt,$(REQ_DEPS)))
FLAGS += -DUF_USE_FMT
ifneq (,$(findstring dreamcast,$(ARCH)))
# dreamcast uses a header only version because reasons
else
DEPS += -lfmt
endif
@ -155,7 +156,7 @@ ifneq (,$(findstring openal,$(REQ_DEPS)))
FLAGS += -DUF_USE_OPENAL -DUF_USE_ALUT
ifneq (,$(findstring dreamcast,$(ARCH)))
ifneq (,$(findstring aldc,$(REQ_DEPS)))
DEPS += -lALdc
DEPS += -lAL -lpthread # kos-ports version saves it as libAL instead of libALdc
FLAGS += -DUF_USE_OPENAL_ALDC -DUF_USE_ALUT
else
DEPS += -lAL

View File

@ -1,8 +1,8 @@
{
// "import": "./rp_downtown_v2.json"
// "import": "./ss2_medsci1.json"
"import": "./ss2_medsci1.json"
// "import": "./sh2_mcdonalds.json"
"import": "./animal_crossing.json"
// "import": "./animal_crossing.json"
// "import": "./mds_mcdonalds.json"
// "import": "./gm_construct.json"
}

View File

@ -2,7 +2,8 @@
"import": "./base_sourceengine.json",
"assets": [
// { "filename": "./models/ss2_medsci1.glb" }
{ "filename": "./models/ss2_medsci1/graph.json" }
// { "filename": "./models/ss2_medsci1/graph.json" }
{ "filename": "./models/ss2_medsci1_small/graph.json" }
],
"metadata": {
"graph": {

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "StartMenu",
"start": "SourceEngine",
"matrix": { "reverseInfinite": true },
"meshes": { "interleaved": false },
"lights": { "enabled": true,

View File

@ -6,6 +6,6 @@ rm ./build/*
sh-elf-objcopy.exe -O binary $DIR/*.elf ./$TARGET_NAME.bin
$KOS_BASE/utils/scramble/scramble.exe ./$TARGET_NAME.bin ./build/1ST_READ.bin
$KOS_BASE/utils/makeip/makeip.exe -g "$TARGET_NAME" ./build/IP.BIN
xorrisofs -C 0,11702 -V DC_GAME -G ./build/IP.BIN -r -J -l -o ./$TARGET_NAME.iso ./build/ ../data/ ./config.json
xorrisofs -C 0,11702 -V DC_GAME -G ./build/IP.BIN -r -J -l -o ./$TARGET_NAME.iso ./build/ ../data/ ./data/
$KOS_BASE/utils/img4dc/cdi4dc.exe ./$TARGET_NAME.iso ./$TARGET_NAME.cdi > /dev/null
# cp ./$TARGET_NAME.cdi /x/programs/vidya/emulators/redream/CDI/.

View File

@ -6,7 +6,7 @@
#include <math.h>
namespace std {
#if 1
#if 0
inline double log2( double n ) { return log(n) / log(2); }
inline double cbrt( double x ) { return ::cbrt( x ); }
#endif

View File

@ -3,7 +3,7 @@
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
#if UF_USE_IMGUI
#include "imgui.h"
#include "imgui_stdlib.h"
@ -70,3 +70,4 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string*
cb_user_data.ChainCallbackUserData = user_data;
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
}
#endif

View File

@ -3,6 +3,7 @@
#include <uf/config.h>
#include <uf/utils/string/string.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/memory/unordered_map.h>
//#define UF_INPUT_USE_ENUM_MOUSE 1

View File

@ -3,6 +3,7 @@
#include <uf/config.h>
#include <uf/utils/string/string.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/memory/unordered_map.h>
#define UF_INPUT_USE_ENUM_MOUSE 1

View File

@ -8,6 +8,8 @@
#include <uf/ext/bullet/bullet.h>
#elif UF_USE_REACTPHYSICS
#include <uf/ext/reactphysics/reactphysics.h>
#else
#include "physics/stub.h"
#endif
namespace uf {

View File

@ -0,0 +1,108 @@
// enough things to get it to compile without a physics lib
namespace uf {
struct Mesh;
}
namespace pod {
struct UF_API Physics {
size_t uid = 0;
uf::Object* object = NULL;
bool shared = false; // share control of the transform both in-engine and bullet, set to true if you're directly modifying the transform
void* body = NULL;
void* shape = NULL;
void* world = NULL;
pod::Transform<> transform = {};
struct Linear {
pod::Vector3f velocity;
pod::Vector3f acceleration;
} linear;
struct Angular {
pod::Quaternion<> velocity;
pod::Quaternion<> acceleration;
} rotational;
struct {
struct {
pod::Transform<> transform = {};
Linear linear;
Angular rotational;
} current, previous;
} internal;
struct {
uint32_t flags = 0;
float mass = 0.0f;
float friction = 0.8f;
float restitution = 0.0f;
pod::Vector3f inertia = {0, 0, 0};
pod::Vector3f gravity = {0, 0, 0};
} stats;
};
typedef Physics PhysicsState;
}
namespace uf {
namespace physics {
namespace impl {
typedef void* WorldState;
inline void UF_API initialize() {}
inline void UF_API initialize( uf::Object& ) {}
inline void UF_API tick( float = 0 ) {}
inline void UF_API tick( uf::Object&, float = 0 ) {}
inline void UF_API terminate() {}
inline void UF_API terminate( uf::Object& ) {}
// base collider creation
inline pod::PhysicsState& UF_API create( uf::Object& ) { static pod::PhysicsState null; return null; }
inline void UF_API destroy( uf::Object& ) { return; }
inline void UF_API destroy( pod::PhysicsState& ) { return; }
inline void UF_API attach( pod::PhysicsState& ) { return; }
inline void UF_API detach( pod::PhysicsState& ) { return; }
// collider for mesh (static or dynamic)
inline pod::PhysicsState& create( uf::Object&, const uf::Mesh&, bool ) { static pod::PhysicsState null; return null; }
// collider for boundingbox
inline pod::PhysicsState& UF_API create( uf::Object&, const pod::Vector3f& ) { static pod::PhysicsState null; return null; }
// collider for capsule
inline pod::PhysicsState& UF_API create( uf::Object&, float, float ) { static pod::PhysicsState null; return null; }
/*
// synchronize engine transforms to bullet transforms
inline void UF_API syncTo( ext::reactphysics::WorldState& ) { return; }
// synchronize bullet transforms to engine transforms
inline void UF_API syncFrom( ext::reactphysics::WorldState&, float = 1 ) { return; }
*/
// apply impulse
inline void UF_API setImpulse( pod::PhysicsState&, const pod::Vector3f& = {} ) { return; }
inline void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& ) { return; }
// directly move a transform
inline void UF_API applyMovement( pod::PhysicsState&, const pod::Vector3f& ) { return; }
// directly apply a velocity
inline void UF_API setVelocity( pod::PhysicsState&, const pod::Vector3f& ) { return; }
inline void UF_API applyVelocity( pod::PhysicsState&, const pod::Vector3f& ) { return; }
// directly rotate a transform
inline void UF_API applyRotation( pod::PhysicsState&, const pod::Quaternion<>& ) { return; }
inline void UF_API applyRotation( pod::PhysicsState&, const pod::Vector3f&, float ) { return; }
// ray casting
inline uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& ) { return NULL; }
inline uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f& ) { return NULL; }
inline uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f&, float& ) { return NULL; }
inline uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, float& ) { return NULL; }
// allows noclip
inline void UF_API activateCollision( pod::PhysicsState&, bool = true ) { return; }
//
inline float UF_API getMass( pod::PhysicsState& ) { return {}; }
inline void UF_API setMass( pod::PhysicsState&, float ) { return; }
}
}
}

View File

@ -170,5 +170,9 @@ uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) {
#include <uf/utils/string/ext.h>
uf::stl::string uf::string::toString( const uf::Entity& entity ) {
#if UF_USE_FMT
return ::fmt::format("{} ({}): {}", entity.getName(), entity.getUid(), (void*) &entity);
#else
return entity.getName() + " (" + std::to_string(entity.getUid()) + "): " + std::to_string(&entity);
#endif
}

View File

@ -1,6 +1,7 @@
#include <uf/engine/object/object.h>
#include <uf/engine/asset/asset.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/math/collision.h>
#include <uf/utils/time/time.h>
#include <uf/utils/audio/audio.h>
#include <uf/utils/math/transform.h>
@ -11,6 +12,7 @@
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/math/physics.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/engine/graph/graph.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Object)
UF_BEHAVIOR_TRAITS_CPP(uf::ObjectBehavior, ticks = true, renders = false, multithread = false) // segfaults @ engine/src/ext/lua/lua.cpp:298 `auto result = state.safe_script_file( s.file, s.env, sol::script_pass_on_error );`

View File

@ -3,6 +3,7 @@
#include <uf/utils/camera/camera.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/math/physics.h>
#include <uf/engine/graph/graph.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Scene)
UF_BEHAVIOR_TRAITS_CPP(uf::SceneBehavior, ticks = false, renders = false, multithread = false)

View File

@ -556,7 +556,9 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
#endif
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) {
#if !UF_ENV_DREAMCAST
graph.name = uf::graph::save( graph, filename );
#endif
// disable baking, doesn't output right if baking from a gltf imported model
// graph.metadata["baking"]["enabled"] = false;

View File

@ -131,7 +131,7 @@ namespace binds {
std::cout << str;
if ( --count != 0 ) std::cout << "\t";
}
std::cout <<"\n");
std::cout <<"\n";
std::cout.flush();
#endif
};

View File

@ -47,8 +47,12 @@ namespace {
pod::Vector2ui resolution = { 640, 480 };
bool GetModifier( uint8_t modifier ) {
// to-fix later
return false;
/*
if ( !::keyboard.state ) return false;
return ::keyboard.state->cond.modifiers & modifier;
*/
}
uf::stl::vector<uint8_t> GetKeys() {
uf::stl::vector<uint8_t> keys;
@ -367,11 +371,11 @@ spec::dreamcast::Window::vector_t spec::dreamcast::Window::getMousePosition( ) {
}
void spec::dreamcast::Window::setSize( const spec::dreamcast::Window::vector_t& size ) {
int e = 0;
int p = PM_RGB565;
vid_pixel_mode_t p = PM_RGB565;
if ( size.x == 320 && size.y == 240 ) e = DM_320x240;
else if ( size.x == 640 && size.y == 480 ) e = DM_640x480;
else if ( size.x == 800 && size.y == 608 ) e = DM_800x608;
//else if ( size.x == 800 && size.y == 608 ) e = DM_800x608;
else if ( size.x == 256 && size.y == 256 ) e = DM_256x256;
else if ( size.x == 768 && size.y == 480 ) e = DM_768x480;
else if ( size.x == 768 && size.y == 576 ) e = DM_768x576;

View File

@ -50,7 +50,11 @@ uf::stl::string uf::checkpoint::traverse( pod::Checkpoint* checkpoint ) {
case pod::Checkpoint::BEGIN: type = "BEGIN"; break;
case pod::Checkpoint::END: type = "END"; break;
}
#if UF_USE_FMT
res.emplace( res.begin(), ::fmt::format("[{}] [{}]: {}", type, checkpoint->info, checkpoint->name) );
#else
res.emplace( res.begin(), "[" + type + "] [" + checkpoint->info + "]: " + checkpoint->name );
#endif
checkpoint = checkpoint->previous;
}

View File

@ -53,12 +53,14 @@ void uf::console::initialize() {
// this could probably be its own function
uf::stl::string s_result = "";
#if UF_USE_FMT
for ( auto i = 0; i < results.size(); ++i ) {
auto& res = results[i];
if ( res.is<uf::stl::string>() ) s_result += ::fmt::format("\n[{}] => {}", i, res.as<uf::stl::string>());
else if ( res.is<ext::json::Value>() ) s_result += ::fmt::format("\n[{}] => {}", i, ext::json::encode( res.as<ext::json::Value>() ));
else s_result += ::fmt::format("\n[{}] => Userdata: {}", i, (void*) res);
}
#endif
return "Hook executed: " + match[1] + s_result;
});
@ -98,7 +100,11 @@ void uf::console::initialize() {
};
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
#if UF_USE_FMT
res += ::fmt::format("Scene: {}: {}\n", scene->getName(), scene->getUid());
#else
res += "Scene: " + scene->getName() + ": " + std::to_string(scene->getUid()) + "\n";
#endif
scene->process(filter, 1);
}

View File

@ -1,4 +1,5 @@
#include <uf/utils/io/inputs.h>
#include <uf/utils/string/ext.h>
uf::inputs::state_t uf::inputs::kbm::states::LShift = false;
uf::inputs::state_t uf::inputs::kbm::states::RShift = false;

View File

@ -1,5 +1,6 @@
#include <uf/utils/math/physics.h>
#include <uf/engine/object/object.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/math/physics.h>
#include <iostream>
/*

View File

@ -49,6 +49,7 @@ namespace {
}
void load_migoto( uf::Object& self, const uf::Serializer& json ) {
#if !UF_ENV_DREAMCAST
struct Position {
pod::Vector3f position;
pod::Vector3f normal;
@ -130,6 +131,7 @@ namespace {
mesh.insertIndices<uint32_t>( indices );
uf::graph::convert( self );
#endif
}
}
void ext::CraetureBehavior::initialize( uf::Object& self ) {

View File

@ -69,8 +69,13 @@ namespace {
};
struct {
#if UF_USE_FREETYPE
ext::freetype::Glyph glyph;
uf::stl::unordered_map<uf::stl::string, uf::stl::unordered_map<size_t, uf::Glyph>> cache;
#else
char glyph;
uf::stl::unordered_map<uf::stl::string, uf::stl::unordered_map<size_t, char>> cache;
#endif
} glyphs;
struct {
@ -96,12 +101,14 @@ namespace {
}
uf::stl::vector<::GlyphBox> generateGlyphs( uf::Object& self, const uf::stl::string& _string ) {
uf::stl::vector<::GlyphBox> gs;
#if UF_USE_FREETYPE
auto& glyphs = ::glyphs;
auto& metadata = this->getComponent<ext::GuiGlyphBehavior::Metadata>();
auto& metadataGui = this->getComponent<ext::GuiBehavior::Metadata>();
auto& transform = this->getComponent<pod::Transform<>>();
uf::stl::vector<::GlyphBox> gs;
auto string = _string == "" ? metadata.string : _string;
auto font = uf::io::root+"/fonts/" + metadata.font;
@ -311,6 +318,7 @@ namespace {
gs.push_back(g);
}
#endif
return gs;
}
@ -354,6 +362,7 @@ void ext::GuiGlyphBehavior::initialize( uf::Object& self ) {
metadataGui.scaleMode = "none";
// generate texture
#if UF_USE_FREETYPE
{
atlas.clear();
@ -393,6 +402,7 @@ void ext::GuiGlyphBehavior::initialize( uf::Object& self ) {
atlas.generate();
atlas.clear(false);
}
#endif
// generate mesh
{

View File

@ -414,10 +414,12 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
TIMER(0.25, keys.vee ) {
bool state = !stats.noclipped;
metadata.system.noclipped = state;
#if UF_USE_REACTPHYSICS
if ( collider.body ) {
collider.body->enableGravity(!state);
uf::physics::impl::activateCollision(collider, !state);
}
#endif
stats.noclipped = state;
UF_MSG_DEBUG( "{}abled noclip: {}", (state ? "En" : "Dis"), uf::vector::toString(transform.position));

View File

@ -14,6 +14,8 @@
#include <uf/engine/asset/asset.h>
#include <uf/engine/asset/masterdata.h>
#include <uf/engine/scene/scene.h>
#include <uf/engine/graph/graph.h>
#include <uf/utils/io/inputs.h>
#include <uf/utils/renderer/renderer.h>
@ -330,7 +332,11 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
for ( uf::Scene* scene : uf::scene::scenes ) {
if ( !scene ) continue;
#if UF_USE_FMT
uf::iostream << ::fmt::format("Scene: {}\n", uf::string::toString( *scene ));
#else
uf::iostream << "Scene: " << uf::string::toString( *scene ) << "\n";
#endif
scene->process([]( uf::Entity* entity, int depth ) {
uf::stl::string indent = ""; for ( auto i = 1; i < depth; ++i ) indent += "\t";
uf::stl::string location = "";
@ -340,7 +346,11 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
location = uf::string::toString( t.position ) + " " + uf::string::toString( t.orientation );
}
#if UF_USE_FMT
uf::iostream << ::fmt::format("{} {} {}\n", indent, uf::string::toString( *entity ), location );
#else
uf::iostream << indent << " " << uf::string::toString( *entity ) << " " << location << "\n";
#endif
}, 1);
}
}

View File

@ -11,7 +11,6 @@
#include <uf/utils/hook/hook.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/string/string.h>
#include <uf/utils/string/ext.h>
@ -34,6 +33,8 @@
#include <uf/engine/scene/scene.h>
#include <uf/engine/asset/asset.h>
#include <uf/utils/math/physics.h>
#include <uf/ext/ext.h>
#include <uf/ext/oal/oal.h>
#include <uf/ext/discord/discord.h>
@ -107,7 +108,11 @@ namespace {
}
void EXT_API ext::load() {
#if UF_ENV_DREAMCAST
ext::config.readFromFile("/cd/data/config.json");
#else
ext::config.readFromFile(uf::io::root+"/config.json");
#endif
}
void EXT_API ext::load( ext::json::Value& json ) {
::config.engine.gc.enabled = json["engine"]["debug"]["garbage collection"]["enabled"].as(::config.engine.gc.enabled);

View File

@ -6,6 +6,6 @@ RENDERER = opengl
TARGET_EXTENSION = elf
OPTIMIZATIONS = -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -fstrict-aliasing -ffast-math -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer -DUF_NO_EXCEPTIONS -fno-exceptions # -g # -flto
WARNINGS = -Wno-attributes -Wno-conversion-null
FLAGS += $(KOS_CPPFLAGS) -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always
FLAGS += $(KOS_CPPFLAGS) -m4-single-only -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always
INCS += $(KOS_INC_PATHS) -I/opt/dreamcast/sh-elf/sh-elf/include
LIBS += $(KOS_LIB_PATHS) -L/opt/dreamcast/sh-elf/sh-elf/lib