Compare commits

..

11 Commits

Author SHA1 Message Date
84a507da38 Port input system 2025-06-09 11:59:42 +02:00
21a5e18e3b (theoretically) Port audio system 2025-06-09 11:43:56 +02:00
1b6007c323 Reintroduce const correctness 2025-06-09 11:33:34 +02:00
6a05210aa1 Convert audio hans RAW files 2025-06-09 11:04:08 +02:00
f13d50a9e1 Initialize textures from assets 2025-06-09 10:56:30 +02:00
f65f4e3e55 Manually scale textures to correct sizes 2025-06-09 10:49:59 +02:00
3298623305 Try to port renderer 2025-06-09 10:49:59 +02:00
f6adc18215 Integrate Hall and riscv target 2025-06-09 10:49:59 +02:00
1b8d4e8c70 Remove SDL dependency 2025-06-09 10:49:59 +02:00
9d09b70bae Prepare port 2025-06-09 10:49:59 +02:00
49f45423d1 Port to entt 2025-06-09 10:49:59 +02:00
18 changed files with 86 additions and 178 deletions

17
.vscode/launch.json vendored
View File

@@ -1,17 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Launch",
"program": "${workspaceFolder}/build/HansTheGatherer",
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

Binary file not shown.

Binary file not shown.

BIN
assets/sounds/hit.raw Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/sounds/pickup.raw Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -16,7 +16,7 @@ namespace Hall
/// <param name="width">The width of the excerpt</param> /// <param name="width">The width of the excerpt</param>
/// <param name="height">The height of the excerpt</param> /// <param name="height">The height of the excerpt</param>
/// <param name="dataWidth">The width of the image (NOT EXCERPT)</param> /// <param name="dataWidth">The width of the image (NOT EXCERPT)</param>
void Draw(unsigned short* data, unsigned short xOffset, unsigned short yOffset, unsigned short screenX, unsigned short screenY, unsigned short width, unsigned short height, unsigned short dataWidth); void Draw(const unsigned short* data, unsigned short xOffset, unsigned short yOffset, unsigned short screenX, unsigned short screenY, unsigned short width, unsigned short height, unsigned short dataWidth);
/// <summary> /// <summary>
/// Clears the whole screen with the given color /// Clears the whole screen with the given color
@@ -24,7 +24,7 @@ namespace Hall
/// <param name="color">The format is R5G5B5A1, with the alpha bit being lsb</param> /// <param name="color">The format is R5G5B5A1, with the alpha bit being lsb</param>
void Clear(unsigned short color); void Clear(unsigned short color);
void SetData(unsigned short* data); void SetData(const unsigned short* data);
void SetXOffset(unsigned short xOffset); void SetXOffset(unsigned short xOffset);
void SetYOffset(unsigned short yOffset); void SetYOffset(unsigned short yOffset);
void SetImageWidth(unsigned short imageWidth); void SetImageWidth(unsigned short imageWidth);

View File

@@ -1,7 +1,7 @@
#include <Hall/Video.h> #include <Hall/Video.h>
volatile char* GPU_START = (char*)0x02000000; volatile char* GPU_START = (char*)0x02000000;
volatile unsigned short** GPU_IMAGE_START = (volatile unsigned short**)(GPU_START + 0); volatile unsigned short const** GPU_IMAGE_START = (volatile unsigned short const**)(GPU_START + 0);
volatile unsigned short* GPU_IMAGE_X_OFFSET = (volatile unsigned short*)(GPU_START + 4); volatile unsigned short* GPU_IMAGE_X_OFFSET = (volatile unsigned short*)(GPU_START + 4);
volatile unsigned short* GPU_IMAGE_Y_OFFSET = (volatile unsigned short*)(GPU_START + 8); volatile unsigned short* GPU_IMAGE_Y_OFFSET = (volatile unsigned short*)(GPU_START + 8);
volatile unsigned short* GPU_IMAGE_WIDTH = (volatile unsigned short*)(GPU_START + 12); volatile unsigned short* GPU_IMAGE_WIDTH = (volatile unsigned short*)(GPU_START + 12);
@@ -19,7 +19,7 @@ volatile bool* GPU_COMMAND_SWAP_BUFFERS = (volatile bool*)(GPU_START + 56);
volatile bool* VSYNC_BUFFER_SWAP = (volatile bool*)(GPU_START + 60); volatile bool* VSYNC_BUFFER_SWAP = (volatile bool*)(GPU_START + 60);
void Hall::Draw(unsigned short* data, unsigned short xOffset, unsigned short yOffset, unsigned short screenX, unsigned short screenY, unsigned short width, unsigned short height, unsigned short dataWidth) void Hall::Draw(const unsigned short* data, unsigned short xOffset, unsigned short yOffset, unsigned short screenX, unsigned short screenY, unsigned short width, unsigned short height, unsigned short dataWidth)
{ {
*GPU_IMAGE_START = data; *GPU_IMAGE_START = data;
*GPU_IMAGE_X_OFFSET = xOffset; *GPU_IMAGE_X_OFFSET = xOffset;
@@ -39,7 +39,7 @@ void Hall::Clear(unsigned short color)
*GPU_COMMAND_CLEAR = true; *GPU_COMMAND_CLEAR = true;
} }
void Hall::SetData(unsigned short* data) void Hall::SetData(const unsigned short* data)
{ {
*GPU_IMAGE_START = data; *GPU_IMAGE_START = data;
} }

View File

@@ -20,104 +20,47 @@ static constexpr uint8_t BASKET_DATA[] = {
}; };
static constexpr uint8_t BACKGROUND_MUSIC_DATA[] = { static constexpr uint8_t BACKGROUND_MUSIC_DATA[] = {
#embed "../assets/sounds/JamaicanSunrise.wav" #embed "../assets/sounds/JamaicanSunrise.raw"
}; };
static constexpr uint8_t PICKUP_SOUND_DATA[] = { static constexpr uint8_t PICKUP_SOUND_DATA[] = {
#embed "../assets/sounds/pickup.wav" #embed "../assets/sounds/pickup.raw"
}; };
static constexpr uint8_t HIT_SOUND_DATA[] = { static constexpr uint8_t HIT_SOUND_DATA[] = {
#embed "../assets/sounds/hit.wav" #embed "../assets/sounds/hit.raw"
}; };
static constexpr uint8_t DEFAULT_FONT_DATA[] = {
#embed "../assets/fonts/OpenTTD-Sans.ttf"
};
// SDL_Texture* load_texture(uint8_t const* data, size_t size, SDL_Renderer* renderer)
// {
// auto* iostream = SDL_IOFromConstMem(data, size);
// SDL_Surface* surface = SDL_LoadBMP_IO(iostream, false);
// if (surface == nullptr)
// {
// // spdlog::error("Failed to load SDL surface!\nCause: {}", SDL_GetError());
// }
// SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
// if (texture == nullptr)
// {
// // spdlog::error("Failed to create texture from surface!\nCause: {}", SDL_GetError());
// }
// return texture;
// }
// AudioAsset load_audio(uint8_t const* data, size_t size)
// {
// AudioAsset audio_asset;
// auto* iostream = SDL_IOFromConstMem(data, size);
// bool res = SDL_LoadWAV_IO(
// iostream, false, &audio_asset.spec, &audio_asset.buffer, &audio_asset.buffer_length);
// if (!res)
// {
// // spdlog::error("Failed to load audio file!\nCause: {}", SDL_GetError());
// }
// return audio_asset;
// }
// FontAsset load_font(uint8_t const* data, size_t size)
// {
// FontAsset font_asset;
// auto* iostream = SDL_IOFromConstMem(data, size);
// auto* ttf = TTF_OpenFontIO(iostream, false, 20);
// font_asset.font = ttf;
// return font_asset;
// }
AssetModule::AssetModule(entt::registry& registry) AssetModule::AssetModule(entt::registry& registry)
{ {
// auto renderer = registry.ctx().get<SdlHandles>().renderer; TextureAtlasLayout background_layout{.width = 400, .height = 240, .rows = 1, .columns = 1};
TextureAtlasLayout fruits_layout{.width = 32, .height = 32, .rows = 6, .columns = 38};
TextureAtlasLayout spiders_layout{.width = 32, .height = 32, .rows = 2, .columns = 4};
TextureAtlasLayout basket_layout{.width = 64, .height = 32, .rows = 1, .columns = 1};
Texture background{.data = BACKGROUND_DATA,
.data_length = sizeof(BACKGROUND_DATA),
.texture_atlas_layout = background_layout};
Texture fruits{.data = FRUITS_DATA,
.data_length = sizeof(FRUITS_DATA),
.texture_atlas_layout = fruits_layout};
Texture spiders{.data = SPIDERS_DATA,
.data_length = sizeof(SPIDERS_DATA),
.texture_atlas_layout = spiders_layout};
Texture basket{.data = BASKET_DATA,
.data_length = sizeof(BASKET_DATA),
.texture_atlas_layout = basket_layout};
// auto* background = load_texture(BACKGROUND_DATA, sizeof(BACKGROUND_DATA), renderer); registry.ctx().emplace<TextureAssets>(TextureAssets{
TextureAtlasLayout background_layout = {.width = 400, .height = 240, .rows = 1, .columns = 1}; .background = background, .fruits = fruits, .spiders = spiders, .basket = basket});
// auto* fruits = load_texture(FRUITS_DATA, sizeof(FRUITS_DATA), renderer); AudioAsset background_music{.buffer = BACKGROUND_MUSIC_DATA,
TextureAtlasLayout fruits_layout = {.width = 32, .height = 32, .rows = 6, .columns = 38}; .buffer_length = sizeof(BACKGROUND_MUSIC_DATA)};
AudioAsset pickup_sound{.buffer = PICKUP_SOUND_DATA,
// auto* spiders = load_texture(SPIDERS_DATA, sizeof(SPIDERS_DATA), renderer); .buffer_length = sizeof(PICKUP_SOUND_DATA)};
TextureAtlasLayout spiders_layout = {.width = 32, .height = 32, .rows = 2, .columns = 4}; AudioAsset hit_sound{.buffer = HIT_SOUND_DATA, .buffer_length = sizeof(HIT_SOUND_DATA)};
registry.ctx().emplace<AudioAssets>(AudioAssets{.background_music = background_music,
// auto* basket = load_texture(BASKET_DATA, sizeof(BASKET_DATA), renderer); .pickup_sound = pickup_sound,
TextureAtlasLayout basket_layout = {.width = 64, .height = 32, .rows = 1, .columns = 1}; .hit_sound = hit_sound});
// registry.ctx().emplace<TextureAssets>(TextureAssets{
// .background = Texture{.sdl_texture = background, .texture_atlas_layout =
// background_layout}, .fruits = Texture{.sdl_texture = fruits, .texture_atlas_layout =
// fruits_layout}, .spiders = Texture{.sdl_texture = spiders, .texture_atlas_layout =
// spiders_layout}, .basket = Texture{.sdl_texture = basket, .texture_atlas_layout =
// basket_layout}});
registry.ctx().emplace<TextureAssets>(
TextureAssets{.background = Texture{.texture_atlas_layout = background_layout},
.fruits = Texture{.texture_atlas_layout = fruits_layout},
.spiders = Texture{.texture_atlas_layout = spiders_layout},
.basket = Texture{.texture_atlas_layout = basket_layout}});
// auto background_music = load_audio(BACKGROUND_MUSIC_DATA, sizeof(BACKGROUND_MUSIC_DATA));
// auto pickup_sound = load_audio(PICKUP_SOUND_DATA, sizeof(PICKUP_SOUND_DATA));
// auto hit_sound = load_audio(HIT_SOUND_DATA, sizeof(HIT_SOUND_DATA));
registry.ctx().emplace<AudioAssets>(AudioAssets{
.background_music = {.buffer = BACKGROUND_MUSIC_DATA,
.buffer_length = sizeof(BACKGROUND_MUSIC_DATA)},
.pickup_sound = {.buffer = PICKUP_SOUND_DATA, .buffer_length = sizeof(PICKUP_SOUND_DATA)},
.hit_sound = {.buffer = HIT_SOUND_DATA, .buffer_length = sizeof(HIT_SOUND_DATA)}});
// registry.ctx().emplace<AudioAssets>(AudioAssets{.background_music = background_music,
// .pickup_sound = pickup_sound,
// .hit_sound = hit_sound});
// auto font = load_font(DEFAULT_FONT_DATA, sizeof(DEFAULT_FONT_DATA)); // auto font = load_font(DEFAULT_FONT_DATA, sizeof(DEFAULT_FONT_DATA));
// registry.ctx().emplace<FontAssets>(FontAssets{.default_font = font}); // registry.ctx().emplace<FontAssets>(FontAssets{.default_font = font});

View File

@@ -14,7 +14,7 @@ struct TextureAtlasLayout
struct Texture struct Texture
{ {
uint8_t* data; uint8_t const* data;
uint32_t data_length; uint32_t data_length;
TextureAtlasLayout texture_atlas_layout; TextureAtlasLayout texture_atlas_layout;
}; };

View File

@@ -3,29 +3,8 @@
AudioModule::AudioModule(entt::registry& registry) AudioModule::AudioModule(entt::registry& registry)
{ {
// auto const& audio_assets = registry.ctx().get<AudioAssets>(); auto const& audio_assets = registry.ctx().get<AudioAssets>();
// auto* music_stream = SDL_OpenAudioDeviceStream(
// SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio_assets.background_music.spec, NULL, NULL);
// auto* sound_stream = SDL_OpenAudioDeviceStream(
// SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio_assets.pickup_sound.spec, NULL, NULL);
// SDL_ResumeAudioStreamDevice(music_stream); registry.ctx().emplace<AudioStreams>(AudioStreams{.music_stream = {.id_left = 0, .id_right = 1},
// SDL_ResumeAudioStreamDevice(sound_stream); .sound_stream = {.id_mono = 2}});
// registry.ctx().emplace<AudioStreams>(
// AudioStreams{.music_stream = music_stream, .sound_stream = sound_stream});
} }
// void AudioModule::FeedAudioStreams(entt::registry& registry)
// {
// auto audio_streams = registry.ctx().get<AudioStreams>();
// auto audio_assets = registry.ctx().get<AudioAssets>();
// if (SDL_GetAudioStreamQueued(audio_streams.music_stream) <
// static_cast<int>(audio_assets.background_music.buffer_length))
// {
// SDL_PutAudioStreamData(audio_streams.music_stream,
// audio_assets.background_music.buffer,
// audio_assets.background_music.buffer_length);
// }
// }

View File

@@ -5,19 +5,28 @@
struct AudioAsset struct AudioAsset
{ {
// SDL_AudioSpec spec;
uint8_t const* buffer; uint8_t const* buffer;
uint32_t buffer_length; uint32_t buffer_length;
}; };
// struct AudioStreams struct MonoChannel
// { {
// SDL_AudioStream* music_stream; int id_mono;
// SDL_AudioStream* sound_stream; };
// };
struct StereoChannel
{
int id_left;
int id_right;
};
struct AudioStreams
{
StereoChannel music_stream;
MonoChannel sound_stream;
};
struct AudioModule struct AudioModule
{ {
AudioModule(entt::registry& registry); AudioModule(entt::registry& registry);
// static void FeedAudioStreams(entt::registry& registry);
}; };

View File

@@ -1,10 +1,15 @@
#pragma once #pragma once
#include <cstdint>
#include <set> #include <set>
enum Key : uint8_t
{
Left,
Right
};
struct ButtonInput struct ButtonInput
{ {
std::set<int> pressed; std::set<Key> pressed;
std::set<int> just_pressed;
std::set<int> just_released;
}; };

View File

@@ -1,9 +1,20 @@
#include "level.hpp" #include "level.hpp"
#include "input.hpp" #include "input.hpp"
#include <Hall/Hall.h>
LevelModule::LevelModule(entt::registry& registry) LevelModule::LevelModule(entt::registry& registry)
{ {
auto const* texture_assets = &registry.ctx().get<TextureAssets>(); auto const* texture_assets = &registry.ctx().get<TextureAssets>();
auto const* audio_steams = &registry.ctx().get<AudioStreams>();
auto const* audio_assets = &registry.ctx().get<AudioAssets>();
// Hall::SetupStereo(audio_steams->music_stream.id_left,
// audio_steams->music_stream.id_right,
// audio_assets->background_music.buffer,
// audio_assets->background_music.buffer_length / (2 * 2),
// 0,
// audio_assets->background_music.buffer_length / (2 * 2));
auto background = registry.create(); auto background = registry.create();
registry.emplace<Position>(background, Position{.x = 0, .y = 0}); registry.emplace<Position>(background, Position{.x = 0, .y = 0});

View File

@@ -35,41 +35,17 @@ int main()
bool exit_gameloop = false; bool exit_gameloop = false;
while (!exit_gameloop) while (!exit_gameloop)
{ {
auto* input = &registry.ctx().get<ButtonInput>();
// Clear just pressed/released
input->just_pressed.clear();
input->just_released.clear();
// Input // Input
// SDL_Event event; auto* input = &registry.ctx().get<ButtonInput>();
// while (SDL_PollEvent(&event)) if (Hall::GetLeft(0))
// { input->pressed.insert(Key::Left);
// switch (event.type) else
// { input->pressed.erase(Key::Left);
// case SDL_EVENT_QUIT:
// exit_gameloop = true;
// break;
// case SDL_EVENT_KEY_DOWN:
// if (event.key.key == SDLK_ESCAPE)
// {
// exit_gameloop = true;
// }
// if (input->pressed.insert(event.key.key).second)
// {
// input->just_pressed.insert(event.key.key);
// }
// break;
// case SDL_EVENT_KEY_UP:
// if (input->pressed.erase(event.key.key) != 0)
// {
// input->just_released.insert(event.key.key);
// }
// break;
// }
// }
// AudioModule::FeedAudioStreams(registry); if (Hall::GetRight(0))
input->pressed.insert(Key::Right);
else
input->pressed.erase(Key::Right);
if (registry.ctx().get<Game>().time != 0) if (registry.ctx().get<Game>().time != 0)
{ {

View File

@@ -20,13 +20,15 @@ void RenderModule::RenderSprites(entt::registry& registry)
registry.view<Position const, Size const, Sprite const>(entt::exclude<Background>); registry.view<Position const, Size const, Sprite const>(entt::exclude<Background>);
auto background_view = registry.view<Position const, Size const, Sprite const, Background>(); auto background_view = registry.view<Position const, Size const, Sprite const, Background>();
auto render_sprite = [](entt::entity entity, Position const& pos, Size const& size, Sprite const&sprite){ auto render_sprite =
[](entt::entity entity, Position const& pos, Size const& size, Sprite const& sprite)
{
TextureAtlasLayout layout = sprite.texture->texture_atlas_layout; TextureAtlasLayout layout = sprite.texture->texture_atlas_layout;
uint8_t row = sprite.texture_atlas_index / layout.columns; uint8_t row = sprite.texture_atlas_index / layout.columns;
uint8_t column = sprite.texture_atlas_index % layout.columns; uint8_t column = sprite.texture_atlas_index % layout.columns;
// Problemchen: Wir können die Sprites nicht strecken... hat keiner Interpolation // Problemchen: Wir können die Sprites nicht strecken... hat keiner Interpolation
// implementiert? // implementiert?
Hall::Draw(reinterpret_cast<unsigned short*>(sprite.texture->data), // Das ist 100% UB Hall::Draw(reinterpret_cast<unsigned short const*>(sprite.texture->data), // Das ist 100% UB
column * layout.width, column * layout.width,
row * layout.height, row * layout.height,
pos.x, pos.x,