Disable auto crlf

This commit is contained in:
jaby 2023-10-11 18:20:43 +02:00
parent 9e235a310c
commit 6d4916178c
23 changed files with 1236 additions and 1236 deletions

26
.gitignore vendored
View File

@ -1,14 +1,14 @@
# For now we ignore what is in root
**/build
**/bin
**/gcm.cache
**/iso/Info
/iso
.lfsconfig
*.d
*.a
*.o
*.ii
# For now we ignore what is in root
**/build
**/bin
**/gcm.cache
**/iso/Info
/iso
.lfsconfig
*.d
*.a
*.o
*.ii
*.xa

View File

@ -1,20 +1,20 @@
ARTIFACT = PoolBox
make_assets = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C assets
make_application = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C application
make_cd = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C iso
all clean rebuild: |assets_$(MAKECMDGOALS) application_$(MAKECMDGOALS) cd_$(MAKECMDGOALS)
all_%: always
$(call make_assets,$*)
$(call make_application,$*)
$(call make_cd,$*)
assets_%: always
$(call make_assets,$*)
application_%: always
$(call make_application,$*)
cd_%: always
$(call make_cd,$*)
ARTIFACT = PoolBox
make_assets = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C assets
make_application = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C application
make_cd = $(MAKE) $(1) ARTIFACT=$(ARTIFACT) -C iso
all clean rebuild: |assets_$(MAKECMDGOALS) application_$(MAKECMDGOALS) cd_$(MAKECMDGOALS)
all_%: always
$(call make_assets,$*)
$(call make_application,$*)
$(call make_cd,$*)
assets_%: always
$(call make_assets,$*)
application_%: always
$(call make_application,$*)
cd_%: always
$(call make_cd,$*)
always: ;

View File

@ -1,12 +1,12 @@
BUILD_DIR = bin
OVERLAY_CONFIG = Overlays.json
include $(JABY_ENGINE_DIR)/mkfile/Wildcard.mk
SRCS = $(call rwildcard, src, c cpp)
INCLUDES += -I$(JABY_ENGINE_DIR)/include
CCFLAGS += -save-temps=obj
include $(JABY_ENGINE_DIR)/mkfile/Makefile
BUILD_DIR = bin
OVERLAY_CONFIG = Overlays.json
include $(JABY_ENGINE_DIR)/mkfile/Wildcard.mk
SRCS = $(call rwildcard, src, c cpp)
INCLUDES += -I$(JABY_ENGINE_DIR)/include
CCFLAGS += -save-temps=obj
include $(JABY_ENGINE_DIR)/mkfile/Makefile
include $(JABY_ENGINE_DIR)/mkfile/PSEXETarget.mk

View File

@ -1,24 +1,24 @@
include $(JABY_ENGINE_DIR)/mkfile/ExportPath.mk
include $(JABY_ENGINE_DIR)/mkfile/RebuildTarget.mk
OUTPUT_DIR = bin
INPUT = $(OUTPUT_DIR)/TexturePage.bin $(OUTPUT_DIR)/IconTexture.bin $(OUTPUT_DIR)/YoshiFont.bin $(OUTPUT_DIR)/Paco.bin
$(OUTPUT_DIR)/TexturePage.bin: TexturePage.png
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4
$(OUTPUT_DIR)/IconTexture.bin: IconTexture.png
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --semi-trans --color-trans
$(OUTPUT_DIR)/YoshiFont.bin: YoshiFont.png
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --color-trans
$(OUTPUT_DIR)/Paco.bin: Paco.png
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --color-trans
all: $(INPUT)
clean:
include $(JABY_ENGINE_DIR)/mkfile/ExportPath.mk
include $(JABY_ENGINE_DIR)/mkfile/RebuildTarget.mk
OUTPUT_DIR = bin
INPUT = $(OUTPUT_DIR)/TexturePage.bin $(OUTPUT_DIR)/IconTexture.bin $(OUTPUT_DIR)/YoshiFont.bin $(OUTPUT_DIR)/Paco.bin
$(OUTPUT_DIR)/TexturePage.bin: TexturePage.png
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4
$(OUTPUT_DIR)/IconTexture.bin: IconTexture.png
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --semi-trans --color-trans
$(OUTPUT_DIR)/YoshiFont.bin: YoshiFont.png
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --color-trans
$(OUTPUT_DIR)/Paco.bin: Paco.png
jaby_engine_fconv --lz4 $< -o $@ simple-tim clut4 --color-trans
all: $(INPUT)
clean:
rm -fr $(OUTPUT_DIR)

View File

@ -1,2 +1,2 @@
include $(JABY_ENGINE_DIR)/mkfile/ISOMakefile.mk
include $(JABY_ENGINE_DIR)/mkfile/ISOMakefile.mk
include $(JABY_ENGINE_DIR)/mkfile/RebuildTarget.mk

View File

@ -1,57 +1,57 @@
#pragma once
#include "../../Auxiliary/types.hpp"
#include "../file_types.hpp"
namespace JabyEngine {
namespace FileProcessor {
class State {
__friends:
struct Reserved {
uint32_t reserved[4];
};
struct Configuration;
template<typename T>
using GenericProcessRoutine = Progress (*)(Configuration&, T&);
typedef GenericProcessRoutine<Reserved> ProcessRoutine;
struct Configuration {
ProcessRoutine process_routine = nullptr;
const uint8_t* data_adr = nullptr;
size_t data_bytes = 0ull;
template<typename T>
static __always_inline Configuration from(GenericProcessRoutine<T> process_routine, const uint8_t* data_adr) {
return {reinterpret_cast<ProcessRoutine>(process_routine), data_adr};
}
constexpr void processed(size_t bytes) {
this->data_adr += bytes;
this->data_bytes -= bytes;
}
};
__friends:
Configuration config;
Reserved reserved;
template<typename T>
static __always_inline State from(const T& reserved, const uint8_t* data_adr, GenericProcessRoutine<T> process_routine) {
return {Configuration::from(process_routine, data_adr), *reinterpret_cast<const Reserved*>(&reserved)};
static_assert(sizeof(T) <= sizeof(Reserved));
}
public:
Progress process(size_t bytes_ready) {
this->config.data_bytes += bytes_ready;
return (*this->config.process_routine)(this->config, this->reserved);
}
};
// The nothing state
State create(const uint32_t* data_adr, const Nothing& nothing);
State create(const uint32_t* data_adr, const SimpleTIM& file);
}
#pragma once
#include "../../Auxiliary/types.hpp"
#include "../file_types.hpp"
namespace JabyEngine {
namespace FileProcessor {
class State {
__friends:
struct Reserved {
uint32_t reserved[4];
};
struct Configuration;
template<typename T>
using GenericProcessRoutine = Progress (*)(Configuration&, T&);
typedef GenericProcessRoutine<Reserved> ProcessRoutine;
struct Configuration {
ProcessRoutine process_routine = nullptr;
const uint8_t* data_adr = nullptr;
size_t data_bytes = 0ull;
template<typename T>
static __always_inline Configuration from(GenericProcessRoutine<T> process_routine, const uint8_t* data_adr) {
return {reinterpret_cast<ProcessRoutine>(process_routine), data_adr};
}
constexpr void processed(size_t bytes) {
this->data_adr += bytes;
this->data_bytes -= bytes;
}
};
__friends:
Configuration config;
Reserved reserved;
template<typename T>
static __always_inline State from(const T& reserved, const uint8_t* data_adr, GenericProcessRoutine<T> process_routine) {
return {Configuration::from(process_routine, data_adr), *reinterpret_cast<const Reserved*>(&reserved)};
static_assert(sizeof(T) <= sizeof(Reserved));
}
public:
Progress process(size_t bytes_ready) {
this->config.data_bytes += bytes_ready;
return (*this->config.process_routine)(this->config, this->reserved);
}
};
// The nothing state
State create(const uint32_t* data_adr, const Nothing& nothing);
State create(const uint32_t* data_adr, const SimpleTIM& file);
}
}

View File

@ -1,167 +1,167 @@
#pragma once
#include "../jabyengine_defines.h"
/*
R0 zr Constant Zero
R1 at Reserved for the assembler
R2-R3 v0-v1 Values for results and expression evaluation
R4-R7 a0-a3 Arguments
R8-R15 t0-t7 Temporaries (not preserved across call)
R16-R23 s0-s7 Saved (preserved across call)
R24-R25 t8-t9 More temporaries (not preserved across call)
R26-R27 k0-k1 Reserved for OS Kernel
R28 gp Global Pointer
R29 sp Stack Pointer
R30 fp Frame Pointer
R31 ra Return address (set by function call)
*/
namespace JabyEngine {
namespace SysCall {
static constexpr const uint32_t Table_A = 0xA0;
static constexpr const uint32_t Table_B = 0xB0;
static constexpr const uint32_t Table_C = 0xC0;
enum struct Priority {
CdromDmaIrq = 0,
CdromIoIrq = 0,
SyscallException = 0,
CardSpecificIrq = 1,
VblankIrq = 1,
Timer2Irq = 1,
Timer1Irq = 1,
Timer0Irq = 1,
PadCardIrq = 2,
DefInt = 3
};
enum InterruptVerifierResult {
SkipHandler = 0,
ExecuteHandler = 1
};
typedef InterruptVerifierResult (*InterruptVerifier)();
typedef uint32_t (*InterruptHandler)(uint32_t);
#pragma pack(push, 1)
struct InterrupCallback {
struct InterrupCallback* next;
InterruptHandler handler_function;
InterruptVerifier verifier_function;
uint32_t notUsed;
};
#pragma pack(pop)
#define __syscall_function_cast(table, ...) reinterpret_cast<__VA_ARGS__>(table)
static __always_inline void* memcpy(void *dst, const void *src, size_t len) {
register uint32_t FuncID asm("t1") = 0x2A;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_A, void*(*)(void*, const void*, size_t))(dst, src, len);
}
static __always_inline void InitPad(uint8_t *portA, uint32_t portASize, uint8_t *portB, uint32_t portBSize) {
register uint32_t FuncID asm("t1") = 0x12;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)(uint8_t*, uint32_t, uint8_t*, uint32_t))(portA, portASize, portB, portBSize);
}
static __always_inline void StartPad() {
register uint32_t FuncID asm("t1") = 0x13;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline void StopPad() {
register uint32_t FuncID asm("t1") = 0x14;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline void ChangeClearPad(int32_t _reserved) {
register uint32_t FuncID asm("t1") = 0x5B;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)(int32_t))(_reserved);
}
static __always_inline void [[noreturn]] ReturnFromException() {
register uint32_t FuncID asm("t1") = 0x17;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline int SysEnqIntRP(Priority prio, InterrupCallback* interElm) {
register uint32_t FuncID asm("t1") = 0x02;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_C, int(*)(Priority prio, InterrupCallback *interElm))(prio, interElm);
}
static __always_inline int SysDeqIntRP(Priority prio, InterrupCallback *interElm) {
register uint32_t FuncID asm("t1") = 0x03;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_C, int(*)(Priority prio, InterrupCallback *interElm))(prio, interElm);
}
static __always_inline uint32_t EnterCriticalSection() {
register uint32_t FuncID asm("a0") = 0x01;
register uint32_t returnValue asm("v0");
__asm__ volatile("syscall" : "=r"(FuncID), "=r"(returnValue) : "r"(FuncID) : "at", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory");
return returnValue;
}
static __always_inline void ExitCriticalSection() {
register uint32_t FuncID asm("a0") = 0x02;
__asm__ volatile("syscall" : "=r"(FuncID) : "r"(FuncID) : "at", "v0", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory");
}
static __always_inline void DeliverEvent(uint32_t classId, uint32_t spec) {
register uint32_t FuncID asm("t1") = 0x07;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void (*)(uint32_t, uint32_t))(classId, spec);
}
static __always_inline uint32_t OpenEvent(uint32_t classId, uint32_t spec, uint32_t mode, void (*handler)()) {
register uint32_t FuncID asm("t1") = 0x08;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t, uint32_t, uint32_t, void(*)()))(classId, spec, mode, handler);
}
static __always_inline int CloseEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x09;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t))(event);
}
static __always_inline int TestEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x0B;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, int (*)(uint32_t))(event);
}
static __always_inline int EnableEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x0C;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, int (*)(uint32_t))(event);
}
void printf(const char* txt, ...);
}
#pragma once
#include "../jabyengine_defines.h"
/*
R0 zr Constant Zero
R1 at Reserved for the assembler
R2-R3 v0-v1 Values for results and expression evaluation
R4-R7 a0-a3 Arguments
R8-R15 t0-t7 Temporaries (not preserved across call)
R16-R23 s0-s7 Saved (preserved across call)
R24-R25 t8-t9 More temporaries (not preserved across call)
R26-R27 k0-k1 Reserved for OS Kernel
R28 gp Global Pointer
R29 sp Stack Pointer
R30 fp Frame Pointer
R31 ra Return address (set by function call)
*/
namespace JabyEngine {
namespace SysCall {
static constexpr const uint32_t Table_A = 0xA0;
static constexpr const uint32_t Table_B = 0xB0;
static constexpr const uint32_t Table_C = 0xC0;
enum struct Priority {
CdromDmaIrq = 0,
CdromIoIrq = 0,
SyscallException = 0,
CardSpecificIrq = 1,
VblankIrq = 1,
Timer2Irq = 1,
Timer1Irq = 1,
Timer0Irq = 1,
PadCardIrq = 2,
DefInt = 3
};
enum InterruptVerifierResult {
SkipHandler = 0,
ExecuteHandler = 1
};
typedef InterruptVerifierResult (*InterruptVerifier)();
typedef uint32_t (*InterruptHandler)(uint32_t);
#pragma pack(push, 1)
struct InterrupCallback {
struct InterrupCallback* next;
InterruptHandler handler_function;
InterruptVerifier verifier_function;
uint32_t notUsed;
};
#pragma pack(pop)
#define __syscall_function_cast(table, ...) reinterpret_cast<__VA_ARGS__>(table)
static __always_inline void* memcpy(void *dst, const void *src, size_t len) {
register uint32_t FuncID asm("t1") = 0x2A;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_A, void*(*)(void*, const void*, size_t))(dst, src, len);
}
static __always_inline void InitPad(uint8_t *portA, uint32_t portASize, uint8_t *portB, uint32_t portBSize) {
register uint32_t FuncID asm("t1") = 0x12;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)(uint8_t*, uint32_t, uint8_t*, uint32_t))(portA, portASize, portB, portBSize);
}
static __always_inline void StartPad() {
register uint32_t FuncID asm("t1") = 0x13;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline void StopPad() {
register uint32_t FuncID asm("t1") = 0x14;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline void ChangeClearPad(int32_t _reserved) {
register uint32_t FuncID asm("t1") = 0x5B;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)(int32_t))(_reserved);
}
static __always_inline void [[noreturn]] ReturnFromException() {
register uint32_t FuncID asm("t1") = 0x17;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void(*)())();
}
static __always_inline int SysEnqIntRP(Priority prio, InterrupCallback* interElm) {
register uint32_t FuncID asm("t1") = 0x02;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_C, int(*)(Priority prio, InterrupCallback *interElm))(prio, interElm);
}
static __always_inline int SysDeqIntRP(Priority prio, InterrupCallback *interElm) {
register uint32_t FuncID asm("t1") = 0x03;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_C, int(*)(Priority prio, InterrupCallback *interElm))(prio, interElm);
}
static __always_inline uint32_t EnterCriticalSection() {
register uint32_t FuncID asm("a0") = 0x01;
register uint32_t returnValue asm("v0");
__asm__ volatile("syscall" : "=r"(FuncID), "=r"(returnValue) : "r"(FuncID) : "at", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory");
return returnValue;
}
static __always_inline void ExitCriticalSection() {
register uint32_t FuncID asm("a0") = 0x02;
__asm__ volatile("syscall" : "=r"(FuncID) : "r"(FuncID) : "at", "v0", "v1", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "memory");
}
static __always_inline void DeliverEvent(uint32_t classId, uint32_t spec) {
register uint32_t FuncID asm("t1") = 0x07;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
__syscall_function_cast(Table_B, void (*)(uint32_t, uint32_t))(classId, spec);
}
static __always_inline uint32_t OpenEvent(uint32_t classId, uint32_t spec, uint32_t mode, void (*handler)()) {
register uint32_t FuncID asm("t1") = 0x08;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t, uint32_t, uint32_t, void(*)()))(classId, spec, mode, handler);
}
static __always_inline int CloseEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x09;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t))(event);
}
static __always_inline int TestEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x0B;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, int (*)(uint32_t))(event);
}
static __always_inline int EnableEvent(uint32_t event) {
register uint32_t FuncID asm("t1") = 0x0C;
__asm__ volatile("" : "=r"(FuncID) : "r"(FuncID));
return __syscall_function_cast(Table_B, int (*)(uint32_t))(event);
}
void printf(const char* txt, ...);
}
}

View File

@ -1,59 +1,59 @@
#ifndef __JABYENGINE_FRAME_TIMER_HPP__
#define __JABYENGINE_FRAME_TIMER_HPP__
#include "frame_time_helper.hpp"
#include <stdint.h>
namespace JabyEngine {
class MasterTime {
__friends:
static uint32_t value;
public:
static uint32_t read() {
return reinterpret_cast<volatile uint32_t&>(MasterTime::value);
}
template<typename T>
static T read_as() {
return static_cast<T>(MasterTime::read());
}
};
template<typename T>
class SimpleTimer {
protected:
T value = 0;
public:
constexpr SimpleTimer() = default;
bool is_expired_for(T time) const {
return static_cast<T>((MasterTime::read_as<T>() - this->value)) >= time;
}
void reset() {
this->value = MasterTime::read_as<T>();
}
};
template<typename T>
class IntervalTimer : public SimpleTimer<T> {
private:
T interval = 0;
public:
constexpr IntervalTimer() = default;
constexpr IntervalTimer(T interval) : SimpleTimer<T>(), interval(interval) {
}
void set_interval(T interval) {
this->interval = interval;
}
bool is_expired() const {
return SimpleTimer<T>::is_expired_for(this->interval);
}
};
}
#ifndef __JABYENGINE_FRAME_TIMER_HPP__
#define __JABYENGINE_FRAME_TIMER_HPP__
#include "frame_time_helper.hpp"
#include <stdint.h>
namespace JabyEngine {
class MasterTime {
__friends:
static uint32_t value;
public:
static uint32_t read() {
return reinterpret_cast<volatile uint32_t&>(MasterTime::value);
}
template<typename T>
static T read_as() {
return static_cast<T>(MasterTime::read());
}
};
template<typename T>
class SimpleTimer {
protected:
T value = 0;
public:
constexpr SimpleTimer() = default;
bool is_expired_for(T time) const {
return static_cast<T>((MasterTime::read_as<T>() - this->value)) >= time;
}
void reset() {
this->value = MasterTime::read_as<T>();
}
};
template<typename T>
class IntervalTimer : public SimpleTimer<T> {
private:
T interval = 0;
public:
constexpr IntervalTimer() = default;
constexpr IntervalTimer(T interval) : SimpleTimer<T>(), interval(interval) {
}
void set_interval(T interval) {
this->interval = interval;
}
bool is_expired() const {
return SimpleTimer<T>::is_expired_for(this->interval);
}
};
}
#endif //!__JABYENGINE_FRAME_TIMER_HPP__

View File

@ -1,26 +1,26 @@
#ifndef __JABYENGINE_DEFINES__H__
#define __JABYENGINE_DEFINES__H__
#include "../stddef.h"
#define __used __attribute__((used))
#define __no_align __attribute__((packed))
#define __no_inline __attribute__((noinline))
#define __no_return __attribute__((noreturn))
#define __always_inline __attribute__((always_inline))
#define __section(name) __attribute__((section(name)))
#define __collect(...) __VA_ARGS__
#ifndef __friends
#define __friends private
#endif //!__friends
#ifdef __cplusplus
#define __constexpr constexpr
#define START_C_FUNCTIONS extern "C" {
#define END_C_FUNCTIONS }
#else
#define __constexpr
#define START_C_FUNCTIONS
#define END_C_FUNCTIONS
#endif
#ifndef __JABYENGINE_DEFINES__H__
#define __JABYENGINE_DEFINES__H__
#include "../stddef.h"
#define __used __attribute__((used))
#define __no_align __attribute__((packed))
#define __no_inline __attribute__((noinline))
#define __no_return __attribute__((noreturn))
#define __always_inline __attribute__((always_inline))
#define __section(name) __attribute__((section(name)))
#define __collect(...) __VA_ARGS__
#ifndef __friends
#define __friends private
#endif //!__friends
#ifdef __cplusplus
#define __constexpr constexpr
#define START_C_FUNCTIONS extern "C" {
#define END_C_FUNCTIONS }
#else
#define __constexpr
#define START_C_FUNCTIONS
#define END_C_FUNCTIONS
#endif
#endif //!__JABYENGINE_DEFINES__H__

View File

@ -1,8 +1,8 @@
#ifndef __STDIO__H
#define __STDIO__H
#include "PSX/jabyengine_defines.h"
START_C_FUNCTIONS
int printf(const char* txt, ...) asm("_ZN10JabyEngine7SysCall6printfEPKcz");
END_C_FUNCTIONS
#ifndef __STDIO__H
#define __STDIO__H
#include "PSX/jabyengine_defines.h"
START_C_FUNCTIONS
int printf(const char* txt, ...) asm("_ZN10JabyEngine7SysCall6printfEPKcz");
END_C_FUNCTIONS
#endif //!__STDIO__H

View File

@ -1,2 +1,2 @@
#Add the JabyEngine tools to path
#Add the JabyEngine tools to path
export PATH := $(JABY_ENGINE_DIR)/bin/:$(PATH)

View File

@ -1,13 +1,13 @@
CD_OUTPUT ?= $(ARTIFACT).bin
$(CD_OUTPUT): always
psxcdgen_ex --list $(ARTIFACT).lba -o $(ARTIFACT) psx bin-cue Config.xml
all: $(CD_OUTPUT)
clean:
rm -fr *.bin
rm -fr *.cue
rm -fr *.lba
CD_OUTPUT ?= $(ARTIFACT).bin
$(CD_OUTPUT): always
psxcdgen_ex --list $(ARTIFACT).lba -o $(ARTIFACT) psx bin-cue Config.xml
all: $(CD_OUTPUT)
clean:
rm -fr *.bin
rm -fr *.cue
rm -fr *.lba
always: ;

View File

@ -1,98 +1,98 @@
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(SELF_DIR)ExportPath.mk
substitute = $(subst $(JABY_ENGINE_DIR)/include/modules,!JABYENGINEMODULES,$(subst ..,!super,$1))
desubstitute = $(subst !JABYENGINEMODULES,$(JABY_ENGINE_DIR)/include/modules,$(subst !super,..,$1))
#Build architecture/variant string, possible values: x86, armv7le, etc...
PLATFORM ?= PSX
#Build profile, possible values: release, debug, profile, coverage
BUILD_DIR ?= bin
BUILD_PROFILE ?= debug
TV_FORMAT ?= PAL
CONFIG_NAME ?= $(PLATFORM)-$(BUILD_PROFILE)
OUTPUT_DIR = $(BUILD_DIR)/$(CONFIG_NAME)
TARGET = $(OUTPUT_DIR)/$(ARTIFACT)
#Compiler definitions
HAS_LINUX_MIPS_GCC = $(shell which mipsel-linux-gnu-gcc > /dev/null 2> /dev/null && echo true || echo false)
ifeq ($(HAS_LINUX_MIPS_GCC),true)
PREFIX ?= mipsel-linux-gnu
FORMAT ?= elf32-tradlittlemips
else
PREFIX ?= mipsel-none-elf
FORMAT ?= elf32-littlemips
endif
#Take this to PSEXETarget.mk??
#LDSCRIPT ?= $(PSCX_REDUX_DIR)/ps-exe.ld
#ifneq ($(strip $(OVERLAYSCRIPT)),)
#LDSCRIPT := $(addprefix $(OVERLAYSCRIPT) , -T$(LDSCRIPT))
#else
#LDSCRIPT := $(addprefix $(PSCX_REDUX_DIR)/default.ld , -T$(LDSCRIPT))
#endif
CC = $(PREFIX)-gcc
CXX = $(PREFIX)-g++
LD = $(CXX)
AR = ar
#architecture flags
ARCHFLAGS = -march=r2000 -mtune=r2000 -mabi=32 -EL -fno-pic -mno-shared -nostdinc -nostdinc++ -mno-abicalls -mfp32 -mno-llsc
ARCHFLAGS += -fno-stack-protector -nostdlib -ffreestanding
#Compiler flags for build profiles
CCFLAGS_release += -O3
CCFLAGS_debug += -O0
CXXFLAGS += -fno-exceptions -fno-rtti
CCFLAGS += -mno-gpopt -fomit-frame-pointer -ffunction-sections -fdata-sections
CCFLAGS += -fno-builtin -fno-strict-aliasing -Wno-attributes
CCFLAGS += -std=c++20 -fmodules-ts
CCFLAGS += $(CCFLAGS_$(BUILD_PROFILE))
CCFLAGS += $(ARCHFLAGS)
CCFLAGS += $(INCLUDES)
CCFLAGS += -DJABYENGINE_$(TV_FORMAT)
#Linker flags
LDFLAGS_release += -Os
LDFLAGS_all += -Wl,-Map=$(TARGET).map -nostdlib -T$(JABY_ENGINE_DIR)/mkfile/psexe.ld -static -Wl,--gc-sections -Wl,--build-id=none -Wl,--no-check-sections
LDFLAGS_all += $(ARCHFLAGS) -Wl,--oformat=$(FORMAT)
LDFLAGS_all += $(LDFLAGS_$(BUILD_PROFILE))
LIBS_all += $(LIBS_$(BUILD_PROFILE))
DEPS = -Wp,-MMD,$(@:%.o=%.d),-MT,$@
#Object files list
MODS += $(call rwildcard,$(JABY_ENGINE_DIR)/include/modules, cxx)
SRCS := $(MODS) $(SRCS)
OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(call substitute,$(basename $(SRCS)))))
#Compiling rule
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.s)
@mkdir -p $(dir $@)
$(CC) -c $(DEPS) -o $@ $(CCFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.c)
@mkdir -p $(dir $@)
$(CC) -c $(DEPS) -o $@ $(CCFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.cpp)
@mkdir -p $(dir $@)
$(CXX) -c $(DEPS) -o $@ $(CCFLAGS) $(CXXFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.cxx)
@mkdir -p $(dir $@)
$(CXX) -c $(DEPS) -o $@ $(CCFLAGS) $(CXXFLAGS) $<
#Inclusion of dependencies (object files to source and includes)
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(SELF_DIR)ExportPath.mk
substitute = $(subst $(JABY_ENGINE_DIR)/include/modules,!JABYENGINEMODULES,$(subst ..,!super,$1))
desubstitute = $(subst !JABYENGINEMODULES,$(JABY_ENGINE_DIR)/include/modules,$(subst !super,..,$1))
#Build architecture/variant string, possible values: x86, armv7le, etc...
PLATFORM ?= PSX
#Build profile, possible values: release, debug, profile, coverage
BUILD_DIR ?= bin
BUILD_PROFILE ?= debug
TV_FORMAT ?= PAL
CONFIG_NAME ?= $(PLATFORM)-$(BUILD_PROFILE)
OUTPUT_DIR = $(BUILD_DIR)/$(CONFIG_NAME)
TARGET = $(OUTPUT_DIR)/$(ARTIFACT)
#Compiler definitions
HAS_LINUX_MIPS_GCC = $(shell which mipsel-linux-gnu-gcc > /dev/null 2> /dev/null && echo true || echo false)
ifeq ($(HAS_LINUX_MIPS_GCC),true)
PREFIX ?= mipsel-linux-gnu
FORMAT ?= elf32-tradlittlemips
else
PREFIX ?= mipsel-none-elf
FORMAT ?= elf32-littlemips
endif
#Take this to PSEXETarget.mk??
#LDSCRIPT ?= $(PSCX_REDUX_DIR)/ps-exe.ld
#ifneq ($(strip $(OVERLAYSCRIPT)),)
#LDSCRIPT := $(addprefix $(OVERLAYSCRIPT) , -T$(LDSCRIPT))
#else
#LDSCRIPT := $(addprefix $(PSCX_REDUX_DIR)/default.ld , -T$(LDSCRIPT))
#endif
CC = $(PREFIX)-gcc
CXX = $(PREFIX)-g++
LD = $(CXX)
AR = ar
#architecture flags
ARCHFLAGS = -march=r2000 -mtune=r2000 -mabi=32 -EL -fno-pic -mno-shared -nostdinc -nostdinc++ -mno-abicalls -mfp32 -mno-llsc
ARCHFLAGS += -fno-stack-protector -nostdlib -ffreestanding
#Compiler flags for build profiles
CCFLAGS_release += -O3
CCFLAGS_debug += -O0
CXXFLAGS += -fno-exceptions -fno-rtti
CCFLAGS += -mno-gpopt -fomit-frame-pointer -ffunction-sections -fdata-sections
CCFLAGS += -fno-builtin -fno-strict-aliasing -Wno-attributes
CCFLAGS += -std=c++20 -fmodules-ts
CCFLAGS += $(CCFLAGS_$(BUILD_PROFILE))
CCFLAGS += $(ARCHFLAGS)
CCFLAGS += $(INCLUDES)
CCFLAGS += -DJABYENGINE_$(TV_FORMAT)
#Linker flags
LDFLAGS_release += -Os
LDFLAGS_all += -Wl,-Map=$(TARGET).map -nostdlib -T$(JABY_ENGINE_DIR)/mkfile/psexe.ld -static -Wl,--gc-sections -Wl,--build-id=none -Wl,--no-check-sections
LDFLAGS_all += $(ARCHFLAGS) -Wl,--oformat=$(FORMAT)
LDFLAGS_all += $(LDFLAGS_$(BUILD_PROFILE))
LIBS_all += $(LIBS_$(BUILD_PROFILE))
DEPS = -Wp,-MMD,$(@:%.o=%.d),-MT,$@
#Object files list
MODS += $(call rwildcard,$(JABY_ENGINE_DIR)/include/modules, cxx)
SRCS := $(MODS) $(SRCS)
OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(call substitute,$(basename $(SRCS)))))
#Compiling rule
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.s)
@mkdir -p $(dir $@)
$(CC) -c $(DEPS) -o $@ $(CCFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.c)
@mkdir -p $(dir $@)
$(CC) -c $(DEPS) -o $@ $(CCFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.cpp)
@mkdir -p $(dir $@)
$(CXX) -c $(DEPS) -o $@ $(CCFLAGS) $(CXXFLAGS) $<
.SECONDEXPANSION:
$(OUTPUT_DIR)/%.o: $$(call desubstitute,%.cxx)
@mkdir -p $(dir $@)
$(CXX) -c $(DEPS) -o $@ $(CCFLAGS) $(CXXFLAGS) $<
#Inclusion of dependencies (object files to source and includes)
-include $(OBJS:%.o=%.d)

View File

@ -1,37 +1,37 @@
#Not intended to be overriden
AUTO_OVERLAY_DIR = $(OUTPUT_DIR)/auto_overlay
include $(AUTO_OVERLAY_DIR)/Overlays.mk
#We use the JabyEngine so we will include ourselves
JABY_ENGINE_LIB_DIR = $(JABY_ENGINE_DIR)/lib/PSX-$(BUILD_PROFILE)
JABY_ENGINE_LIB_NAME = JabyEngine_$(TV_FORMAT)
OVERLAY_TARGET = $(foreach ovl, $(OVERLAYSECTION), $(OUTPUT_DIR)/Overlay$(ovl))
#Linking rule
$(TARGET).elf: $(OBJS) $(JABY_ENGINE_LIB_DIR)/lib$(JABY_ENGINE_LIB_NAME).a $(AUTO_OVERLAY_DIR)/Overlays.ld
$(LD) -o $(TARGET).elf $(LDFLAGS_all) $(LDFLAGS) $(OBJS) -L$(JABY_ENGINE_LIB_DIR) -L$(AUTO_OVERLAY_DIR) -l$(JABY_ENGINE_LIB_NAME) $(LIBS)
#Strips the psexe
$(TARGET).psexe: $(TARGET).elf
$(PREFIX)-objcopy $(addprefix -R , $(OVERLAYSECTION)) -O binary $< $@
#Create overlays
$(OVERLAY_TARGET): $(TARGET).elf
$(PREFIX)-objcopy -j $(suffix $@) -O binary $< $@
#Create overlay makefile
$(AUTO_OVERLAY_DIR)/Overlays.mk: $(OVERLAY_CONFIG)
@mkdir -p $(AUTO_OVERLAY_DIR)
mkoverlay --mk-file $(AUTO_OVERLAY_DIR)/Overlays.mk --ld-script $(AUTO_OVERLAY_DIR)/Overlays.ld $<
#Rules section for default compilation and linking
all: $(TARGET).psexe $(OVERLAY_TARGET)
clean:
rm -fr $(OUTPUT_DIR)
# For mkoverlay to function correctly this is required (otherwise Overlays.mk is not re-generated)
rebuild: clean
$(MAKE) all
#Not intended to be overriden
AUTO_OVERLAY_DIR = $(OUTPUT_DIR)/auto_overlay
include $(AUTO_OVERLAY_DIR)/Overlays.mk
#We use the JabyEngine so we will include ourselves
JABY_ENGINE_LIB_DIR = $(JABY_ENGINE_DIR)/lib/PSX-$(BUILD_PROFILE)
JABY_ENGINE_LIB_NAME = JabyEngine_$(TV_FORMAT)
OVERLAY_TARGET = $(foreach ovl, $(OVERLAYSECTION), $(OUTPUT_DIR)/Overlay$(ovl))
#Linking rule
$(TARGET).elf: $(OBJS) $(JABY_ENGINE_LIB_DIR)/lib$(JABY_ENGINE_LIB_NAME).a $(AUTO_OVERLAY_DIR)/Overlays.ld
$(LD) -o $(TARGET).elf $(LDFLAGS_all) $(LDFLAGS) $(OBJS) -L$(JABY_ENGINE_LIB_DIR) -L$(AUTO_OVERLAY_DIR) -l$(JABY_ENGINE_LIB_NAME) $(LIBS)
#Strips the psexe
$(TARGET).psexe: $(TARGET).elf
$(PREFIX)-objcopy $(addprefix -R , $(OVERLAYSECTION)) -O binary $< $@
#Create overlays
$(OVERLAY_TARGET): $(TARGET).elf
$(PREFIX)-objcopy -j $(suffix $@) -O binary $< $@
#Create overlay makefile
$(AUTO_OVERLAY_DIR)/Overlays.mk: $(OVERLAY_CONFIG)
@mkdir -p $(AUTO_OVERLAY_DIR)
mkoverlay --mk-file $(AUTO_OVERLAY_DIR)/Overlays.mk --ld-script $(AUTO_OVERLAY_DIR)/Overlays.ld $<
#Rules section for default compilation and linking
all: $(TARGET).psexe $(OVERLAY_TARGET)
clean:
rm -fr $(OUTPUT_DIR)
# For mkoverlay to function correctly this is required (otherwise Overlays.mk is not re-generated)
rebuild: clean
$(MAKE) all

View File

@ -1,2 +1,2 @@
#Macro to expand files recursively: parameters $1 - directory, $2 - extension, i.e. cpp
#Macro to expand files recursively: parameters $1 - directory, $2 - extension, i.e. cpp
rwildcard = $(wildcard $(addprefix $1/*.,$2)) $(foreach d,$(wildcard $1/*),$(call rwildcard,$d,$2))

View File

@ -1,251 +1,251 @@
/*
MIT License
Copyright (c) 2019 PCSX-Redux authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
OUTPUT_FORMAT("binary")
EXTERN(_ZN10JabyEngine5startEv)
ENTRY(_ZN10JabyEngine5startEv)
TLOAD_ADDR = DEFINED(TLOAD_ADDR) ? TLOAD_ADDR : 0x80010000;
MEMORY {
loader : ORIGIN = (TLOAD_ADDR - 0x800), LENGTH = 2048
ram(rwx) : ORIGIN = 0x80010000, LENGTH = 2M - 0x10000
ram_alt(rwx) : ORIGIN = 0x80010000, LENGTH = 2M - 0x10000
dcache : ORIGIN = 0x1f800000, LENGTH = 0x400
}
__ram_top = ORIGIN(ram) + LENGTH(ram);
__sp = __ram_top - 0x100;
__dcache = ORIGIN(dcache);
__dcache_top = ORIGIN(dcache) + LENGTH(dcache);
__bss_len = (__bss_end - __bss_start);
__ftext_len = (__ftext_end - __ftext_start);
__fdata_len = (__planschi_end - __fdata_start);
__persistent_lbas_len = (__persistent_lbas_end - __persistent_lbas_start);
__stack_start = ORIGIN(ram) + LENGTH(ram);
SECTIONS {
/DISCARD/ : { *(.MIPS.abiflags) }
/* Everything is statically linked, so discard PLTs. */
/DISCARD/ : { *(.rel.iplt) *(.rela.iplt) *(.rel.plt) *(.rela.plt) *(.plt) *(.iplt) }
/* Discard things that the standard link script drops, too. */
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu.*) *(.comment) }
}
/*Overlay sections created by mkoverlay*/
INCLUDE Overlays.ld
SECTIONS {
.planschi __engine_bss_end : SUBALIGN(4)
{
__planschi_start = .;
__boot_loader_start = .;
*libJabyEngine_*.a:*_boot.o(.text.startup._GLOBAL__*)
*_boot.o(.text.startup._GLOBAL__*)
*libJabyEngine_*.a:*_boot.o(.ctors)
*_boot.o(.ctors)
*libJabyEngine_*.a:*_boot.o(.text.*)
*_boot.o(.text.*)
*libJabyEngine_*.a:*_boot.o(.rodata*)
*_boot.o(.rodata*)
*libJabyEngine_*.a:*_boot.o(.sdata*)
*_boot.o(.sdata*)
*libJabyEngine_*.a:*_boot.o(.data*)
*_boot.o(.data*)
*libJabyEngine_*.a:*_boot.o(.sbss*)
*_boot.o(.sbss*)
*libJabyEngine_*.a:*_boot.o(.bss*)
*_boot.o(.bss*)
*libJabyEngine_*.a:*_boot.o(*)
*_boot.o(*)
. = ALIGN(4);
__boot_loader_end = .;
/*Only needed for the PSX BIOS to load the entire game*/
. = ALIGN(2048);
__planschi_end = .;
} > ram_alt
}
SECTIONS {
.PSX_EXE_Header : {
/*
0x0000 - 0x0007 : "PS-X EXE"
*/
BYTE(80); BYTE(83); BYTE(45); BYTE(88); BYTE(32); BYTE(69); BYTE(88); BYTE(69);
/* 0x0008 - 0x000F : skip text_off and data_off since they're not supported by the PS1 BIOS */
LONG(0); LONG(0);
/* 0x0010 - 0x0013 : entry point */
LONG(ABSOLUTE(_ZN10JabyEngine5startEv));
/* 0x0014 - 0x0017 : initial value of $gp */
LONG(0);
/* 0x0018 - 0x001B : Memory address to load "text" section to. */
/*
NOTE: The "text" section is actually all of the "load"
sections of the file including .text, .rodata, .data.
etc.
*/
LONG(TLOAD_ADDR);
/* 0x001C - 0x001F : size, in bytes, of the "text" section. */
LONG(__persistent_lbas_len + __ftext_len + __fdata_len);
/* 0x0020 - 0x002F :
Skip "data_addr", "data_size", "bss_addr" and "bss_size".
None of these are supported by retail PS1 BIOS.
*/
LONG(0); LONG(0);
LONG(0); LONG(0);
/* 0x0030 - 0x0033 : Initial stack address. */
LONG(DEFINED(_sp) ? ABSOLUTE(_sp) : 0x801FFF00);
/* 0x0034 - 0x0037 : Initial stack size, set it to 0. */
LONG(0);
/* Skip the remaining fields as they're not supported by the BIOS */
/* e.g. 2048 header bytes minus whatever we've actually used */
. = . + 1992;
} > loader
.persistent_lbas TLOAD_ADDR : {
__persistent_lbas_start = .;
__persistent_lbas = .;
KEEP(*(.header.lbas))
. = ALIGN(4);
__persistent_lbas_end = .;
} > ram
__ftext_start = ABSOLUTE(.);
.text : {
__text_start = .;
*(.start)
*(.init)
KEEP (*(SORT_NONE(.fini)))
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
. = ALIGN(16);
KEEP(*(.init))
. = ALIGN(16);
KEEP(*(.fini))
. = ALIGN(16);
__text_end = .;
} > ram
__ftext_end = ABSOLUTE(.);
__fdata_start = ABSOLUTE(.);
.rodata : {
*(.rodata .rodata.* .rdata .rdata.* .gnu.linkonce.r.*)
. = ALIGN(16);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(16);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
. = ALIGN(16);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
__init_array_end = .;
. = ALIGN(16);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
__fini_array_end = .;
__build_id = .;
*(.note.gnu.build-id)
__build_id_end = .;
} > ram
.rodata1 : {
*(.rodata1)
} > ram
.data : {
__data_start = .;
*(.a0table)
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
*(.got.plt)
*(.got)
__data_end = .;
} > ram
.engine_bss : {
__engine_bss_start = .;
*libJabyEngine_*.a:*(.dynsbss)
*libJabyEngine_*.a:*(.sbss .sbss.* .gnu.linkonce.sb.*)
*libJabyEngine_*.a:*(.scommon)
*libJabyEngine_*.a:*(.dynbss)
*libJabyEngine_*.a:*(.bss .bss.* .gnu.linkonce.b.*)
*libJabyEngine_*.a:*(COMMON)
. = ALIGN(4);
__engine_bss_end = .;
} > ram
__fdata_end = .;
.bss __persistent_overlay_end (NOLOAD) : {
__bss_start = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > ram
__heap_start = __bss_end;
__end = .;
/*
MIT License
Copyright (c) 2019 PCSX-Redux authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
OUTPUT_FORMAT("binary")
EXTERN(_ZN10JabyEngine5startEv)
ENTRY(_ZN10JabyEngine5startEv)
TLOAD_ADDR = DEFINED(TLOAD_ADDR) ? TLOAD_ADDR : 0x80010000;
MEMORY {
loader : ORIGIN = (TLOAD_ADDR - 0x800), LENGTH = 2048
ram(rwx) : ORIGIN = 0x80010000, LENGTH = 2M - 0x10000
ram_alt(rwx) : ORIGIN = 0x80010000, LENGTH = 2M - 0x10000
dcache : ORIGIN = 0x1f800000, LENGTH = 0x400
}
__ram_top = ORIGIN(ram) + LENGTH(ram);
__sp = __ram_top - 0x100;
__dcache = ORIGIN(dcache);
__dcache_top = ORIGIN(dcache) + LENGTH(dcache);
__bss_len = (__bss_end - __bss_start);
__ftext_len = (__ftext_end - __ftext_start);
__fdata_len = (__planschi_end - __fdata_start);
__persistent_lbas_len = (__persistent_lbas_end - __persistent_lbas_start);
__stack_start = ORIGIN(ram) + LENGTH(ram);
SECTIONS {
/DISCARD/ : { *(.MIPS.abiflags) }
/* Everything is statically linked, so discard PLTs. */
/DISCARD/ : { *(.rel.iplt) *(.rela.iplt) *(.rel.plt) *(.rela.plt) *(.plt) *(.iplt) }
/* Discard things that the standard link script drops, too. */
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu.*) *(.comment) }
}
/*Overlay sections created by mkoverlay*/
INCLUDE Overlays.ld
SECTIONS {
.planschi __engine_bss_end : SUBALIGN(4)
{
__planschi_start = .;
__boot_loader_start = .;
*libJabyEngine_*.a:*_boot.o(.text.startup._GLOBAL__*)
*_boot.o(.text.startup._GLOBAL__*)
*libJabyEngine_*.a:*_boot.o(.ctors)
*_boot.o(.ctors)
*libJabyEngine_*.a:*_boot.o(.text.*)
*_boot.o(.text.*)
*libJabyEngine_*.a:*_boot.o(.rodata*)
*_boot.o(.rodata*)
*libJabyEngine_*.a:*_boot.o(.sdata*)
*_boot.o(.sdata*)
*libJabyEngine_*.a:*_boot.o(.data*)
*_boot.o(.data*)
*libJabyEngine_*.a:*_boot.o(.sbss*)
*_boot.o(.sbss*)
*libJabyEngine_*.a:*_boot.o(.bss*)
*_boot.o(.bss*)
*libJabyEngine_*.a:*_boot.o(*)
*_boot.o(*)
. = ALIGN(4);
__boot_loader_end = .;
/*Only needed for the PSX BIOS to load the entire game*/
. = ALIGN(2048);
__planschi_end = .;
} > ram_alt
}
SECTIONS {
.PSX_EXE_Header : {
/*
0x0000 - 0x0007 : "PS-X EXE"
*/
BYTE(80); BYTE(83); BYTE(45); BYTE(88); BYTE(32); BYTE(69); BYTE(88); BYTE(69);
/* 0x0008 - 0x000F : skip text_off and data_off since they're not supported by the PS1 BIOS */
LONG(0); LONG(0);
/* 0x0010 - 0x0013 : entry point */
LONG(ABSOLUTE(_ZN10JabyEngine5startEv));
/* 0x0014 - 0x0017 : initial value of $gp */
LONG(0);
/* 0x0018 - 0x001B : Memory address to load "text" section to. */
/*
NOTE: The "text" section is actually all of the "load"
sections of the file including .text, .rodata, .data.
etc.
*/
LONG(TLOAD_ADDR);
/* 0x001C - 0x001F : size, in bytes, of the "text" section. */
LONG(__persistent_lbas_len + __ftext_len + __fdata_len);
/* 0x0020 - 0x002F :
Skip "data_addr", "data_size", "bss_addr" and "bss_size".
None of these are supported by retail PS1 BIOS.
*/
LONG(0); LONG(0);
LONG(0); LONG(0);
/* 0x0030 - 0x0033 : Initial stack address. */
LONG(DEFINED(_sp) ? ABSOLUTE(_sp) : 0x801FFF00);
/* 0x0034 - 0x0037 : Initial stack size, set it to 0. */
LONG(0);
/* Skip the remaining fields as they're not supported by the BIOS */
/* e.g. 2048 header bytes minus whatever we've actually used */
. = . + 1992;
} > loader
.persistent_lbas TLOAD_ADDR : {
__persistent_lbas_start = .;
__persistent_lbas = .;
KEEP(*(.header.lbas))
. = ALIGN(4);
__persistent_lbas_end = .;
} > ram
__ftext_start = ABSOLUTE(.);
.text : {
__text_start = .;
*(.start)
*(.init)
KEEP (*(SORT_NONE(.fini)))
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
. = ALIGN(16);
KEEP(*(.init))
. = ALIGN(16);
KEEP(*(.fini))
. = ALIGN(16);
__text_end = .;
} > ram
__ftext_end = ABSOLUTE(.);
__fdata_start = ABSOLUTE(.);
.rodata : {
*(.rodata .rodata.* .rdata .rdata.* .gnu.linkonce.r.*)
. = ALIGN(16);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(16);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
. = ALIGN(16);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
__init_array_end = .;
. = ALIGN(16);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
__fini_array_end = .;
__build_id = .;
*(.note.gnu.build-id)
__build_id_end = .;
} > ram
.rodata1 : {
*(.rodata1)
} > ram
.data : {
__data_start = .;
*(.a0table)
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
*(.got.plt)
*(.got)
__data_end = .;
} > ram
.engine_bss : {
__engine_bss_start = .;
*libJabyEngine_*.a:*(.dynsbss)
*libJabyEngine_*.a:*(.sbss .sbss.* .gnu.linkonce.sb.*)
*libJabyEngine_*.a:*(.scommon)
*libJabyEngine_*.a:*(.dynbss)
*libJabyEngine_*.a:*(.bss .bss.* .gnu.linkonce.b.*)
*libJabyEngine_*.a:*(COMMON)
. = ALIGN(4);
__engine_bss_end = .;
} > ram
__fdata_end = .;
.bss __persistent_overlay_end (NOLOAD) : {
__bss_start = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > ram
__heap_start = __bss_end;
__end = .;
}

View File

@ -1,50 +1,50 @@
include ../../mkfile/RebuildTarget.mk
JABY_ENGINE_DIR = ../../
ARTIFACT = libJabyEngine_$(TV_FORMAT)
BUILD_DIR = bin
SPLASH_IMAGE = src/BootLoader/splash_image_pal_boot.hpp
SPLASH_IMAGE_NTSC = src/BootLoader/splash_image_ntsc_boot.hpp
CCFLAGS += -Iinclude -I../../include -D__friends=public
CCFLAGS += -save-temps=obj
include ../../mkfile/Wildcard.mk
SRCS = $(call rwildcard, src, c cpp s)
include ../../mkfile/Makefile
LIB_DIR = ../../lib/$(CONFIG_NAME)
MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS))
#$(info $$var is [${MAIN_BOOT_OBJ}])
#$(info $$var2 is [${MAIN_LIB_OBJS}])
#Linking rule
$(TARGET).a: $(MAIN_LIB_OBJS) $(SPLASH_IMAGE)
@mkdir -p $(dir $@)
$(AR) rcs $(TARGET).a $(MAIN_LIB_OBJS)
#Copy rules
$(LIB_DIR)/$(ARTIFACT).a: $(TARGET).a
@mkdir -p $(LIB_DIR)
cp $(TARGET).a $(LIB_DIR)/$(ARTIFACT).a
# Improve later
# rule to make the boot image
$(SPLASH_IMAGE): ressources/Splash.png
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
$(SPLASH_IMAGE_NTSC): ressources/Splash_ntsc.png
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
#Rules section for default compilation and linking
all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a
clean:
rm -fr $(SPLASH_IMAGE)
rm -fr $(SPLASH_IMAGE_NTSC)
rm -fr $(OUTPUT_DIR)
rm -fr gcm.cache
include ../../mkfile/RebuildTarget.mk
JABY_ENGINE_DIR = ../../
ARTIFACT = libJabyEngine_$(TV_FORMAT)
BUILD_DIR = bin
SPLASH_IMAGE = src/BootLoader/splash_image_pal_boot.hpp
SPLASH_IMAGE_NTSC = src/BootLoader/splash_image_ntsc_boot.hpp
CCFLAGS += -Iinclude -I../../include -D__friends=public
CCFLAGS += -save-temps=obj
include ../../mkfile/Wildcard.mk
SRCS = $(call rwildcard, src, c cpp s)
include ../../mkfile/Makefile
LIB_DIR = ../../lib/$(CONFIG_NAME)
MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS))
#$(info $$var is [${MAIN_BOOT_OBJ}])
#$(info $$var2 is [${MAIN_LIB_OBJS}])
#Linking rule
$(TARGET).a: $(MAIN_LIB_OBJS) $(SPLASH_IMAGE)
@mkdir -p $(dir $@)
$(AR) rcs $(TARGET).a $(MAIN_LIB_OBJS)
#Copy rules
$(LIB_DIR)/$(ARTIFACT).a: $(TARGET).a
@mkdir -p $(LIB_DIR)
cp $(TARGET).a $(LIB_DIR)/$(ARTIFACT).a
# Improve later
# rule to make the boot image
$(SPLASH_IMAGE): ressources/Splash.png
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
$(SPLASH_IMAGE_NTSC): ressources/Splash_ntsc.png
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
#Rules section for default compilation and linking
all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a
clean:
rm -fr $(SPLASH_IMAGE)
rm -fr $(SPLASH_IMAGE_NTSC)
rm -fr $(OUTPUT_DIR)
rm -fr gcm.cache
rm -fr $(LIB_DIR)/$(ARTIFACT).a

View File

@ -1,53 +1,53 @@
#include "../../internal-include/BootLoader/boot_loader.hpp"
#include "../../internal-include/CD/cd_internal.hpp"
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/IOPorts/memory_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace CD {
namespace internal {
extern SysCall::InterrupCallback callback;
}
}
namespace boot {
namespace CD {
using JabyEngine::CD::internal::Command;
void setup() {
static constexpr auto DebugX = 1;
static constexpr auto DebugY = 1;
static constexpr auto DebugScale = 1.0;
__debug_boot_color_at(::JabyEngine::GPU::Color24::White(), DebugX, DebugY, DebugScale);
SysCall::EnterCriticalSection();
Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::create());
Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::create());
SysCall::SysEnqIntRP(SysCall::Priority::CdromIoIrq, &::JabyEngine::CD::internal::callback);
CD_IO::PortIndex1::change_to();
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable);
Interrupt::enable_irq(Interrupt::CDROM);
Interrupt::ack_irq(Interrupt::CDROM);
SysCall::ExitCriticalSection();
__debug_boot_color_at(::JabyEngine::GPU::Color24::Red(), DebugX, DebugY, DebugScale);
CD_IO::PortIndex0::change_to();
__debug_boot_color_at(::JabyEngine::GPU::Color24::Green(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
__debug_boot_color_at(::JabyEngine::GPU::Color24::Blue(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
__debug_boot_color_at(::JabyEngine::GPU::Color24::Yellow(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::Init);
// Demute?
}
}
}
#include "../../internal-include/BootLoader/boot_loader.hpp"
#include "../../internal-include/CD/cd_internal.hpp"
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/IOPorts/memory_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace CD {
namespace internal {
extern SysCall::InterrupCallback callback;
}
}
namespace boot {
namespace CD {
using JabyEngine::CD::internal::Command;
void setup() {
static constexpr auto DebugX = 1;
static constexpr auto DebugY = 1;
static constexpr auto DebugScale = 1.0;
__debug_boot_color_at(::JabyEngine::GPU::Color24::White(), DebugX, DebugY, DebugScale);
SysCall::EnterCriticalSection();
Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::create());
Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::create());
SysCall::SysEnqIntRP(SysCall::Priority::CdromIoIrq, &::JabyEngine::CD::internal::callback);
CD_IO::PortIndex1::change_to();
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable);
Interrupt::enable_irq(Interrupt::CDROM);
Interrupt::ack_irq(Interrupt::CDROM);
SysCall::ExitCriticalSection();
__debug_boot_color_at(::JabyEngine::GPU::Color24::Red(), DebugX, DebugY, DebugScale);
CD_IO::PortIndex0::change_to();
__debug_boot_color_at(::JabyEngine::GPU::Color24::Green(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
__debug_boot_color_at(::JabyEngine::GPU::Color24::Blue(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
__debug_boot_color_at(::JabyEngine::GPU::Color24::Yellow(), DebugX, DebugY, DebugScale);
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::Init);
// Demute?
}
}
}
}

View File

@ -1,83 +1,83 @@
#include "../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/Auxiliary/lz4_decompressor.hpp>
#include <PSX/File/Processor/file_processor.hpp>
#include <PSX/GPU/gpu.hpp>
#include <PSX/System/syscalls.hpp>
#include <stdio.h>
#ifdef JABYENGINE_PAL
#include "splash_image_pal_boot.hpp"
#else
#include "splash_image_ntsc_boot.hpp"
#endif //JABYENGINE_PAL
extern "C" uint32_t __boot_loader_end;
namespace JabyEngine {
namespace GPU {
namespace internal {
extern SysCall::InterrupCallback callback;
}
}
namespace boot {
namespace GPU {
using namespace JabyEngine::GPU;
static void configurate_display() {
// Ideal I hope that an offset of 0,0 will produce a well enough centered picture for every TV
GPU_IO::GP1.write(GPU_IO::Command::DisplayMode(::JabyEngine::GPU::internal::Display::DisplayMode));
GPU::Display::set_offset(0, 0);
}
static size_t decompress_logo() {
LZ4Decompressor lz4_decomp(reinterpret_cast<uint8_t*>(&__boot_loader_end));
const auto [progress, bytes_ready] = lz4_decomp.process(ArrayRange(SplashScreen, sizeof(SplashScreen)), true);
switch(progress) {
case Progress::InProgress:
printf("Decompressing still in progress... %llu\n", bytes_ready);
break;
case Progress::Error:
printf("Error decompressing!!!\n");
break;
case Progress::Done:
printf("Done decompressing: %llu Bytes ready\n", bytes_ready);
break;
}
return bytes_ready;
}
void display_logo() {
const auto bytes_ready = decompress_logo();
// Upload SplashScreen picture
auto state = FileProcessor::create(&__boot_loader_end, SimpleTIM(32, 0, 0, 0));
state.process(bytes_ready);
// Duplicate DisplayBuffer content
::JabyEngine::GPU::internal::copy_vram_to_vram({PositionU16::create(0, Display::Height), SizeU16::create(Display::Width, Display::Height)}, PositionU16::create(0, 0));
Display::enable();
}
void setup() {
GPU_IO::GP1.write(GPU_IO::Command::Reset());
configurate_display();
::JabyEngine::GPU::internal::Display::exchange_buffer_and_display();
GPU::internal::wait_ready_for_CMD();
GPU::internal::quick_fill_fast(Color24::Black(), {PositionU16::create(0, 0), SizeU16::create(Display::Width, Display::Height)});
SysCall::EnterCriticalSection();
SysCall::SysEnqIntRP(SysCall::Priority::VblankIrq, &::JabyEngine::GPU::internal::callback);
Interrupt::enable_irq(Interrupt::VBlank);
SysCall::ExitCriticalSection();
}
}
}
#include "../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/Auxiliary/lz4_decompressor.hpp>
#include <PSX/File/Processor/file_processor.hpp>
#include <PSX/GPU/gpu.hpp>
#include <PSX/System/syscalls.hpp>
#include <stdio.h>
#ifdef JABYENGINE_PAL
#include "splash_image_pal_boot.hpp"
#else
#include "splash_image_ntsc_boot.hpp"
#endif //JABYENGINE_PAL
extern "C" uint32_t __boot_loader_end;
namespace JabyEngine {
namespace GPU {
namespace internal {
extern SysCall::InterrupCallback callback;
}
}
namespace boot {
namespace GPU {
using namespace JabyEngine::GPU;
static void configurate_display() {
// Ideal I hope that an offset of 0,0 will produce a well enough centered picture for every TV
GPU_IO::GP1.write(GPU_IO::Command::DisplayMode(::JabyEngine::GPU::internal::Display::DisplayMode));
GPU::Display::set_offset(0, 0);
}
static size_t decompress_logo() {
LZ4Decompressor lz4_decomp(reinterpret_cast<uint8_t*>(&__boot_loader_end));
const auto [progress, bytes_ready] = lz4_decomp.process(ArrayRange(SplashScreen, sizeof(SplashScreen)), true);
switch(progress) {
case Progress::InProgress:
printf("Decompressing still in progress... %llu\n", bytes_ready);
break;
case Progress::Error:
printf("Error decompressing!!!\n");
break;
case Progress::Done:
printf("Done decompressing: %llu Bytes ready\n", bytes_ready);
break;
}
return bytes_ready;
}
void display_logo() {
const auto bytes_ready = decompress_logo();
// Upload SplashScreen picture
auto state = FileProcessor::create(&__boot_loader_end, SimpleTIM(32, 0, 0, 0));
state.process(bytes_ready);
// Duplicate DisplayBuffer content
::JabyEngine::GPU::internal::copy_vram_to_vram({PositionU16::create(0, Display::Height), SizeU16::create(Display::Width, Display::Height)}, PositionU16::create(0, 0));
Display::enable();
}
void setup() {
GPU_IO::GP1.write(GPU_IO::Command::Reset());
configurate_display();
::JabyEngine::GPU::internal::Display::exchange_buffer_and_display();
GPU::internal::wait_ready_for_CMD();
GPU::internal::quick_fill_fast(Color24::Black(), {PositionU16::create(0, 0), SizeU16::create(Display::Width, Display::Height)});
SysCall::EnterCriticalSection();
SysCall::SysEnqIntRP(SysCall::Priority::VblankIrq, &::JabyEngine::GPU::internal::callback);
Interrupt::enable_irq(Interrupt::VBlank);
SysCall::ExitCriticalSection();
}
}
}
}

View File

@ -1,141 +1,141 @@
#include "../../internal-include/CD/cd_internal.hpp"
#include <PSX/System/IOPorts/dma_io.hpp>
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace CD {
namespace internal {
static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector);
static SysCall::InterruptVerifierResult interrupt_verifier();
static uint32_t interrupt_handler(uint32_t);
static SectorBufferAllocator sector_allocator;
static uint32_t cur_lba;
static uint32_t dst_lba;
CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None;
uint8_t cmd_interrupt_bit = 0;
State current_state = State::Free;
SysCall::InterrupCallback callback = {
.next = nullptr,
.handler_function = interrupt_handler,
.verifier_function = interrupt_verifier
};
static void pause_cd() {
CD_IO::PortIndex0::change_to();
Command::send<CD_IO::PortIndex0>(CD_IO::Command::Pause);
}
// Requires Index0
static void read_cd(uint32_t lba) {
const auto loc = CDTimeStamp::from(lba);
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd());
Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadN);
current_state = State::Reading;
}
static void read_sector_dma(CD_IO::DataSector& sector) {
static const auto WaitSectorReady = []() {
while(!CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::HasDataFifoData));
};
static const auto ReadSector = [](uint32_t* dst) {
DMA_IO::CDROM.set_adr(reinterpret_cast<uintptr_t>(dst));
DMA_IO::CDROM.block_ctrl.write(DMA_IO::BCR::SyncMode0::for_cd());
DMA_IO::CDROM.channel_ctrl.write(DMA_IO::CHCHR::StartCDROM());
DMA_IO::CDROM.wait();
CD_IO::PortIndex0::Request.write(CD_IO::Request::reset());
};
WaitSectorReady();
ReadSector(sector.data);
}
static void read_sector_to(CD_IO::DataSector& sector) {
CD_IO::PortIndex0::change_to();
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
// We only support DMA rn
read_sector_dma(sector);
// Do we ever want to support reading via IO Port?
// Doesn't seem to important when we can use DMA
}
static SysCall::InterruptVerifierResult interrupt_verifier() {
if(Interrupt::is_irq(Interrupt::CDROM)) {
return SysCall::InterruptVerifierResult::ExecuteHandler;
}
else {
return SysCall::InterruptVerifierResult::SkipHandler;
}
}
static uint32_t interrupt_handler(uint32_t) {
const auto old_status = CD_IO::IndexStatus.read();
CD_IO::PortIndex1::change_to();
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
last_interrupt = cur_irq;
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq);
if(cur_irq == CD_IO::Interrupt::DataReady) {
// Obtain sector content here
auto* sector = sector_allocator.allocate_sector();
if(sector) {
//Now obtain sector
read_sector_to(*sector);
cur_lba++;
if(cur_lba == dst_lba) {
current_state = State::Done;
pause_cd();
}
}
else {
current_state = State::BufferFull;
pause_cd();
}
}
else if(cur_irq == CD_IO::Interrupt::DiskError) {
current_state = State::Error;
}
// No masking required because we can only write bit 0 - 2
CD_IO::IndexStatus.write(old_status);
Interrupt::ack_irq(Interrupt::CDROM);
SysCall::ReturnFromException();
__builtin_unreachable();
}
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) {
cur_lba = file_info.get_lba();
dst_lba = cur_lba + file_info.get_size_in_sectors();
sector_allocator = buffer_allocator;
Command::wait_completed();
CD_IO::PortIndex0::change_to();
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode);
read_cd(cur_lba);
}
void continue_reading() {
if(current_state == State::BufferFull) {
Command::wait_completed();
read_cd(cur_lba);
}
}
}
}
#include "../../internal-include/CD/cd_internal.hpp"
#include <PSX/System/IOPorts/dma_io.hpp>
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace CD {
namespace internal {
static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector);
static SysCall::InterruptVerifierResult interrupt_verifier();
static uint32_t interrupt_handler(uint32_t);
static SectorBufferAllocator sector_allocator;
static uint32_t cur_lba;
static uint32_t dst_lba;
CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None;
uint8_t cmd_interrupt_bit = 0;
State current_state = State::Free;
SysCall::InterrupCallback callback = {
.next = nullptr,
.handler_function = interrupt_handler,
.verifier_function = interrupt_verifier
};
static void pause_cd() {
CD_IO::PortIndex0::change_to();
Command::send<CD_IO::PortIndex0>(CD_IO::Command::Pause);
}
// Requires Index0
static void read_cd(uint32_t lba) {
const auto loc = CDTimeStamp::from(lba);
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd());
Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadN);
current_state = State::Reading;
}
static void read_sector_dma(CD_IO::DataSector& sector) {
static const auto WaitSectorReady = []() {
while(!CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::HasDataFifoData));
};
static const auto ReadSector = [](uint32_t* dst) {
DMA_IO::CDROM.set_adr(reinterpret_cast<uintptr_t>(dst));
DMA_IO::CDROM.block_ctrl.write(DMA_IO::BCR::SyncMode0::for_cd());
DMA_IO::CDROM.channel_ctrl.write(DMA_IO::CHCHR::StartCDROM());
DMA_IO::CDROM.wait();
CD_IO::PortIndex0::Request.write(CD_IO::Request::reset());
};
WaitSectorReady();
ReadSector(sector.data);
}
static void read_sector_to(CD_IO::DataSector& sector) {
CD_IO::PortIndex0::change_to();
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
// We only support DMA rn
read_sector_dma(sector);
// Do we ever want to support reading via IO Port?
// Doesn't seem to important when we can use DMA
}
static SysCall::InterruptVerifierResult interrupt_verifier() {
if(Interrupt::is_irq(Interrupt::CDROM)) {
return SysCall::InterruptVerifierResult::ExecuteHandler;
}
else {
return SysCall::InterruptVerifierResult::SkipHandler;
}
}
static uint32_t interrupt_handler(uint32_t) {
const auto old_status = CD_IO::IndexStatus.read();
CD_IO::PortIndex1::change_to();
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
last_interrupt = cur_irq;
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq);
if(cur_irq == CD_IO::Interrupt::DataReady) {
// Obtain sector content here
auto* sector = sector_allocator.allocate_sector();
if(sector) {
//Now obtain sector
read_sector_to(*sector);
cur_lba++;
if(cur_lba == dst_lba) {
current_state = State::Done;
pause_cd();
}
}
else {
current_state = State::BufferFull;
pause_cd();
}
}
else if(cur_irq == CD_IO::Interrupt::DiskError) {
current_state = State::Error;
}
// No masking required because we can only write bit 0 - 2
CD_IO::IndexStatus.write(old_status);
Interrupt::ack_irq(Interrupt::CDROM);
SysCall::ReturnFromException();
__builtin_unreachable();
}
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) {
cur_lba = file_info.get_lba();
dst_lba = cur_lba + file_info.get_size_in_sectors();
sector_allocator = buffer_allocator;
Command::wait_completed();
CD_IO::PortIndex0::change_to();
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode);
read_cd(cur_lba);
}
void continue_reading() {
if(current_state == State::BufferFull) {
Command::wait_completed();
read_cd(cur_lba);
}
}
}
}
}

View File

@ -1,25 +1,25 @@
#ifndef __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
#define __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
#include <PSX/File/Processor/file_processor.hpp>
namespace JabyEngine {
namespace FileProcessor {
namespace Helper {
template<typename T>
static void simple_read(T& dst, State::Configuration& config) {
static constexpr size_t T_SIZE = sizeof(T);
dst = *reinterpret_cast<const T*>(config.data_adr);
config.processed(T_SIZE);
}
template<typename T>
static Progress exchange_and_execute_process_function(State::GenericProcessRoutine<T> process_routine, State::Configuration& config, T& state) {
config.process_routine = reinterpret_cast<State::ProcessRoutine>(process_routine);
return process_routine(config, state);
}
}
}
}
#ifndef __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
#define __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
#include <PSX/File/Processor/file_processor.hpp>
namespace JabyEngine {
namespace FileProcessor {
namespace Helper {
template<typename T>
static void simple_read(T& dst, State::Configuration& config) {
static constexpr size_t T_SIZE = sizeof(T);
dst = *reinterpret_cast<const T*>(config.data_adr);
config.processed(T_SIZE);
}
template<typename T>
static Progress exchange_and_execute_process_function(State::GenericProcessRoutine<T> process_routine, State::Configuration& config, T& state) {
config.process_routine = reinterpret_cast<State::ProcessRoutine>(process_routine);
return process_routine(config, state);
}
}
}
}
#endif // !__JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__

View File

@ -1,102 +1,102 @@
#include "../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/Timer/frame_timer.hpp>
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace GPU {
uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0
namespace internal {
static SysCall::InterruptVerifierResult interrupt_verifier();
static uint32_t interrupt_handler(uint32_t);
static uint8_t vsync_counter = 0;
SysCall::InterrupCallback callback = {
.next = nullptr,
.handler_function = interrupt_handler,
.verifier_function = interrupt_verifier
};
static SysCall::InterruptVerifierResult interrupt_verifier() {
if(Interrupt::is_irq(Interrupt::VBlank)) {
return SysCall::InterruptVerifierResult::ExecuteHandler;
}
else {
return SysCall::InterruptVerifierResult::SkipHandler;
}
}
static uint32_t interrupt_handler(uint32_t) {
vsync_counter++;
MasterTime::value++;
Interrupt::ack_irq(Interrupt::VBlank);
SysCall::ReturnFromException();
__builtin_unreachable();
}
uint32_t Display :: exchange_buffer_and_display() {
const uint16_t draw_area_y = (PublicDisplay::Height*PublicDisplay::current_id);
GPU::internal::set_draw_area(GPU::PositionU16::create(0, draw_area_y));
PublicDisplay::current_id ^= 1;
GPU_IO::GP1.write(GPU_IO::Command::DisplayArea(GPU::PositionU16::create(0, static_cast<uint16_t>((PublicDisplay::Height*PublicDisplay::current_id)))));
return draw_area_y;
}
void wait_vsync(uint8_t syncs) {
volatile auto& vsync_count = reinterpret_cast<volatile uint8_t&>(vsync_counter);
const uint8_t dst_value = vsync_count + syncs;
while(vsync_count != dst_value);
}
void render(const uint32_t* data, size_t words) {
wait_ready_for_CMD();
for(size_t n = 0; n < words; n++) {
GPU_IO::GP0.write({data[n]});
}
}
void render_dma(const uint32_t* data) {
wait_ready_for_CMD();
// DPCR already enabled
GPU_IO::GP1.write(GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU));
DMA_IO::GPU.set_adr(reinterpret_cast<uintptr_t>(data));
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR::SyncMode2::for_gpu_cmd());
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPULinked());
}
}
#ifndef USE_NO$PSX
void Display :: set_offset(uint16_t x, uint16_t y) {
x += 78;
y += 43;
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3));
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height));
}
#else
void Display :: set_offset(uint16_t x, uint16_t y) {
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)));
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)));
}
#endif //USE_NO$PSX
uint8_t swap_buffers_vsync(uint8_t syncs, bool clear_screen) {
// Waits for finish FIFO
internal::wait_ready_for_CMD();
internal::wait_vsync(syncs);
const int16_t draw_offset_y = internal::Display::exchange_buffer_and_display();
internal::set_draw_offset(GPU::PositionI16::create(0, draw_offset_y));
if(clear_screen) {
internal::quick_fill_fast(Color24::Black(), AreaU16::create(0, static_cast<uint16_t>(draw_offset_y), Display::Width, Display::Height));
}
return Display::current_id;
}
}
#include "../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/Timer/frame_timer.hpp>
#include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/syscalls.hpp>
namespace JabyEngine {
namespace GPU {
uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0
namespace internal {
static SysCall::InterruptVerifierResult interrupt_verifier();
static uint32_t interrupt_handler(uint32_t);
static uint8_t vsync_counter = 0;
SysCall::InterrupCallback callback = {
.next = nullptr,
.handler_function = interrupt_handler,
.verifier_function = interrupt_verifier
};
static SysCall::InterruptVerifierResult interrupt_verifier() {
if(Interrupt::is_irq(Interrupt::VBlank)) {
return SysCall::InterruptVerifierResult::ExecuteHandler;
}
else {
return SysCall::InterruptVerifierResult::SkipHandler;
}
}
static uint32_t interrupt_handler(uint32_t) {
vsync_counter++;
MasterTime::value++;
Interrupt::ack_irq(Interrupt::VBlank);
SysCall::ReturnFromException();
__builtin_unreachable();
}
uint32_t Display :: exchange_buffer_and_display() {
const uint16_t draw_area_y = (PublicDisplay::Height*PublicDisplay::current_id);
GPU::internal::set_draw_area(GPU::PositionU16::create(0, draw_area_y));
PublicDisplay::current_id ^= 1;
GPU_IO::GP1.write(GPU_IO::Command::DisplayArea(GPU::PositionU16::create(0, static_cast<uint16_t>((PublicDisplay::Height*PublicDisplay::current_id)))));
return draw_area_y;
}
void wait_vsync(uint8_t syncs) {
volatile auto& vsync_count = reinterpret_cast<volatile uint8_t&>(vsync_counter);
const uint8_t dst_value = vsync_count + syncs;
while(vsync_count != dst_value);
}
void render(const uint32_t* data, size_t words) {
wait_ready_for_CMD();
for(size_t n = 0; n < words; n++) {
GPU_IO::GP0.write({data[n]});
}
}
void render_dma(const uint32_t* data) {
wait_ready_for_CMD();
// DPCR already enabled
GPU_IO::GP1.write(GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU));
DMA_IO::GPU.set_adr(reinterpret_cast<uintptr_t>(data));
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR::SyncMode2::for_gpu_cmd());
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPULinked());
}
}
#ifndef USE_NO$PSX
void Display :: set_offset(uint16_t x, uint16_t y) {
x += 78;
y += 43;
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3));
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height));
}
#else
void Display :: set_offset(uint16_t x, uint16_t y) {
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)));
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)));
}
#endif //USE_NO$PSX
uint8_t swap_buffers_vsync(uint8_t syncs, bool clear_screen) {
// Waits for finish FIFO
internal::wait_ready_for_CMD();
internal::wait_vsync(syncs);
const int16_t draw_offset_y = internal::Display::exchange_buffer_and_display();
internal::set_draw_offset(GPU::PositionI16::create(0, draw_offset_y));
if(clear_screen) {
internal::quick_fill_fast(Color24::Black(), AreaU16::create(0, static_cast<uint16_t>(draw_offset_y), Display::Width, Display::Height));
}
return Display::current_id;
}
}
}

View File

@ -1,12 +1,12 @@
.set push
.set noreorder
.section .text, "ax", @progbits
.align 2
.global _ZN10JabyEngine7SysCall6printfEPKcz
.type _ZN10JabyEngine7SysCall6printfEPKcz, @function
_ZN10JabyEngine7SysCall6printfEPKcz:
li $t2, 0xa0
jr $t2
li $t1, 0x3f
.set push
.set noreorder
.section .text, "ax", @progbits
.align 2
.global _ZN10JabyEngine7SysCall6printfEPKcz
.type _ZN10JabyEngine7SysCall6printfEPKcz, @function
_ZN10JabyEngine7SysCall6printfEPKcz:
li $t2, 0xa0
jr $t2
li $t1, 0x3f