Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84a507da38 | |||
| 21a5e18e3b | |||
| 1b6007c323 | |||
| 6a05210aa1 | |||
| f13d50a9e1 | |||
| f65f4e3e55 | |||
| 3298623305 | |||
| f6adc18215 | |||
| 1b8d4e8c70 | |||
| 9d09b70bae |
@@ -1,25 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.24)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
|
||||||
project(HansTheGatherer)
|
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/riscv-toolchain.cmake)
|
||||||
|
|
||||||
|
project(HansTheGatherer C CXX ASM)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
# Option to switch real platform vs. SDL implementation...
|
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(
|
|
||||||
SDL3
|
|
||||||
URL https://github.com/libsdl-org/SDL/releases/download/release-3.2.14/SDL3-3.2.14.tar.gz
|
|
||||||
OVERRIDE_FIND_PACKAGE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(SDL3)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
SDL3_ttf
|
|
||||||
URL https://github.com/libsdl-org/SDL_ttf/releases/download/release-3.2.2/SDL3_ttf-3.2.2.tar.gz
|
|
||||||
OVERRIDE_FIND_PACKAGE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(SDL3_ttf)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
entt
|
entt
|
||||||
@@ -27,11 +14,23 @@ FetchContent_Declare(
|
|||||||
OVERRIDE_FIND_PACKAGE
|
OVERRIDE_FIND_PACKAGE
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(entt)
|
FetchContent_MakeAvailable(entt)
|
||||||
|
|
||||||
find_package(entt CONFIG REQUIRED)
|
find_package(entt CONFIG REQUIRED)
|
||||||
|
|
||||||
find_package(SDL3 CONFIG REQUIRED)
|
add_library(RISCV_Options INTERFACE)
|
||||||
find_package(SDL3_ttf CONFIG REQUIRED)
|
target_compile_options(RISCV_Options INTERFACE
|
||||||
find_package(spdlog CONFIG REQUIRED)
|
-fno-exceptions
|
||||||
|
-fno-unwind-tables
|
||||||
|
-fno-rtti
|
||||||
|
-fno-pic # PIC?
|
||||||
|
-mno-relax
|
||||||
|
-march=rv32im
|
||||||
|
-mabi=ilp32
|
||||||
|
-std=c++20
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(lib)
|
||||||
|
add_subdirectory(wuehans)
|
||||||
|
|
||||||
add_executable(HansTheGatherer
|
add_executable(HansTheGatherer
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
@@ -42,6 +41,20 @@ add_executable(HansTheGatherer
|
|||||||
src/render.cpp
|
src/render.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(HansTheGatherer SDL3::SDL3 SDL3_ttf::SDL3_ttf EnTT spdlog::spdlog)
|
target_link_options(HansTheGatherer PRIVATE
|
||||||
|
-nostartfiles
|
||||||
|
-Wl,--gc-sections
|
||||||
|
-march=rv32im
|
||||||
|
-mabi=ilp32
|
||||||
|
-lstdc++
|
||||||
|
-lc
|
||||||
|
-lgcc
|
||||||
|
-mcmodel=medany
|
||||||
|
)
|
||||||
|
|
||||||
set_property(TARGET HansTheGatherer PROPERTY CXX_STANDARD 20)
|
target_link_libraries(HansTheGatherer PRIVATE
|
||||||
|
RISCV_Options
|
||||||
|
WueHans
|
||||||
|
Hall
|
||||||
|
EnTT
|
||||||
|
)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 912 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 375 KiB |
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 32 KiB |
BIN
assets/sounds/hit.raw
Normal file
BIN
assets/sounds/pickup.raw
Normal file
19
cmake/riscv-toolchain.cmake
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
set(CMAKE_SYSTEM_NAME Generic)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR riscv)
|
||||||
|
|
||||||
|
set(RISCV_PREFIX riscv32-unknown-elf)
|
||||||
|
set(CMAKE_C_COMPILER ${RISCV_PREFIX}-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER ${RISCV_PREFIX}-g++)
|
||||||
|
set(CMAKE_ASM_COMPILER ${RISCV_PREFIX}-gcc)
|
||||||
|
|
||||||
|
set(CMAKE_FIND_ROOT_PATH root)
|
||||||
|
|
||||||
|
# Don't run the linker on compiler check
|
||||||
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||||
|
|
||||||
|
# adjust the default behavior of the FIND_XXX() commands:
|
||||||
|
# search programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
# search headers and libraries in the target environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
1
lib/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add_subdirectory(Hall)
|
||||||
11
lib/Hall/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
add_library(Hall STATIC
|
||||||
|
source/Audio.cpp
|
||||||
|
source/System.cpp
|
||||||
|
source/Video.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Hall
|
||||||
|
PUBLIC SYSTEM include
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Hall PRIVATE RISCV_Options)
|
||||||
2
lib/Hall/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Hall
|
||||||
|
Hallo, hier ist Hall
|
||||||
63
lib/Hall/include/Hall/Audio.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Hall
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the global volume. 0 is muted, 128 is the default, 255 is max
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">0 is muted, 128 is the default, 255 is max</param>
|
||||||
|
void SetGlobalVolume(unsigned char volume);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares a channel to be used to play a non-looped single-channel audio
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelID">The ID of the channel. Must be within [0,7]</param>
|
||||||
|
/// <param name="data">A pointer to the first sample of the audio data</param>
|
||||||
|
/// <param name="sampleCount">The total number of samples in the audio data</param>
|
||||||
|
/// <param name="volume">The channel's local volume. 0 is muted, 128 is the default, 255 is max</param>
|
||||||
|
void SetupMono(int channelID, short* data, int sampleCount, unsigned char volume = 128);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares a channel to be used to play a looped single-channel audio
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelID">The ID of the channel. Must be within [0,7]</param>
|
||||||
|
/// <param name="data">A pointer to the first sample of the audio data</param>
|
||||||
|
/// <param name="sampleCount">The total number of samples in the audio data</param>
|
||||||
|
/// <param name="loopStart">The index of the first sample of the loop (inclusive)</param>
|
||||||
|
/// <param name="loopEnd">The index of the last sample of the loop (exclusive?)</param>
|
||||||
|
/// <param name="volume">The channel's local volume. 0 is muted, 128 is the default, 255 is max</param>
|
||||||
|
void SetupMono(int channelID, short* data, int sampleCount, unsigned int loopStart, unsigned int loopEnd, unsigned char volume = 128);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares two channels to be used to play a non-looped stereo audio
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelID_left">The ID of the channel for the left audio. Must be within [0,7]</param>
|
||||||
|
/// <param name="channelID_right">The ID of the channel for the right audio. Must be within [0,7]</param>
|
||||||
|
/// <param name="data">A pointer to the first sample of the audio data</param>
|
||||||
|
/// <param name="sampleCount">The total number of samples PER CHANNEL in the audio data</param>
|
||||||
|
/// <param name="volume">The channel's local volume. 0 is muted, 128 is the default, 255 is max</param>
|
||||||
|
void SetupStereo(int channelID_left, int channelID_right, short* data, int sampleCount, unsigned char volume = 128);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares two channels to be used to play a looped stereo audio
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelID_left">The ID of the channel for the left audio. Must be within [0,7]</param>
|
||||||
|
/// <param name="channelID_right">The ID of the channel for the right audio. Must be within [0,7]</param>
|
||||||
|
/// <param name="data">A pointer to the first sample of the audio data</param>
|
||||||
|
/// <param name="sampleCount">The total number of samples PER CHANNEL in the audio data</param>
|
||||||
|
/// <param name="loopStart">The index of the first sample of the loop (inclusive)</param>
|
||||||
|
/// <param name="loopEnd">The index of the last sample of the loop (exclusive?)</param>
|
||||||
|
/// <param name="volume">The channel's local volume. 0 is muted, 128 is the default, 255 is max</param>
|
||||||
|
void SetupStereo(int channelID_left, int channelID_right, short* data, int sampleCount, unsigned int loopStart, unsigned int loopEnd, unsigned char volume = 128);
|
||||||
|
|
||||||
|
|
||||||
|
void Play(unsigned char channelSelect);
|
||||||
|
void Pause(unsigned char channelSelect);
|
||||||
|
void SetData(unsigned char channelSelect, short* data);
|
||||||
|
void SetLoop(unsigned char channelSelect, bool isLooping);
|
||||||
|
void SetLoopBoundaries(unsigned char channelSelect, int start, int end);
|
||||||
|
void SetPosition(unsigned char channelSelect, int position);
|
||||||
|
void SetSample(unsigned char channelSelect, short sample);
|
||||||
|
void SetVolume(unsigned char channelSelect, unsigned char volume);
|
||||||
|
|
||||||
|
}
|
||||||
5
lib/Hall/include/Hall/Hall.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Hall/System.h>
|
||||||
|
#include <Hall/Video.h>
|
||||||
|
#include <Hall/Audio.h>
|
||||||
36
lib/Hall/include/Hall/System.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Hall
|
||||||
|
{
|
||||||
|
static const int SYSTEM_CLK_FREQUENCY = 50000000; //50 MHz
|
||||||
|
static void* const SDRAM_START = 0x0; //Start of the RAM. It is 32 MB large
|
||||||
|
static void* const BOOTLOADER_START = (void* const) 0x02010000; //Start of the bootloader. It is 32 kB large
|
||||||
|
static void* const SD_CARD_START = (void* const) 0x80000000; //Start of the SD-Card
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an 8-Byte int, that represents the number of ticks that passed since the system's boot-up. Divide by SYSTEM_CLK_FREQUENCY to get seconds
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The system time since boot-up in ticks</returns>
|
||||||
|
unsigned long long GetSystemTime();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the state of all buttons on the controller.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Must be in the range [0,1]</param>
|
||||||
|
/// <returns>Each button corresponds to one bit: 0 - B, 1 - Y, 2 - Select, 3 - Start, 4 - Up, 5 - Down, 6 - Left, 7 - Right, 8 - A, 9 - X, 10 - L, 11 - R</returns>
|
||||||
|
unsigned short GetController(int id);
|
||||||
|
|
||||||
|
unsigned int GetSystemTimeExcerpt(int precision);
|
||||||
|
bool GetA(unsigned short controller);
|
||||||
|
bool GetB(unsigned short controller);
|
||||||
|
bool GetX(unsigned short controller);
|
||||||
|
bool GetY(unsigned short controller);
|
||||||
|
bool GetStart(unsigned short controller);
|
||||||
|
bool GetSelect(unsigned short controller);
|
||||||
|
bool GetUp(unsigned short controller);
|
||||||
|
bool GetDown(unsigned short controller);
|
||||||
|
bool GetLeft(unsigned short controller);
|
||||||
|
bool GetRight(unsigned short controller);
|
||||||
|
bool GetL(unsigned short controller);
|
||||||
|
bool GetR(unsigned short controller);
|
||||||
|
}
|
||||||
43
lib/Hall/include/Hall/Video.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Hall
|
||||||
|
{
|
||||||
|
const int SCREEN_HEIGHT = 240;
|
||||||
|
const int SCREEN_WIDTH = 400;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws an excerpt of the given data onto the screen. All coordinates describe the top-left corner
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">A pointer to the first pixel of an image</param>
|
||||||
|
/// <param name="xOffset">The x offset within that image</param>
|
||||||
|
/// <param name="yOffset">The y offset within that image</param>
|
||||||
|
/// <param name="screenX">The x position on screen.</param>
|
||||||
|
/// <param name="screenY">The y position on screen.</param>
|
||||||
|
/// <param name="width">The width of the excerpt</param>
|
||||||
|
/// <param name="height">The height of the excerpt</param>
|
||||||
|
/// <param name="dataWidth">The width of the image (NOT EXCERPT)</param>
|
||||||
|
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>
|
||||||
|
/// Clears the whole screen with the given color
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The format is R5G5B5A1, with the alpha bit being lsb</param>
|
||||||
|
void Clear(unsigned short color);
|
||||||
|
|
||||||
|
void SetData(const unsigned short* data);
|
||||||
|
void SetXOffset(unsigned short xOffset);
|
||||||
|
void SetYOffset(unsigned short yOffset);
|
||||||
|
void SetImageWidth(unsigned short imageWidth);
|
||||||
|
void SetWidth(unsigned short width);
|
||||||
|
void SetHeight(unsigned short height);
|
||||||
|
void SetScreenX(unsigned short x);
|
||||||
|
void SetScreenY(unsigned short y);
|
||||||
|
void SetClearColor(unsigned short color);
|
||||||
|
void SetCommandDraw();
|
||||||
|
void SetCommandClear();
|
||||||
|
void SetCommandSwapBuffers();
|
||||||
|
|
||||||
|
bool GetIsGPUBusy();
|
||||||
|
bool GetVSync();
|
||||||
|
bool GetHSync();
|
||||||
|
}
|
||||||
132
lib/Hall/source/Audio.cpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#include <Hall/Audio.h>
|
||||||
|
|
||||||
|
volatile char* AUDIO_START = (char*) 0x2000100;
|
||||||
|
volatile short** AUDIO_START_ADDRESS = (volatile short**)(AUDIO_START + 4);
|
||||||
|
volatile int* AUDIO_SAMPLE_COUNT = (volatile int*)(AUDIO_START + 8);
|
||||||
|
volatile int* AUDIO_LOOP_START = (volatile int*)(AUDIO_START + 12);
|
||||||
|
volatile int* AUDIO_LOOP_END = (volatile int*)(AUDIO_START + 16);
|
||||||
|
volatile int* AUDIO_CURRENT_POSITION = (volatile int*)(AUDIO_START + 20);
|
||||||
|
volatile short* AUDIO_LAST_SAMPLE = (volatile short*)(AUDIO_START + 24);
|
||||||
|
volatile unsigned char* AUDIO_VOLUME = (volatile unsigned char*)(AUDIO_START + 28);
|
||||||
|
volatile bool* AUDIO_IS_LOOPING = (volatile bool*)(AUDIO_START + 32);
|
||||||
|
volatile bool* AUDIO_IS_PLAYING = (volatile bool*)(AUDIO_START + 36);
|
||||||
|
volatile bool* AUDIO_IS_MONO = (volatile bool*)(AUDIO_START + 40);
|
||||||
|
volatile bool* AUDIO_IS_RIGHT = (volatile bool*)(AUDIO_START + 44);
|
||||||
|
unsigned char* AUDIO_GLOBAL_VOLUME = (unsigned char*)(AUDIO_START + 48); //I think we can skip volatile for these two
|
||||||
|
unsigned char* AUDIO_CHANNEL_SELECT = (unsigned char*)(AUDIO_START + 52); //Because they will never change and always address the same value
|
||||||
|
|
||||||
|
|
||||||
|
void Hall::SetGlobalVolume(unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_GLOBAL_VOLUME = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetupMono(int channelID, short* data, int sampleCount, unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = 1 << channelID;
|
||||||
|
*AUDIO_START_ADDRESS = data;
|
||||||
|
*AUDIO_SAMPLE_COUNT = sampleCount;
|
||||||
|
*AUDIO_CURRENT_POSITION = 0;
|
||||||
|
*AUDIO_VOLUME = volume;
|
||||||
|
*AUDIO_IS_LOOPING = false;
|
||||||
|
*AUDIO_IS_PLAYING = false;
|
||||||
|
*AUDIO_IS_MONO = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetupMono(int channelID, short* data, int sampleCount, unsigned int loopStart, unsigned int loopEnd, unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = 1 << channelID;
|
||||||
|
*AUDIO_START_ADDRESS = data;
|
||||||
|
*AUDIO_SAMPLE_COUNT = sampleCount;
|
||||||
|
*AUDIO_CURRENT_POSITION = 0;
|
||||||
|
*AUDIO_VOLUME = volume;
|
||||||
|
*AUDIO_IS_LOOPING = true;
|
||||||
|
*AUDIO_LOOP_START = loopStart;
|
||||||
|
*AUDIO_LOOP_END = loopEnd;
|
||||||
|
*AUDIO_IS_PLAYING = false;
|
||||||
|
*AUDIO_IS_MONO = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetupStereo(int channelID_left, int channelID_right, short* data, int sampleCount, unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = (1 << channelID_left) | (1 << channelID_right);
|
||||||
|
*AUDIO_START_ADDRESS = data;
|
||||||
|
*AUDIO_SAMPLE_COUNT = sampleCount;
|
||||||
|
*AUDIO_CURRENT_POSITION = 0;
|
||||||
|
*AUDIO_VOLUME = volume;
|
||||||
|
*AUDIO_IS_LOOPING = false;
|
||||||
|
*AUDIO_IS_PLAYING = false;
|
||||||
|
*AUDIO_IS_MONO = false;
|
||||||
|
*AUDIO_IS_RIGHT = false;
|
||||||
|
|
||||||
|
*AUDIO_CHANNEL_SELECT = 1 << channelID_right;
|
||||||
|
*AUDIO_IS_RIGHT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetupStereo(int channelID_left, int channelID_right, short* data, int sampleCount, unsigned int loopStart, unsigned int loopEnd, unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = (1 << channelID_left) | (1 << channelID_right);
|
||||||
|
*AUDIO_START_ADDRESS = data;
|
||||||
|
*AUDIO_SAMPLE_COUNT = sampleCount;
|
||||||
|
*AUDIO_CURRENT_POSITION = 0;
|
||||||
|
*AUDIO_VOLUME = volume;
|
||||||
|
*AUDIO_LOOP_START = loopStart;
|
||||||
|
*AUDIO_LOOP_END = loopEnd;
|
||||||
|
*AUDIO_IS_LOOPING = true;
|
||||||
|
*AUDIO_IS_PLAYING = false;
|
||||||
|
*AUDIO_IS_MONO = false;
|
||||||
|
*AUDIO_IS_RIGHT = false;
|
||||||
|
|
||||||
|
*AUDIO_CHANNEL_SELECT = 1 << channelID_right;
|
||||||
|
*AUDIO_IS_RIGHT = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::Play(unsigned char channelSelect)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_IS_PLAYING = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::Pause(unsigned char channelSelect)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_IS_PLAYING = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetData(unsigned char channelSelect, short* data)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_START_ADDRESS = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetLoop(unsigned char channelSelect, bool isLooping)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_IS_LOOPING;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetLoopBoundaries(unsigned char channelSelect, int start, int end)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_LOOP_START = start;
|
||||||
|
*AUDIO_LOOP_END = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetPosition(unsigned char channelSelect, int position)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_CURRENT_POSITION = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetSample(unsigned char channelSelect, short sample)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_LAST_SAMPLE = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetVolume(unsigned char channelSelect, unsigned char volume)
|
||||||
|
{
|
||||||
|
*AUDIO_CHANNEL_SELECT = channelSelect;
|
||||||
|
*AUDIO_VOLUME = volume;
|
||||||
|
}
|
||||||
90
lib/Hall/source/System.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include <Hall/System.h>
|
||||||
|
|
||||||
|
volatile char* SYSTEM_TIME = (volatile char*)0x02000300;
|
||||||
|
volatile unsigned int* SYSTEM_TIME_0 = (volatile unsigned int*)(SYSTEM_TIME + 0); //Least precise
|
||||||
|
volatile unsigned int* SYSTEM_TIME_1 = (volatile unsigned int*)(SYSTEM_TIME + 4);
|
||||||
|
volatile unsigned int* SYSTEM_TIME_2 = (volatile unsigned int*)(SYSTEM_TIME + 8);
|
||||||
|
volatile unsigned int* SYSTEM_TIME_3 = (volatile unsigned int*)(SYSTEM_TIME + 12);
|
||||||
|
volatile unsigned int* SYSTEM_TIME_4 = (volatile unsigned int*)(SYSTEM_TIME + 16);//Most precise
|
||||||
|
|
||||||
|
volatile char* CONTROLLER_START = (volatile char*)0x02000200;
|
||||||
|
volatile unsigned short* CONTROLLER_0 = (volatile unsigned short*)(CONTROLLER_START + 0);
|
||||||
|
volatile unsigned short* CONTROLLER_1 = (volatile unsigned short*)(CONTROLLER_START + 2);
|
||||||
|
|
||||||
|
unsigned long long Hall::GetSystemTime()
|
||||||
|
{
|
||||||
|
unsigned long long result = *SYSTEM_TIME_0;
|
||||||
|
result = result << 32;
|
||||||
|
result += *SYSTEM_TIME_4;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Hall::GetSystemTimeExcerpt(int precision)
|
||||||
|
{
|
||||||
|
return *(SYSTEM_TIME_0 + precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short Hall::GetController(int id)
|
||||||
|
{
|
||||||
|
return *(CONTROLLER_0 + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetA(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetB(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetX(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetY(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetStart(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetSelect(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetUp(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetDown(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetLeft(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetRight(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetL(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetR(unsigned short controller)
|
||||||
|
{
|
||||||
|
return controller & (1 << 11);
|
||||||
|
}
|
||||||
117
lib/Hall/source/Video.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include <Hall/Video.h>
|
||||||
|
|
||||||
|
volatile char* GPU_START = (char*)0x02000000;
|
||||||
|
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_Y_OFFSET = (volatile unsigned short*)(GPU_START + 8);
|
||||||
|
volatile unsigned short* GPU_IMAGE_WIDTH = (volatile unsigned short*)(GPU_START + 12);
|
||||||
|
volatile unsigned short* GPU_WIDTH = (volatile unsigned short*)(GPU_START + 16);
|
||||||
|
volatile unsigned short* GPU_HEIGHT = (volatile unsigned short*)(GPU_START + 20);
|
||||||
|
volatile unsigned short* GPU_SCREEN_X = (volatile unsigned short*)(GPU_START + 24);
|
||||||
|
volatile unsigned short* GPU_SCREEN_Y = (volatile unsigned short*)(GPU_START + 28);
|
||||||
|
volatile unsigned short* GPU_CLEAR_COLOR = (volatile unsigned short*)(GPU_START + 32);
|
||||||
|
volatile bool* GPU_COMMAND_DRAW = (volatile bool*)(GPU_START + 36);
|
||||||
|
volatile bool* GPU_COMMAND_CLEAR = (volatile bool*)(GPU_START + 40);
|
||||||
|
volatile bool* GPU_IS_BUSY = (volatile bool*)(GPU_START + 44);
|
||||||
|
volatile bool* GPU_VSYNC = (volatile bool*)(GPU_START + 48);
|
||||||
|
volatile bool* GPU_HSYNC = (volatile bool*)(GPU_START + 52);
|
||||||
|
volatile bool* GPU_COMMAND_SWAP_BUFFERS = (volatile bool*)(GPU_START + 56);
|
||||||
|
volatile bool* VSYNC_BUFFER_SWAP = (volatile bool*)(GPU_START + 60);
|
||||||
|
|
||||||
|
|
||||||
|
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_X_OFFSET = xOffset;
|
||||||
|
*GPU_IMAGE_Y_OFFSET = yOffset;
|
||||||
|
*GPU_IMAGE_WIDTH = dataWidth;
|
||||||
|
*GPU_WIDTH = width;
|
||||||
|
*GPU_HEIGHT = height;
|
||||||
|
*GPU_SCREEN_X = screenX;
|
||||||
|
*GPU_SCREEN_Y = screenY;
|
||||||
|
*GPU_COMMAND_DRAW = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Hall::Clear(unsigned short color)
|
||||||
|
{
|
||||||
|
*GPU_CLEAR_COLOR = color;
|
||||||
|
*GPU_COMMAND_CLEAR = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetData(const unsigned short* data)
|
||||||
|
{
|
||||||
|
*GPU_IMAGE_START = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetXOffset(unsigned short xOffset)
|
||||||
|
{
|
||||||
|
*GPU_IMAGE_X_OFFSET = xOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetYOffset(unsigned short yOffset)
|
||||||
|
{
|
||||||
|
*GPU_IMAGE_Y_OFFSET = yOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetImageWidth(unsigned short imageWidth)
|
||||||
|
{
|
||||||
|
*GPU_IMAGE_WIDTH = imageWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetWidth(unsigned short width)
|
||||||
|
{
|
||||||
|
*GPU_WIDTH = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetHeight(unsigned short height)
|
||||||
|
{
|
||||||
|
*GPU_HEIGHT = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Hall::SetScreenX(unsigned short x)
|
||||||
|
{
|
||||||
|
*GPU_SCREEN_X = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Hall::SetScreenY(unsigned short y)
|
||||||
|
{
|
||||||
|
*GPU_SCREEN_Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetClearColor(unsigned short color)
|
||||||
|
{
|
||||||
|
*GPU_CLEAR_COLOR = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetCommandDraw()
|
||||||
|
{
|
||||||
|
*GPU_COMMAND_DRAW = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetCommandClear()
|
||||||
|
{
|
||||||
|
*GPU_COMMAND_CLEAR = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hall::SetCommandSwapBuffers()
|
||||||
|
{
|
||||||
|
*GPU_COMMAND_SWAP_BUFFERS = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetIsGPUBusy()
|
||||||
|
{
|
||||||
|
return *GPU_IS_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetVSync()
|
||||||
|
{
|
||||||
|
return *GPU_VSYNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hall::GetHSync()
|
||||||
|
{
|
||||||
|
return *GPU_HSYNC;
|
||||||
|
}
|
||||||
102
src/assets.cpp
@@ -1,9 +1,7 @@
|
|||||||
#include "assets.hpp"
|
#include "assets.hpp"
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
#include "definitions.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
static constexpr uint8_t BACKGROUND_DATA[] = {
|
static constexpr uint8_t BACKGROUND_DATA[] = {
|
||||||
#embed "../assets/images/jungle.bmp"
|
#embed "../assets/images/jungle.bmp"
|
||||||
@@ -22,94 +20,48 @@ 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};
|
||||||
auto* background = load_texture(BACKGROUND_DATA, sizeof(BACKGROUND_DATA), renderer);
|
TextureAtlasLayout spiders_layout{.width = 32, .height = 32, .rows = 2, .columns = 4};
|
||||||
TextureAtlasLayout background_layout = {.width = 866, .height = 510, .rows = 1, .columns = 1};
|
TextureAtlasLayout basket_layout{.width = 64, .height = 32, .rows = 1, .columns = 1};
|
||||||
|
Texture background{.data = BACKGROUND_DATA,
|
||||||
auto* fruits = load_texture(FRUITS_DATA, sizeof(FRUITS_DATA), renderer);
|
.data_length = sizeof(BACKGROUND_DATA),
|
||||||
TextureAtlasLayout fruits_layout = {.width = 16, .height = 16, .rows = 6, .columns = 38};
|
.texture_atlas_layout = background_layout};
|
||||||
|
Texture fruits{.data = FRUITS_DATA,
|
||||||
auto* spiders = load_texture(SPIDERS_DATA, sizeof(SPIDERS_DATA), renderer);
|
.data_length = sizeof(FRUITS_DATA),
|
||||||
TextureAtlasLayout spiders_layout = {.width = 16, .height = 16, .rows = 2, .columns = 4};
|
.texture_atlas_layout = fruits_layout};
|
||||||
|
Texture spiders{.data = SPIDERS_DATA,
|
||||||
auto* basket = load_texture(BASKET_DATA, sizeof(BASKET_DATA), renderer);
|
.data_length = sizeof(SPIDERS_DATA),
|
||||||
TextureAtlasLayout basket_layout = {.width = 16, .height = 16, .rows = 1, .columns = 1};
|
.texture_atlas_layout = spiders_layout};
|
||||||
|
Texture basket{.data = BASKET_DATA,
|
||||||
|
.data_length = sizeof(BASKET_DATA),
|
||||||
|
.texture_atlas_layout = basket_layout};
|
||||||
|
|
||||||
registry.ctx().emplace<TextureAssets>(TextureAssets{
|
registry.ctx().emplace<TextureAssets>(TextureAssets{
|
||||||
.background = Texture{.sdl_texture = background, .texture_atlas_layout = background_layout},
|
.background = background, .fruits = fruits, .spiders = spiders, .basket = basket});
|
||||||
.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}});
|
|
||||||
|
|
||||||
auto background_music = load_audio(BACKGROUND_MUSIC_DATA, sizeof(BACKGROUND_MUSIC_DATA));
|
AudioAsset background_music{.buffer = BACKGROUND_MUSIC_DATA,
|
||||||
auto pickup_sound = load_audio(PICKUP_SOUND_DATA, sizeof(PICKUP_SOUND_DATA));
|
.buffer_length = sizeof(BACKGROUND_MUSIC_DATA)};
|
||||||
auto hit_sound = load_audio(HIT_SOUND_DATA, sizeof(HIT_SOUND_DATA));
|
AudioAsset pickup_sound{.buffer = PICKUP_SOUND_DATA,
|
||||||
|
.buffer_length = sizeof(PICKUP_SOUND_DATA)};
|
||||||
|
AudioAsset hit_sound{.buffer = HIT_SOUND_DATA, .buffer_length = sizeof(HIT_SOUND_DATA)};
|
||||||
registry.ctx().emplace<AudioAssets>(AudioAssets{.background_music = background_music,
|
registry.ctx().emplace<AudioAssets>(AudioAssets{.background_music = background_music,
|
||||||
.pickup_sound = pickup_sound,
|
.pickup_sound = pickup_sound,
|
||||||
.hit_sound = hit_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});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "audio.hpp"
|
#include "audio.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <SDL3_ttf/SDL_ttf.h>
|
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
|
|
||||||
struct TextureAtlasLayout
|
struct TextureAtlasLayout
|
||||||
@@ -16,7 +14,8 @@ struct TextureAtlasLayout
|
|||||||
|
|
||||||
struct Texture
|
struct Texture
|
||||||
{
|
{
|
||||||
SDL_Texture* sdl_texture;
|
uint8_t const* data;
|
||||||
|
uint32_t data_length;
|
||||||
TextureAtlasLayout texture_atlas_layout;
|
TextureAtlasLayout texture_atlas_layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,15 +34,15 @@ struct AudioAssets
|
|||||||
AudioAsset hit_sound;
|
AudioAsset hit_sound;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FontAsset
|
// struct FontAsset
|
||||||
{
|
// {
|
||||||
TTF_Font* font;
|
// TTF_Font* font;
|
||||||
};
|
// };
|
||||||
|
|
||||||
struct FontAssets
|
// struct FontAssets
|
||||||
{
|
// {
|
||||||
FontAsset default_font;
|
// FontAsset default_font;
|
||||||
};
|
// };
|
||||||
|
|
||||||
struct AssetModule
|
struct AssetModule
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,28 +4,7 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
|
|
||||||
struct AudioAsset
|
struct AudioAsset
|
||||||
{
|
{
|
||||||
SDL_AudioSpec spec;
|
uint8_t const* buffer;
|
||||||
uint8_t* buffer;
|
|
||||||
uint32_t buffer_length;
|
uint32_t buffer_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MonoChannel
|
||||||
|
{
|
||||||
|
int id_mono;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StereoChannel
|
||||||
|
{
|
||||||
|
int id_left;
|
||||||
|
int id_right;
|
||||||
|
};
|
||||||
|
|
||||||
struct AudioStreams
|
struct AudioStreams
|
||||||
{
|
{
|
||||||
SDL_AudioStream* music_stream;
|
StereoChannel music_stream;
|
||||||
SDL_AudioStream* sound_stream;
|
MonoChannel sound_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AudioModule
|
struct AudioModule
|
||||||
{
|
{
|
||||||
AudioModule(entt::registry& registry);
|
AudioModule(entt::registry& registry);
|
||||||
static void FeedAudioStreams(entt::registry& registry);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <SDL3_ttf/SDL_ttf.h>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
static constexpr int WINDOW_WIDTH = 400;
|
static constexpr int WINDOW_WIDTH = 400;
|
||||||
static constexpr int WINDOW_HEIGHT = 240;
|
static constexpr int WINDOW_HEIGHT = 240;
|
||||||
|
|
||||||
struct SdlHandles
|
// struct SdlHandles
|
||||||
{
|
// {
|
||||||
SDL_Window* window;
|
// SDL_Window* window;
|
||||||
SDL_Renderer* renderer;
|
// SDL_Renderer* renderer;
|
||||||
TTF_TextEngine* text_engine;
|
// TTF_TextEngine* text_engine;
|
||||||
};
|
// };
|
||||||
|
|
||||||
struct Game
|
struct Game
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <cstdint>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
enum Key : uint8_t
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
};
|
||||||
|
|
||||||
struct ButtonInput
|
struct ButtonInput
|
||||||
{
|
{
|
||||||
std::set<SDL_Keycode> pressed;
|
std::set<Key> pressed;
|
||||||
std::set<SDL_Keycode> just_pressed;
|
|
||||||
std::set<SDL_Keycode> just_released;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,45 @@
|
|||||||
#include "level.hpp"
|
#include "level.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <Hall/Hall.h>
|
||||||
|
|
||||||
|
LevelModule::LevelModule(entt::registry& registry)
|
||||||
|
{
|
||||||
|
auto const* texture_assets = ®istry.ctx().get<TextureAssets>();
|
||||||
|
auto const* audio_steams = ®istry.ctx().get<AudioStreams>();
|
||||||
|
auto const* audio_assets = ®istry.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();
|
||||||
|
registry.emplace<Position>(background, Position{.x = 0, .y = 0});
|
||||||
|
registry.emplace<Sprite>(
|
||||||
|
background, Sprite{.texture = &texture_assets->background, .texture_atlas_index = 0});
|
||||||
|
registry.emplace<Size>(background, Size{.w = WINDOW_WIDTH, .h = WINDOW_HEIGHT});
|
||||||
|
registry.emplace<Background>(background);
|
||||||
|
|
||||||
|
auto basket = registry.create();
|
||||||
|
registry.emplace<WorldPosition>(basket);
|
||||||
|
registry.emplace<Position>(basket,
|
||||||
|
Position{.x = WINDOW_WIDTH / 2 - 32, .y = WINDOW_HEIGHT - 32});
|
||||||
|
registry.emplace<Sprite>(basket,
|
||||||
|
Sprite{.texture = &texture_assets->basket, .texture_atlas_index = 0});
|
||||||
|
registry.emplace<Size>(basket, Size{.w = 64, .h = 32});
|
||||||
|
registry.emplace<Basket>(basket);
|
||||||
|
|
||||||
|
auto basket_cb = registry.create();
|
||||||
|
registry.emplace<WorldPosition>(basket_cb);
|
||||||
|
registry.emplace<Position>(basket_cb, Position{.x = 0, .y = 16});
|
||||||
|
registry.emplace<Size>(basket_cb, Size{.w = 64, .h = 16});
|
||||||
|
registry.emplace<CollisionBox>(basket_cb);
|
||||||
|
registry.emplace<Parent>(basket_cb, basket);
|
||||||
|
registry.emplace<BasketCollisionBox>(basket_cb);
|
||||||
|
}
|
||||||
|
|
||||||
void LevelModule::MoveBasket(entt::registry& registry)
|
void LevelModule::MoveBasket(entt::registry& registry)
|
||||||
{
|
{
|
||||||
@@ -10,14 +48,14 @@ void LevelModule::MoveBasket(entt::registry& registry)
|
|||||||
|
|
||||||
for (auto [entity, pos, size, sprite] : basket_view.each())
|
for (auto [entity, pos, size, sprite] : basket_view.each())
|
||||||
{
|
{
|
||||||
if (input.pressed.contains(SDLK_LEFT))
|
// if (input.pressed.contains(SDLK_LEFT))
|
||||||
{
|
// {
|
||||||
pos.x -= 5;
|
// pos.x -= 5;
|
||||||
}
|
// }
|
||||||
if (input.pressed.contains(SDLK_RIGHT))
|
// if (input.pressed.contains(SDLK_RIGHT))
|
||||||
{
|
// {
|
||||||
pos.x += 5;
|
// pos.x += 5;
|
||||||
}
|
// }
|
||||||
|
|
||||||
pos.x = pos.x < 0 ? 0 : pos.x;
|
pos.x = pos.x < 0 ? 0 : pos.x;
|
||||||
pos.x = pos.x > WINDOW_WIDTH - size.w ? WINDOW_WIDTH - size.w : pos.x;
|
pos.x = pos.x > WINDOW_WIDTH - size.w ? WINDOW_WIDTH - size.w : pos.x;
|
||||||
@@ -79,7 +117,7 @@ void LevelModule::SpawnFruits(entt::registry& registry)
|
|||||||
void LevelModule::CollectFruit(entt::registry& registry)
|
void LevelModule::CollectFruit(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto& game = registry.ctx().get<Game>();
|
auto& game = registry.ctx().get<Game>();
|
||||||
auto const& audio_streams = registry.ctx().get<AudioStreams>();
|
// auto const& audio_streams = registry.ctx().get<AudioStreams>();
|
||||||
auto const& audio_assets = registry.ctx().get<AudioAssets>();
|
auto const& audio_assets = registry.ctx().get<AudioAssets>();
|
||||||
|
|
||||||
auto view = registry.view<Position, Fruit, Collided>();
|
auto view = registry.view<Position, Fruit, Collided>();
|
||||||
@@ -89,16 +127,16 @@ void LevelModule::CollectFruit(entt::registry& registry)
|
|||||||
pos.x += 1000;
|
pos.x += 1000;
|
||||||
// registry.destroy(entity);
|
// registry.destroy(entity);
|
||||||
|
|
||||||
SDL_PutAudioStreamData(audio_streams.sound_stream,
|
// SDL_PutAudioStreamData(audio_streams.sound_stream,
|
||||||
audio_assets.pickup_sound.buffer,
|
// audio_assets.pickup_sound.buffer,
|
||||||
audio_assets.pickup_sound.buffer_length);
|
// audio_assets.pickup_sound.buffer_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelModule::CollectSpider(entt::registry& registry)
|
void LevelModule::CollectSpider(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto& game = registry.ctx().get<Game>();
|
auto& game = registry.ctx().get<Game>();
|
||||||
auto const& audio_streams = registry.ctx().get<AudioStreams>();
|
// auto const& audio_streams = registry.ctx().get<AudioStreams>();
|
||||||
auto const& audio_assets = registry.ctx().get<AudioAssets>();
|
auto const& audio_assets = registry.ctx().get<AudioAssets>();
|
||||||
|
|
||||||
auto view = registry.view<Position, Spider, Collided>();
|
auto view = registry.view<Position, Spider, Collided>();
|
||||||
@@ -108,9 +146,9 @@ void LevelModule::CollectSpider(entt::registry& registry)
|
|||||||
pos.x += 1000;
|
pos.x += 1000;
|
||||||
// registry.destroy(entity);
|
// registry.destroy(entity);
|
||||||
|
|
||||||
SDL_PutAudioStreamData(audio_streams.sound_stream,
|
// SDL_PutAudioStreamData(audio_streams.sound_stream,
|
||||||
audio_assets.hit_sound.buffer,
|
// audio_assets.hit_sound.buffer,
|
||||||
audio_assets.hit_sound.buffer_length);
|
// audio_assets.hit_sound.buffer_length);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "sprite.hpp"
|
#include "sprite.hpp"
|
||||||
|
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
struct Background
|
struct Background
|
||||||
{
|
{
|
||||||
@@ -33,34 +32,7 @@ struct BasketCollisionBox
|
|||||||
|
|
||||||
struct LevelModule
|
struct LevelModule
|
||||||
{
|
{
|
||||||
LevelModule(entt::registry& registry)
|
LevelModule(entt::registry& registry);
|
||||||
{
|
|
||||||
auto const* texture_assets = ®istry.ctx().get<TextureAssets>();
|
|
||||||
|
|
||||||
auto background = registry.create();
|
|
||||||
registry.emplace<Position>(background, Position{.x = 0, .y = 0});
|
|
||||||
registry.emplace<Sprite>(
|
|
||||||
background, Sprite{.texture = &texture_assets->background, .texture_atlas_index = 0});
|
|
||||||
registry.emplace<Size>(background, Size{.w = WINDOW_WIDTH, .h = WINDOW_HEIGHT});
|
|
||||||
registry.emplace<Background>(background);
|
|
||||||
|
|
||||||
auto basket = registry.create();
|
|
||||||
registry.emplace<WorldPosition>(basket);
|
|
||||||
registry.emplace<Position>(basket,
|
|
||||||
Position{.x = WINDOW_WIDTH / 2 - 32, .y = WINDOW_HEIGHT - 32});
|
|
||||||
registry.emplace<Sprite>(
|
|
||||||
basket, Sprite{.texture = &texture_assets->basket, .texture_atlas_index = 0});
|
|
||||||
registry.emplace<Size>(basket, Size{.w = 64, .h = 32});
|
|
||||||
registry.emplace<Basket>(basket);
|
|
||||||
|
|
||||||
auto basket_cb = registry.create();
|
|
||||||
registry.emplace<WorldPosition>(basket_cb);
|
|
||||||
registry.emplace<Position>(basket_cb, Position{.x = 0, .y = 16});
|
|
||||||
registry.emplace<Size>(basket_cb, Size{.w = 64, .h = 16});
|
|
||||||
registry.emplace<CollisionBox>(basket_cb);
|
|
||||||
registry.emplace<Parent>(basket_cb, basket);
|
|
||||||
registry.emplace<BasketCollisionBox>(basket_cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MoveBasket(entt::registry& registry);
|
static void MoveBasket(entt::registry& registry);
|
||||||
static void SpawnFruits(entt::registry& registry);
|
static void SpawnFruits(entt::registry& registry);
|
||||||
|
|||||||
109
src/main.cpp
@@ -5,61 +5,26 @@
|
|||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
#include "render.hpp"
|
#include "render.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <Hall/Hall.h>
|
||||||
#include <SDL3_ttf/SDL_ttf.h>
|
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
void increment_ticks(entt::registry& registry)
|
void increment_ticks(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto& game = registry.ctx().get<Game>();
|
auto& game = registry.ctx().get<Game>();
|
||||||
// auto& translate_system = registry.ctx().get<TranslateSystem>();
|
|
||||||
|
|
||||||
game.ticks += 1;
|
game.ticks += 1;
|
||||||
|
|
||||||
if (game.ticks % 60 == 0)
|
if (game.ticks % 60 == 0 && game.time > 0)
|
||||||
{
|
{
|
||||||
game.time = std::max(0, game.time - 1);
|
game.time--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (game.time == 0)
|
|
||||||
// translate_system.translate_system.disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
spdlog::info("Initialize SDL...");
|
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
|
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO))
|
|
||||||
{
|
|
||||||
spdlog::critical("Failed to initialize SDL!\nCause: {}", SDL_GetError());
|
|
||||||
std::terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
TTF_Init();
|
|
||||||
|
|
||||||
auto* window = SDL_CreateWindow("HansTheGatherer", WINDOW_WIDTH, WINDOW_HEIGHT, 0);
|
|
||||||
if (window == nullptr)
|
|
||||||
{
|
|
||||||
spdlog::critical("Failed to create SDL window!\nCause: {}", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* renderer = SDL_CreateRenderer(window, nullptr);
|
|
||||||
if (renderer == nullptr)
|
|
||||||
{
|
|
||||||
spdlog::critical("Failed to create SDL renderer!\nCause: {}", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* text_engine = TTF_CreateRendererTextEngine(renderer);
|
|
||||||
|
|
||||||
entt::registry registry;
|
entt::registry registry;
|
||||||
|
|
||||||
registry.ctx().emplace<Game>(Game{.ticks = 0, .time = 60, .score = 0, .random_engine = {}});
|
registry.ctx().emplace<Game>(Game{.ticks = 0, .time = 60, .score = 0, .random_engine = {}});
|
||||||
registry.ctx().emplace<ButtonInput>(ButtonInput{});
|
registry.ctx().emplace<ButtonInput>(ButtonInput{});
|
||||||
auto sdl_handles = registry.ctx().emplace<SdlHandles>(
|
|
||||||
SdlHandles{.window = window, .renderer = renderer, .text_engine = text_engine});
|
|
||||||
|
|
||||||
AssetModule asset_module(registry);
|
AssetModule asset_module(registry);
|
||||||
AudioModule audio_module(registry);
|
AudioModule audio_module(registry);
|
||||||
@@ -70,63 +35,39 @@ int main()
|
|||||||
bool exit_gameloop = false;
|
bool exit_gameloop = false;
|
||||||
while (!exit_gameloop)
|
while (!exit_gameloop)
|
||||||
{
|
{
|
||||||
auto* input = ®istry.ctx().get<ButtonInput>();
|
|
||||||
|
|
||||||
// Clear just pressed/released
|
|
||||||
input->just_pressed.clear();
|
|
||||||
input->just_released.clear();
|
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
SDL_Event event;
|
auto* input = ®istry.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);
|
||||||
increment_ticks(registry);
|
else
|
||||||
LevelModule::MoveBasket(registry);
|
input->pressed.erase(Key::Right);
|
||||||
LevelModule::SpawnFruits(registry);
|
|
||||||
LevelModule::CollectFruit(registry);
|
if (registry.ctx().get<Game>().time != 0)
|
||||||
LevelModule::CollectSpider(registry);
|
{
|
||||||
// LevelModule::DespawnItems(registry);
|
increment_ticks(registry);
|
||||||
|
LevelModule::MoveBasket(registry);
|
||||||
|
LevelModule::SpawnFruits(registry);
|
||||||
|
LevelModule::CollectFruit(registry);
|
||||||
|
LevelModule::CollectSpider(registry);
|
||||||
|
// LevelModule::DespawnItems(registry);
|
||||||
|
}
|
||||||
|
|
||||||
PhysicsModule::TranslatePhysicsObject(registry);
|
PhysicsModule::TranslatePhysicsObject(registry);
|
||||||
PhysicsModule::PropagatePosition(registry);
|
PhysicsModule::PropagatePosition(registry);
|
||||||
PhysicsModule::RemoveCollisionMarker(registry);
|
PhysicsModule::RemoveCollisionMarker(registry);
|
||||||
PhysicsModule::CollisionCheck(registry);
|
PhysicsModule::CollisionCheck(registry);
|
||||||
|
|
||||||
SDL_RenderClear(sdl_handles.renderer);
|
Hall::Clear(0);
|
||||||
RenderModule::RenderSprites(registry);
|
RenderModule::RenderSprites(registry);
|
||||||
RenderModule::RenderScore(registry);
|
RenderModule::RenderScore(registry);
|
||||||
SDL_RenderPresent(sdl_handles.renderer);
|
Hall::SetCommandSwapBuffers();
|
||||||
|
Hall::GetVSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DestroyRenderer(renderer);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
#include "level.hpp"
|
#include "level.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
void PhysicsModule::TranslatePhysicsObject(entt::registry& registry)
|
void PhysicsModule::TranslatePhysicsObject(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto view = registry.view<Position, Velocity const>();
|
auto view = registry.view<Position, Velocity const>();
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "physics.hpp"
|
#include "physics.hpp"
|
||||||
#include "sprite.hpp"
|
#include "sprite.hpp"
|
||||||
|
|
||||||
|
#include <Hall/Hall.h>
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
RenderModule::RenderModule(entt::registry& registry)
|
RenderModule::RenderModule(entt::registry& registry)
|
||||||
@@ -13,60 +15,44 @@ RenderModule::RenderModule(entt::registry& registry)
|
|||||||
|
|
||||||
void RenderModule::RenderSprites(entt::registry& registry)
|
void RenderModule::RenderSprites(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto const& sdl_handles = registry.ctx().get<SdlHandles>();
|
|
||||||
auto const& game = registry.ctx().get<Game>();
|
auto const& game = registry.ctx().get<Game>();
|
||||||
auto sprites_view =
|
auto sprites_view =
|
||||||
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>();
|
||||||
|
|
||||||
for (auto [entity, pos, size, sprite] : background_view.each())
|
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;
|
||||||
SDL_FRect srcrect{static_cast<float>(column * layout.width),
|
// Problemchen: Wir können die Sprites nicht strecken... hat keiner Interpolation
|
||||||
static_cast<float>(row * layout.height),
|
// implementiert?
|
||||||
static_cast<float>(layout.width),
|
Hall::Draw(reinterpret_cast<unsigned short const*>(sprite.texture->data), // Das ist 100% UB
|
||||||
static_cast<float>(layout.height)};
|
column * layout.width,
|
||||||
|
row * layout.height,
|
||||||
|
pos.x,
|
||||||
|
pos.y,
|
||||||
|
layout.width,
|
||||||
|
layout.height,
|
||||||
|
sprite.texture->data_length);
|
||||||
|
};
|
||||||
|
|
||||||
SDL_FRect dstrect{static_cast<float>(pos.x),
|
background_view.each(render_sprite);
|
||||||
static_cast<float>(pos.y),
|
sprites_view.each(render_sprite);
|
||||||
static_cast<float>(size.w),
|
|
||||||
static_cast<float>(size.h)};
|
|
||||||
|
|
||||||
SDL_RenderTexture(sdl_handles.renderer, sprite.texture->sdl_texture, &srcrect, &dstrect);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto [entity, pos, size, sprite] : sprites_view.each())
|
|
||||||
{
|
|
||||||
TextureAtlasLayout layout = sprite.texture->texture_atlas_layout;
|
|
||||||
uint8_t row = sprite.texture_atlas_index / layout.columns;
|
|
||||||
uint8_t column = sprite.texture_atlas_index % layout.columns;
|
|
||||||
SDL_FRect srcrect{static_cast<float>(column * layout.width),
|
|
||||||
static_cast<float>(row * layout.height),
|
|
||||||
static_cast<float>(layout.width),
|
|
||||||
static_cast<float>(layout.height)};
|
|
||||||
|
|
||||||
SDL_FRect dstrect{static_cast<float>(pos.x),
|
|
||||||
static_cast<float>(pos.y),
|
|
||||||
static_cast<float>(size.w),
|
|
||||||
static_cast<float>(size.h)};
|
|
||||||
|
|
||||||
SDL_RenderTexture(sdl_handles.renderer, sprite.texture->sdl_texture, &srcrect, &dstrect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderModule::RenderScore(entt::registry& registry)
|
void RenderModule::RenderScore(entt::registry& registry)
|
||||||
{
|
{
|
||||||
auto const& sdl_handles = registry.ctx().get<SdlHandles>();
|
// auto const& sdl_handles = registry.ctx().get<SdlHandles>();
|
||||||
auto const& game = registry.ctx().get<Game>();
|
auto const& game = registry.ctx().get<Game>();
|
||||||
auto const& font_assets = registry.ctx().get<FontAssets>();
|
// auto const& font_assets = registry.ctx().get<FontAssets>();
|
||||||
|
|
||||||
auto score_string = std::format("Score: {}\nTime: {}", game.score, game.time);
|
auto score_string = std::format("Score: {}\nTime: {}", game.score, game.time);
|
||||||
auto text = TTF_CreateText(sdl_handles.text_engine,
|
// auto text = TTF_CreateText(sdl_handles.text_engine,
|
||||||
font_assets.default_font.font,
|
// font_assets.default_font.font,
|
||||||
score_string.c_str(),
|
// score_string.c_str(),
|
||||||
score_string.length());
|
// score_string.length());
|
||||||
TTF_DrawRendererText(text, 0.0, 0.0);
|
// TTF_DrawRendererText(text, 0.0, 0.0);
|
||||||
TTF_DestroyText(text);
|
// TTF_DestroyText(text);
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "assets.hpp"
|
#include "assets.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
struct Sprite
|
struct Sprite
|
||||||
|
|||||||
11
wuehans/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
add_library(WueHans STATIC start.S syscall.c)
|
||||||
|
|
||||||
|
target_include_directories(WueHans PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(WueHans PRIVATE RISCV_Options)
|
||||||
|
|
||||||
|
target_link_options(WueHans PUBLIC
|
||||||
|
-T ${CMAKE_CURRENT_SOURCE_DIR}/wuehans.ld
|
||||||
|
)
|
||||||
54
wuehans/start.S
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
.section .text.startSection
|
||||||
|
.global _Z4mainv
|
||||||
|
.global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
/* zero-initialize all registers */
|
||||||
|
addi x1, zero, 0
|
||||||
|
addi x2, zero, 0
|
||||||
|
addi x3, zero, 0
|
||||||
|
addi x4, zero, 0
|
||||||
|
addi x5, zero, 0
|
||||||
|
addi x6, zero, 0
|
||||||
|
addi x7, zero, 0
|
||||||
|
addi x8, zero, 0
|
||||||
|
addi x9, zero, 0
|
||||||
|
addi x10, zero, 0
|
||||||
|
addi x11, zero, 0
|
||||||
|
addi x12, zero, 0
|
||||||
|
addi x13, zero, 0
|
||||||
|
addi x14, zero, 0
|
||||||
|
addi x15, zero, 0
|
||||||
|
addi x16, zero, 0
|
||||||
|
addi x17, zero, 0
|
||||||
|
addi x18, zero, 0
|
||||||
|
addi x19, zero, 0
|
||||||
|
addi x20, zero, 0
|
||||||
|
addi x21, zero, 0
|
||||||
|
addi x22, zero, 0
|
||||||
|
addi x23, zero, 0
|
||||||
|
addi x24, zero, 0
|
||||||
|
addi x25, zero, 0
|
||||||
|
addi x26, zero, 0
|
||||||
|
addi x27, zero, 0
|
||||||
|
addi x28, zero, 0
|
||||||
|
addi x29, zero, 0
|
||||||
|
addi x30, zero, 0
|
||||||
|
addi x31, zero, 0
|
||||||
|
|
||||||
|
/* set stack pointer */
|
||||||
|
.equ STACK_START, 0x02000000
|
||||||
|
lui sp, %hi(STACK_START)
|
||||||
|
addi sp, sp, %lo(STACK_START)
|
||||||
|
|
||||||
|
/* push zeros on the stack for argc and argv */
|
||||||
|
/* (stack is aligned to 16 bytes in riscv calling convention) */
|
||||||
|
addi sp,sp,-16
|
||||||
|
sw zero,0(sp)
|
||||||
|
sw zero,4(sp)
|
||||||
|
sw zero,8(sp)
|
||||||
|
sw zero,12(sp)
|
||||||
|
|
||||||
|
/* jump to libc init */
|
||||||
|
// j _Z4mainv
|
||||||
|
j main
|
||||||
186
wuehans/syscall.c
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// #include <fatfs/ff.h>
|
||||||
|
#include <wuehans_config.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
/* #include <DebugHelper.h> */
|
||||||
|
|
||||||
|
void *__dso_handle = 0;
|
||||||
|
|
||||||
|
// const TCHAR STDOUT[30] = "stdout.txt";
|
||||||
|
// const TCHAR STDERR[30] = "stderr.txt";
|
||||||
|
|
||||||
|
// FIL fp = {0};
|
||||||
|
// FATFS FatFs = {0};
|
||||||
|
// BYTE is_mounted = 0;
|
||||||
|
|
||||||
|
// struct FD_Data {
|
||||||
|
// FIL fp;
|
||||||
|
// BYTE mode;
|
||||||
|
// BYTE is_open;
|
||||||
|
// } FD_Data_default = {NULL, FA_READ, 0};
|
||||||
|
// typedef struct FD_Data FD_Data;
|
||||||
|
|
||||||
|
// #define FILE_AMOUNT 4
|
||||||
|
// static FD_Data fd_data[FILE_AMOUNT];
|
||||||
|
|
||||||
|
// int _write(int fd, char *ptr, int len) {
|
||||||
|
// if (is_mounted == 0) {
|
||||||
|
// f_mount(&FatFs, "", 0);
|
||||||
|
// is_mounted = 1;
|
||||||
|
// }
|
||||||
|
// // stdout
|
||||||
|
// if (fd == 1) {
|
||||||
|
|
||||||
|
// FIL write_file;
|
||||||
|
// FRESULT fr = f_open(&write_file, STDOUT, FA_OPEN_APPEND | FA_WRITE);
|
||||||
|
// if (fr != 0) {
|
||||||
|
// return fr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// UINT written = 0;
|
||||||
|
|
||||||
|
// fr = f_write(&write_file, ptr, len, &written);
|
||||||
|
// if (fr != 0) {
|
||||||
|
// // TODO: Set errno
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// f_close(&write_file);
|
||||||
|
|
||||||
|
// // HACK: Hackermann
|
||||||
|
// volatile int* x = (int*) 0x80000000;
|
||||||
|
// int b = *x;
|
||||||
|
// // HACK: Hackermann Ende
|
||||||
|
|
||||||
|
// return written;
|
||||||
|
// } else if (fd > 2 && (fd-3) < FILE_AMOUNT && fd_data[fd-3].is_open) {
|
||||||
|
// UINT bw = 0;
|
||||||
|
// f_write(&fd_data[fd-3].fp, ptr, len, &bw);
|
||||||
|
|
||||||
|
// return bw;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int _read(int fd, char *ptr, int len) {
|
||||||
|
// if (fd > 2 && (fd-3) < FILE_AMOUNT && fd_data[fd-3].is_open) {
|
||||||
|
// UINT bytesRead = 0;
|
||||||
|
// FRESULT result = f_read(&fd_data[fd-3].fp, ptr, len, &bytesRead);
|
||||||
|
// /* ScreenPrint("_read"); */
|
||||||
|
// return bytesRead;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void *_sbrk(int incr) {
|
||||||
|
// extern int heap_begin;
|
||||||
|
// static unsigned char *heap = NULL;
|
||||||
|
// unsigned char *prev_heap;
|
||||||
|
|
||||||
|
// if (heap == NULL) {
|
||||||
|
// heap = (unsigned char *)&heap_begin;
|
||||||
|
// }
|
||||||
|
// prev_heap = heap;
|
||||||
|
|
||||||
|
// if ((int)heap + incr < heap_begin + HEAP_SIZE) {
|
||||||
|
// heap += incr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* ScreenPrint("_sbrk"); */
|
||||||
|
// return prev_heap;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int _fstat(int fd, struct stat *st) {
|
||||||
|
// st->st_mode = S_IFREG;
|
||||||
|
// /* ScreenPrint("_fstat"); */
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int _lseek(int fd, int offset, int whence) {
|
||||||
|
// // Invalid lseek call
|
||||||
|
// if (fd <= 2 || (fd-3) >= FILE_AMOUNT || !fd_data[fd-3].is_open) {
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Calculate the correct offset for f_lseek()
|
||||||
|
// FSIZE_t ofs = 0;
|
||||||
|
// switch (whence) {
|
||||||
|
// // Set to offset directly
|
||||||
|
// case SEEK_SET:
|
||||||
|
// ofs = offset;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// // Increment by offset
|
||||||
|
// case SEEK_CUR:
|
||||||
|
// ofs = f_tell(&fd_data[fd-3].fp) + offset;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// // Append offset to EOF
|
||||||
|
// case SEEK_END:
|
||||||
|
// ofs = f_size(&fd_data[fd-3].fp) + offset;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// FRESULT result = f_lseek(&fd_data[fd-3].fp, ofs);
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int _open(const char *name, int flags, int mode) {
|
||||||
|
// if (is_mounted == 0) {
|
||||||
|
// f_mount(&FatFs, "", 0);
|
||||||
|
// is_mounted = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int i;
|
||||||
|
// for (i = 0; i < FILE_AMOUNT; i++) {
|
||||||
|
// if (fd_data[i].is_open == 1) {
|
||||||
|
// // Entry already in use
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// mode = FA_READ;
|
||||||
|
// FRESULT fr = f_open(&fd_data[i].fp, name, mode);
|
||||||
|
// if (fr != FR_OK) {
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fd_data[i].mode = mode;
|
||||||
|
// fd_data[i].is_open = 1;
|
||||||
|
// // Exclude stdout, stderr, stdin
|
||||||
|
// return i+3;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int _close(int fd) {
|
||||||
|
// if (fd > 2 && (fd-3) < FILE_AMOUNT) {
|
||||||
|
// fd_data[fd-3].is_open = 0;
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
int _isatty(int fd)
|
||||||
|
{
|
||||||
|
errno = ENOTTY;
|
||||||
|
/* ScreenPrint("isatty"); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _exit(int status) {
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _kill(int pid, int sig) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getpid() { return -1; }
|
||||||
207
wuehans/wuehans.ld
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
|
||||||
|
/* ---- Original Script: /opt/riscv32i/riscv32-unknown-elf/lib/ldscripts/elf32lriscv.x ---- */
|
||||||
|
/* Default linker script, for normal executables */
|
||||||
|
/* Copyright (C) 2014-2017 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
|
||||||
|
"elf32-littleriscv")
|
||||||
|
OUTPUT_ARCH(riscv)
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x00000000;
|
||||||
|
|
||||||
|
.startSection :
|
||||||
|
{
|
||||||
|
KEEP(*(.text.startSection))
|
||||||
|
}
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) }
|
||||||
|
.iplt : { *(.iplt) }
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.sdata2 :
|
||||||
|
{
|
||||||
|
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||||
|
}
|
||||||
|
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
|
||||||
|
.gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
|
||||||
|
.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
.init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
}
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (0, .);
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
|
||||||
|
/* We want the small data sections together, so single-instruction offsets
|
||||||
|
can access them all, and initialized data all before uninitialized, so
|
||||||
|
we can shorten the on-disk segment size. */
|
||||||
|
.sdata :
|
||||||
|
{
|
||||||
|
__global_pointer$ = . + 0x800;
|
||||||
|
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
|
||||||
|
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||||
|
}
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.sbss :
|
||||||
|
{
|
||||||
|
*(.dynsbss)
|
||||||
|
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||||
|
*(.scommon)
|
||||||
|
}
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
PROVIDE(_bss_end = .);
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 32 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(32 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
. = ALIGN(32 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||||
|
PROVIDE(heap_begin = .);
|
||||||
|
}
|
||||||
7
wuehans/wuehans_config.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef WUEHANS_CONFIG_H
|
||||||
|
#define WUEHANS_CONFIG_H
|
||||||
|
|
||||||
|
// Heap Size in Bytes
|
||||||
|
#define HEAP_SIZE 0x800000
|
||||||
|
|
||||||
|
#endif
|
||||||