Compare commits
1 Commits
592e641ba9
...
david/clar
| Author | SHA1 | Date | |
|---|---|---|---|
| e07cfc8ec3 |
217
deps/ox/ox-docs.md
vendored
217
deps/ox/ox-docs.md
vendored
@@ -28,7 +28,10 @@ All components have a platform indicator next to them:
|
|||||||
Ox provides ```ox::Error``` to report errors.
|
Ox provides ```ox::Error``` to report errors.
|
||||||
```ox::Error``` is a struct that has overloaded operators to behave like an
|
```ox::Error``` is a struct that has overloaded operators to behave like an
|
||||||
integer error code, plus some extra fields to enhance debuggability.
|
integer error code, plus some extra fields to enhance debuggability.
|
||||||
```ox::Error```s will also include the file and line of the error.
|
If instantiated through the ```OxError(x)``` macro, it will also include the
|
||||||
|
file and line of the error.
|
||||||
|
The ```OxError(x)``` macro should only be used for the initial instantiation of
|
||||||
|
an ```ox::Error```.
|
||||||
|
|
||||||
In addition to ```ox::Error``` there is also the template ```ox::Result<T>```.
|
In addition to ```ox::Error``` there is also the template ```ox::Result<T>```.
|
||||||
```ox::Result``` simply wraps the type T value in a struct that also includes
|
```ox::Result``` simply wraps the type T value in a struct that also includes
|
||||||
@@ -46,7 +49,7 @@ ox::Result<int> foo(int i) noexcept {
|
|||||||
if (i < 10) {
|
if (i < 10) {
|
||||||
return i + 1; // implicitly calls ox::Result<T>::Result(T)
|
return i + 1; // implicitly calls ox::Result<T>::Result(T)
|
||||||
}
|
}
|
||||||
return ox::Error(1); // implicitly calls ox::Result<T>::Result(ox::Error)
|
return OxError(1); // implicitly calls ox::Result<T>::Result(ox::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
int caller1() {
|
int caller1() {
|
||||||
@@ -178,216 +181,6 @@ variant for creating a non-const value.
|
|||||||
|
|
||||||
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
|
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
|
||||||
|
|
||||||
### Ox String Types
|
|
||||||
|
|
||||||
Ox has six different major string types.
|
|
||||||
These types are divided into two categories: store types and view types.
|
|
||||||
|
|
||||||
String stores maintain a copy of the string data, whereas view types only
|
|
||||||
maintain a reference to the data.
|
|
||||||
Views should be used where you otherwise might use a const reference to a
|
|
||||||
string store type.
|
|
||||||
|
|
||||||
Having all of these different string types may sound like an interoperability
|
|
||||||
nightmare, but taking string view types extensively where applicable makes the
|
|
||||||
imagined interoperability issues virtually non-existent.
|
|
||||||
|
|
||||||
#### String Store Types
|
|
||||||
|
|
||||||
##### String / BasicString
|
|
||||||
|
|
||||||
```ox::String```, or really ```ox::BasicString```, is Ox's version of
|
|
||||||
```std::string```.
|
|
||||||
Like ```std::string```, ```String``` allocates to store the string data.
|
|
||||||
Also like ```std::string```, ```String``` allows for small string
|
|
||||||
optimization for strings under 8 bytes.
|
|
||||||
Unlike ```std::string```, the template that ```String``` is based on,
|
|
||||||
```BasicString```, takes a parameter that allows adjusting to different size
|
|
||||||
small string buffers.
|
|
||||||
```ox::String``` is an alias to ```ox::BasicString<8>```.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
// s can hold up to 100 bytes, plus one for a null terminator before allocating
|
|
||||||
ox::BasicString<100> s;
|
|
||||||
```
|
|
||||||
Also unlike ```std::string```, ```ox::String``` has an explicit C-string conversion
|
|
||||||
constructor.
|
|
||||||
This prevents accidental instantiations of ```String```.
|
|
||||||
|
|
||||||
Consider the following:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void fStd(std::string const&);
|
|
||||||
void fOx(ox::String const&);
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
// implicit and silent instantiation of std::string, which includes an
|
|
||||||
// allocation
|
|
||||||
fStd("123456789");
|
|
||||||
// Will fail to compile:
|
|
||||||
fOx("123456789");
|
|
||||||
// But explicit String instantiation will work:
|
|
||||||
fOx(ox::String{"123456789"});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### IString
|
|
||||||
|
|
||||||
```IString```, or "inline string", is like ```BasicString```, but it will cut
|
|
||||||
off strings that exceed that limit.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
ox::IString<5> s; // s can hold up to 5 characters, plus a null terminator
|
|
||||||
s = "12345"; // valid
|
|
||||||
s = "123456"; // will compile and run, but will get cut off at '5'
|
|
||||||
```
|
|
||||||
|
|
||||||
This is useful for certain string categories that have fixed lengths, like UUID
|
|
||||||
strings or for numbers.
|
|
||||||
|
|
||||||
Ox makes use of ```IString``` in the following ways:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
using UUIDStr = ox::IString<36>;
|
|
||||||
|
|
||||||
// and
|
|
||||||
|
|
||||||
template<Integer_c Integer>
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr auto intToStr(Integer v) noexcept {
|
|
||||||
constexpr auto Cap = [] {
|
|
||||||
auto out = 0;
|
|
||||||
switch (sizeof(Integer)) {
|
|
||||||
case 1:
|
|
||||||
out = 3;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
out = 5;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
out = 10;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
out = 21;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return out + ox::is_signed_v<Integer>;
|
|
||||||
}();
|
|
||||||
ox::IString<Cap> out;
|
|
||||||
std::ignore = out.resize(out.cap());
|
|
||||||
ox::CharBuffWriter w{{out.data(), out.cap()}};
|
|
||||||
std::ignore = writeItoa(v, w);
|
|
||||||
std::ignore = out.resize(w.tellp());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### StringParam
|
|
||||||
|
|
||||||
```StringParam``` is a weird type.
|
|
||||||
Because ```String::String(const char*)``` is explicit, it becomes a pain for
|
|
||||||
functions to take ```String```s.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct Type {
|
|
||||||
ox::String m_s;
|
|
||||||
explicit Type(ox::String p): m_s(std::move(p)) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void f() {
|
|
||||||
ox::String s{"asdf"};
|
|
||||||
Type t1{"asdf"}; // invalid - will not compile
|
|
||||||
Type t2{s}; // invalid - will not compile
|
|
||||||
Type t3{std::move(s)}; // valid
|
|
||||||
Type t4{ox::String{"asdf"}}; // valid
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```StringParam``` has implicit conversion constructors, and will appropriately
|
|
||||||
move from r-value ```String```s or create a ```String``` if not passed
|
|
||||||
ownership of an existing ```String```.
|
|
||||||
Think of ```StringParam``` as a way to opt-in to implicit instantiation with
|
|
||||||
strings.
|
|
||||||
|
|
||||||
```StringParam``` can access the string as a view through the ```view()```
|
|
||||||
function, and the ```String``` inside can be accessed by moving from the
|
|
||||||
```StringParam```.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct Type {
|
|
||||||
ox::String m_s;
|
|
||||||
explicit Type(ox::StringParam p): m_s(std::move(p)) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void f() {
|
|
||||||
ox::String s{"asdf"};
|
|
||||||
Type t1{"asdf"}; // valid
|
|
||||||
Type t2{s}; // valid
|
|
||||||
Type t3{std::move(s)}; // valid
|
|
||||||
Type t4{ox::String{"asdf"}}; // valid
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### String View Types
|
|
||||||
|
|
||||||
##### StringView
|
|
||||||
|
|
||||||
```ox::StringView``` is Ox's version of ```std::string_view```.
|
|
||||||
```StringView``` contains a pointer to a string, along with its size.
|
|
||||||
|
|
||||||
This should be the normal type taken when a function needs a string that will
|
|
||||||
exist until it returns.
|
|
||||||
|
|
||||||
##### CStringView
|
|
||||||
|
|
||||||
```CStringView``` is like ```StringView```, but it comes with the promise that
|
|
||||||
the string ends with a null terminator.
|
|
||||||
Accordingly, it has a ```c_str()``` function in addition to the ```data()```
|
|
||||||
function that ```StringView``` has.
|
|
||||||
|
|
||||||
```CStringView``` should be used when wrapping a C API that only takes C
|
|
||||||
strings.
|
|
||||||
|
|
||||||
##### StringLiteral
|
|
||||||
|
|
||||||
```StringLiteral``` is a string view type, but it kind of straddles the line
|
|
||||||
between view and store types.
|
|
||||||
Creating a ```StringLiteral``` is a promise that you are passing a string
|
|
||||||
literal into the constructor.
|
|
||||||
This means you can treat it like a store, that can be safely used as a copy of
|
|
||||||
the data.
|
|
||||||
Functions that take ```StringLiteral```s are allowed to assume that the data
|
|
||||||
will have no lifetime concerns and hold onto it without any need to make a
|
|
||||||
copy.
|
|
||||||
It has a consteval constructor to enforce the promise that it is a compile time
|
|
||||||
string.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void f(ox::StringLiteral const&);
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
f("123456789"); // valid
|
|
||||||
f(ox::String{"123456789"}.c_str()); // invalid - will not compile
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Other Variants
|
|
||||||
|
|
||||||
There are a few convenience aliases as well.
|
|
||||||
|
|
||||||
* StringCR = String const&
|
|
||||||
* StringViewCR = StringView const&
|
|
||||||
* CStringViewCR = CStringView const&
|
|
||||||
* CString = const char*
|
|
||||||
|
|
||||||
String views do not generally need const references, but it does make debugging
|
|
||||||
easier, as we can skip the constructor call if a string view already exists.
|
|
||||||
|
|
||||||
These kind of aliases probably should not exist for most types, but strings are
|
|
||||||
fundamental and ease of use is desirable.
|
|
||||||
|
|
||||||
### Logging and Output
|
### Logging and Output
|
||||||
|
|
||||||
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.
|
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.
|
||||||
|
|||||||
2
deps/ox/src/ox/clargs/clargs.cpp
vendored
2
deps/ox/src/ox/clargs/clargs.cpp
vendored
@@ -40,7 +40,7 @@ ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
|
bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
|
||||||
auto const [value, err] = m_ints.at(arg);
|
auto const [value, err] = m_bools.at(arg);
|
||||||
return !err ? *value : defaultValue;
|
return !err ? *value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
deps/ox/src/ox/std/strconv.hpp
vendored
6
deps/ox/src/ox/std/strconv.hpp
vendored
@@ -25,7 +25,7 @@ constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
|||||||
auto it = 0;
|
auto it = 0;
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
OX_RETURN_ERROR(writer.put('-'));
|
OX_RETURN_ERROR(writer.put('-'));
|
||||||
val = ~val + 1;
|
++it;
|
||||||
}
|
}
|
||||||
while (mod) {
|
while (mod) {
|
||||||
auto digit = val / mod;
|
auto digit = val / mod;
|
||||||
@@ -33,9 +33,9 @@ constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
|||||||
mod /= base;
|
mod /= base;
|
||||||
if (it || digit) {
|
if (it || digit) {
|
||||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||||
if (digit >= 10) [[unlikely]] {
|
if (digit >= 10) {
|
||||||
|
start = 'a';
|
||||||
digit -= 10;
|
digit -= 10;
|
||||||
OX_RETURN_ERROR(writer.put('1'));
|
|
||||||
}
|
}
|
||||||
OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
|
OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
|
||||||
++it;
|
++it;
|
||||||
|
|||||||
6
deps/ox/src/ox/std/stringliteral.hpp
vendored
6
deps/ox/src/ox/std/stringliteral.hpp
vendored
@@ -23,12 +23,12 @@ class StringLiteral: public detail::BaseStringView {
|
|||||||
|
|
||||||
constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
|
constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
|
||||||
|
|
||||||
consteval StringLiteral(std::nullptr_t) noexcept {}
|
consteval explicit StringLiteral(std::nullptr_t) noexcept {}
|
||||||
|
|
||||||
consteval StringLiteral(char const *str, std::size_t const len) noexcept: BaseStringView{str, len} {}
|
consteval explicit StringLiteral(char const *str, std::size_t const len) noexcept: BaseStringView{str, len} {}
|
||||||
|
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||||
consteval StringLiteral(char const *str) noexcept: StringLiteral{str, ox::strlen(str)} {}
|
consteval explicit StringLiteral(char const *str) noexcept: StringLiteral{str, ox::strlen(str)} {}
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||||
|
|
||||||
constexpr StringLiteral &operator=(StringLiteral const &other) noexcept {
|
constexpr StringLiteral &operator=(StringLiteral const &other) noexcept {
|
||||||
|
|||||||
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@@ -28,4 +28,3 @@ add_test("[ox/std] FromHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "FromHex")
|
|||||||
add_test("[ox/std] ToHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ToHex")
|
add_test("[ox/std] ToHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ToHex")
|
||||||
add_test("[ox/std] UUID" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID")
|
add_test("[ox/std] UUID" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID")
|
||||||
add_test("[ox/std] UUID::generate" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID::generate")
|
add_test("[ox/std] UUID::generate" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID::generate")
|
||||||
add_test("[ox/std] intToStr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "intToStr")
|
|
||||||
|
|||||||
27
deps/ox/src/ox/std/test/tests.cpp
vendored
27
deps/ox/src/ox/std/test/tests.cpp
vendored
@@ -536,33 +536,6 @@ OX_CLANG_NOWARN_END
|
|||||||
return ox::Error(0);
|
return ox::Error(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"intToStr",
|
|
||||||
[] {
|
|
||||||
oxExpect(ox::intToStr(static_cast<int8_t>(127)), "127");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int8_t>(-128)), "-128");
|
|
||||||
oxExpect(ox::intToStr(static_cast<uint8_t>(255)), "255");
|
|
||||||
oxExpect(ox::intToStr(static_cast<uint16_t>(65535)), "65535");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int16_t>(32767)), "32767");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int16_t>(-32768)), "-32768");
|
|
||||||
oxExpect(ox::intToStr(static_cast<uint32_t>(4294967295)), "4294967295");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int32_t>(2147483647)), "2147483647");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int32_t>(-2147483648)), "-2147483648");
|
|
||||||
oxExpect(ox::intToStr(static_cast<uint64_t>(18446744073709551615u)), "18446744073709551615");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int64_t>(9223372036854775807)), "9223372036854775807");
|
|
||||||
oxExpect(ox::intToStr(static_cast<int64_t>(-9223372036854775807)), "-9223372036854775807");
|
|
||||||
oxExpect(ox::intToStr(0), "0");
|
|
||||||
oxExpect(ox::intToStr(5), "5");
|
|
||||||
oxExpect(ox::intToStr(5000), "5000");
|
|
||||||
oxExpect(ox::intToStr(50000), "50000");
|
|
||||||
oxExpect(ox::intToStr(500000), "500000");
|
|
||||||
oxExpect(ox::intToStr(-5), "-5");
|
|
||||||
oxExpect(ox::intToStr(-5000), "-5000");
|
|
||||||
oxExpect(ox::intToStr(-50000), "-50000");
|
|
||||||
oxExpect(ox::intToStr(-500000), "-500000");
|
|
||||||
return ox::Error{};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char **argv) {
|
int main(int argc, const char **argv) {
|
||||||
|
|||||||
8
deps/ox/src/ox/std/vector.hpp
vendored
8
deps/ox/src/ox/std/vector.hpp
vendored
@@ -247,8 +247,6 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
|||||||
|
|
||||||
constexpr void resize(std::size_t size) noexcept(useNoexcept);
|
constexpr void resize(std::size_t size) noexcept(useNoexcept);
|
||||||
|
|
||||||
constexpr void reserveResize(std::size_t size) noexcept(useNoexcept);
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr T *data() noexcept {
|
constexpr T *data() noexcept {
|
||||||
return m_items;
|
return m_items;
|
||||||
@@ -519,12 +517,6 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) n
|
|||||||
m_size = size;
|
m_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
|
||||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveResize(std::size_t const size) noexcept(useNoexcept) {
|
|
||||||
reserve(size);
|
|
||||||
resize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const&v) const noexcept {
|
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const&v) const noexcept {
|
||||||
for (std::size_t i = 0; i < m_size; ++i) {
|
for (std::size_t i = 0; i < m_size; ++i) {
|
||||||
|
|||||||
20
deps/teagba/include/teagba/addresses.hpp
vendored
20
deps/teagba/include/teagba/addresses.hpp
vendored
@@ -99,23 +99,23 @@ volatile OffsetPair ®BgOfs(auto const bgIdx) noexcept {
|
|||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
// Memory Addresses
|
// Memory Addresses
|
||||||
|
|
||||||
#define MEM_EWRAM (*(reinterpret_cast<ox::Array<uint16_t, 0x0203'FFFF - 0x0200'0000>*>(0x0200'0000)))
|
#define MEM_EWRAM (*reinterpret_cast<ox::Array<uint16_t, 0x0203'FFFF - 0x0200'0000>*>(0x0200'0000))
|
||||||
|
|
||||||
#define MEM_IWRAM (*(reinterpret_cast<ox::Array<uint8_t, 0x0300'7FFF - 0x0300'0000>*>(0x0300'0000)))
|
#define MEM_IWRAM (*reinterpret_cast<ox::Array<uint8_t, 0x0300'7FFF - 0x0300'0000>*>(0x0300'0000))
|
||||||
|
|
||||||
#define REG_BLNDCTL (*reinterpret_cast<uint16_t*>(0x0400'0050))
|
#define REG_BLNDCTL (*reinterpret_cast<uint16_t*>(0x0400'0050))
|
||||||
|
|
||||||
using Palette = ox::Array<uint16_t, 128>;
|
using Palette = ox::Array<uint16_t, 128>;
|
||||||
#define MEM_BG_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0000)))
|
#define MEM_BG_PALETTE (*reinterpret_cast<::Palette*>(0x0500'0000))
|
||||||
#define MEM_SPRITE_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0200)))
|
#define MEM_SPRITE_PALETTE (*reinterpret_cast<::Palette*>(0x0500'0200))
|
||||||
|
|
||||||
using BgMapTile = ox::Array<uint16_t, 8192>;
|
using BgMapTile = ox::Array<uint16_t, 8192>;
|
||||||
#define MEM_BG_TILES (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'0000)))
|
#define MEM_BG_TILES (*reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'0000))
|
||||||
#define MEM_BG_MAP (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'e000)))
|
#define MEM_BG_MAP (*reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'e000))
|
||||||
|
|
||||||
#define MEM_SPRITE_TILES (*(reinterpret_cast<ox::Array<uint16_t, 32 * ox::units::KB>*>(0x0601'0000)))
|
#define MEM_SPRITE_TILES (*reinterpret_cast<ox::Array<uint16_t, 32 * ox::units::KB>*>(0x0601'0000))
|
||||||
#define MEM_OAM (*(reinterpret_cast<ox::Array<uint64_t, 64>*>(0x0700'0000)))
|
#define MEM_OAM (*reinterpret_cast<ox::Array<uint64_t, 64>*>(0x0700'0000))
|
||||||
|
|
||||||
#define MEM_ROM (*(reinterpret_cast<ox::Array<char, 32 * ox::units::MB>*>(0x0700'0000)))
|
#define MEM_ROM (*reinterpret_cast<ox::Array<char, 32 * ox::units::MB>*>(0x0700'0000))
|
||||||
|
|
||||||
#define MEM_SRAM (*(reinterpret_cast<ox::Array<char, 64 * ox::units::KB>*>(0x0e00'0000)))
|
#define MEM_SRAM (*reinterpret_cast<ox::Array<char, 64 * ox::units::KB>*>(0x0e00'0000))
|
||||||
|
|||||||
2
deps/teagba/include/teagba/gfx.hpp
vendored
2
deps/teagba/include/teagba/gfx.hpp
vendored
@@ -43,4 +43,6 @@ void applySpriteUpdates() noexcept;
|
|||||||
|
|
||||||
void setBgOffset(uint16_t bg, int16_t x, int16_t y) noexcept;
|
void setBgOffset(uint16_t bg, int16_t x, int16_t y) noexcept;
|
||||||
|
|
||||||
|
void scrollBgOffset(uint16_t bg, int16_t x, int16_t y) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
8
deps/teagba/src/gfx.cpp
vendored
8
deps/teagba/src/gfx.cpp
vendored
@@ -18,7 +18,7 @@ GbaSpriteAttrUpdate &spriteAttr(size_t const i) noexcept {
|
|||||||
|
|
||||||
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept {
|
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept {
|
||||||
const auto ie = REG_IE; // disable vblank interrupt handler
|
const auto ie = REG_IE; // disable vblank interrupt handler
|
||||||
REG_IE = REG_IE & static_cast<uint16_t>(~Int_vblank); // disable vblank interrupt handler
|
REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler
|
||||||
g_spriteBuffer[upd.idx] = upd;
|
g_spriteBuffer[upd.idx] = upd;
|
||||||
REG_IE = ie; // enable vblank interrupt handler
|
REG_IE = ie; // enable vblank interrupt handler
|
||||||
}
|
}
|
||||||
@@ -35,4 +35,10 @@ void setBgOffset(uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
|||||||
o.y = y;
|
o.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrollBgOffset(uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
||||||
|
auto &o = regBgOfs(bg);
|
||||||
|
o.x = o.x + x;
|
||||||
|
o.y = o.y + y;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ All components have a platform indicator next to them:
|
|||||||
* opengl - OpenGL implementation (P-)
|
* opengl - OpenGL implementation (P-)
|
||||||
* studio - studio plugin for core (P-)
|
* studio - studio plugin for core (P-)
|
||||||
* keel - keel plugin for core (PG)
|
* keel - keel plugin for core (PG)
|
||||||
* sound - sound system for Nostalgia (PG)
|
* scene - defines & processes map data (PG)
|
||||||
* studio - studio plugin for sound (P-)
|
* studio - studio plugin for scene (P-)
|
||||||
* keel - keel plugin for sound (PG)
|
* keel - keel plugin for scene (PG)
|
||||||
* player - plays the games (PG)
|
* player - plays the games (PG)
|
||||||
* studio - makes the games (P-)
|
* studio - makes the games (P-)
|
||||||
* tools - command line tools (P-)
|
* tools - command line tools (P-)
|
||||||
@@ -89,8 +89,7 @@ The GBA has two major resources for learning about its hardware:
|
|||||||
|
|
||||||
On the surface, it seems like C++ changes the way we do things from C for no
|
On the surface, it seems like C++ changes the way we do things from C for no
|
||||||
reason, but there are reasons for many of these duplications of functionality.
|
reason, but there are reasons for many of these duplications of functionality.
|
||||||
The C++ language designers aren't stupid.
|
The C++ language designers aren't stupid. Question them, but don't ignore them.
|
||||||
Question them, but don't ignore them.
|
|
||||||
|
|
||||||
#### Casting
|
#### Casting
|
||||||
|
|
||||||
@@ -164,11 +163,10 @@ The Ox way of doing things is the Olympic way of doing things.
|
|||||||
### Error Handling
|
### Error Handling
|
||||||
|
|
||||||
Instead of throwing exceptions, generally try to use
|
Instead of throwing exceptions, generally try to use
|
||||||
[ox::Error](deps/ox/ox-docs.md#error-handling) for error reporting.
|
[ox::Errors](deps/ox/ox-docs.md#error-handling) for error reporting,
|
||||||
Exceptions may be used where errors-as-values will not work, but catch them and
|
but exceptions may be used where they make sense.
|
||||||
convert them to ```ox::Error``` as soon as possible.
|
|
||||||
|
|
||||||
Exceptions should generally just use ```ox::Exception```, which is basically an
|
Exceptions should generally just use ```OxException```, which is bascially an
|
||||||
exception form of ```ox::Error```.
|
exception form of ```ox::Error```.
|
||||||
|
|
||||||
### File I/O
|
### File I/O
|
||||||
|
|||||||
@@ -23,15 +23,17 @@ struct BgCbbData {
|
|||||||
unsigned bpp = 4;
|
unsigned bpp = 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Context final {
|
class Context {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
turbine::Context &turbineCtx;
|
turbine::Context &turbineCtx;
|
||||||
ox::Array<BgCbbData, 4> cbbData;
|
ox::Array<BgCbbData, 4> cbbData;
|
||||||
ox::Array<OffsetPair, 4> bgOffsets;
|
|
||||||
|
|
||||||
explicit Context(turbine::Context &tctx) noexcept: turbineCtx{tctx} {}
|
explicit Context(turbine::Context &tctx) noexcept: turbineCtx{tctx} {}
|
||||||
|
Context(Context &other) noexcept = delete;
|
||||||
Context(Context const &other) noexcept = delete;
|
Context(Context const &other) noexcept = delete;
|
||||||
|
Context(Context const &&other) noexcept = delete;
|
||||||
|
virtual ~Context() noexcept = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -293,16 +295,12 @@ void setBgPriority(Context&, uint_t const bgIdx, uint_t const priority) noexcept
|
|||||||
bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11);
|
bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBgOffset(Context &ctx, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
void setBgOffset(Context&, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
||||||
ctx.bgOffsets[bg] = {.x = x, .y = y};
|
|
||||||
teagba::setBgOffset(bg, x, y);
|
teagba::setBgOffset(bg, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrollBgOffset(Context &ctx, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
void scrollBgOffset(Context&, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
|
||||||
auto &o = ctx.bgOffsets[bg];
|
teagba::scrollBgOffset(bg, x, y);
|
||||||
o.x += x;
|
|
||||||
o.y += y;
|
|
||||||
teagba::setBgOffset(bg, o.x, o.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hideSprite(Context&, unsigned const idx) noexcept {
|
void hideSprite(Context&, unsigned const idx) noexcept {
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ class Context {
|
|||||||
blocksPerSprite{params.glBlocksPerSprite} {
|
blocksPerSprite{params.glBlocksPerSprite} {
|
||||||
}
|
}
|
||||||
Context(Context const&) = delete;
|
Context(Context const&) = delete;
|
||||||
|
Context(Context&&) = delete;
|
||||||
Context &operator=(Context const&) = delete;
|
Context &operator=(Context const&) = delete;
|
||||||
|
Context &operator=(Context&&) = delete;
|
||||||
~Context() noexcept {
|
~Context() noexcept {
|
||||||
turbine::gl::removeDrawer(turbineCtx, &drawer);
|
turbine::gl::removeDrawer(turbineCtx, &drawer);
|
||||||
}
|
}
|
||||||
@@ -111,7 +113,7 @@ namespace renderer {
|
|||||||
static constexpr auto Scale = 1;
|
static constexpr auto Scale = 1;
|
||||||
static constexpr auto PriorityScale = 0.01f;
|
static constexpr auto PriorityScale = 0.01f;
|
||||||
|
|
||||||
static constexpr ox::StringLiteral bgvshadTmpl{R"glsl(
|
static constexpr ox::CStringView bgvshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
in vec3 vPosition;
|
in vec3 vPosition;
|
||||||
@@ -133,9 +135,9 @@ static constexpr ox::StringLiteral bgvshadTmpl{R"glsl(
|
|||||||
vTexCoord.x,
|
vTexCoord.x,
|
||||||
vTexCoord.y * vTileHeight + vTileIdx * vTileHeight);
|
vTexCoord.y * vTileHeight + vTileIdx * vTileHeight);
|
||||||
fPalOffset = vPalOffset;
|
fPalOffset = vPalOffset;
|
||||||
})glsl"};
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::StringLiteral bgfshadTmpl{R"glsl(
|
static constexpr ox::CStringView bgfshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
in float fPalOffset;
|
in float fPalOffset;
|
||||||
@@ -149,9 +151,9 @@ static constexpr ox::StringLiteral bgfshadTmpl{R"glsl(
|
|||||||
if (outColor.a == 0) {
|
if (outColor.a == 0) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
})glsl"};
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::StringLiteral spritevshadTmpl{R"glsl(
|
static constexpr ox::CStringView spritevshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
in float vEnabled;
|
in float vEnabled;
|
||||||
in vec3 vPosition;
|
in vec3 vPosition;
|
||||||
@@ -168,9 +170,9 @@ static constexpr ox::StringLiteral spritevshadTmpl{R"glsl(
|
|||||||
vPosition.z - 0.004,
|
vPosition.z - 0.004,
|
||||||
1.0) * vEnabled;
|
1.0) * vEnabled;
|
||||||
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
||||||
})glsl"};
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::StringLiteral spritefshadTmpl{R"glsl(
|
static constexpr ox::CStringView spritefshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
in vec2 fTexCoord;
|
in vec2 fTexCoord;
|
||||||
@@ -183,7 +185,7 @@ static constexpr ox::StringLiteral spritefshadTmpl{R"glsl(
|
|||||||
if (outColor.a == 0) {
|
if (outColor.a == 0) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
})glsl"};
|
})glsl";
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static constexpr auto bgVertexRow(uint_t const x, uint_t const y) noexcept {
|
static constexpr auto bgVertexRow(uint_t const x, uint_t const y) noexcept {
|
||||||
@@ -839,12 +841,6 @@ void setBgPriority(Context &ctx, uint_t const bgIdx, uint_t const priority) noex
|
|||||||
bg.priority = static_cast<float>(priority & 0b11);
|
bg.priority = static_cast<float>(priority & 0b11);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBgOffset(Context&, uint16_t const, int16_t const, int16_t const) noexcept {
|
|
||||||
}
|
|
||||||
|
|
||||||
void scrollBgOffset(Context&, uint16_t const, int16_t const, int16_t const) noexcept {
|
|
||||||
}
|
|
||||||
|
|
||||||
void hideSprite(Context &ctx, uint_t const idx) noexcept {
|
void hideSprite(Context &ctx, uint_t const idx) noexcept {
|
||||||
auto &s = ctx.spriteStates[idx];
|
auto &s = ctx.spriteStates[idx];
|
||||||
s.enabled = false;
|
s.enabled = false;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void TileSheetGrid::update(ox::Vec2 const &paneSize, TileSheet::SubSheet const &
|
|||||||
glBindVertexArray(m_bufferSet.vao);
|
glBindVertexArray(m_bufferSet.vao);
|
||||||
setBufferObjects(paneSize, subsheet);
|
setBufferObjects(paneSize, subsheet);
|
||||||
glutils::sendVbo(m_bufferSet);
|
glutils::sendVbo(m_bufferSet);
|
||||||
//glutils::sendEbo(m_bufferSet);
|
glutils::sendEbo(m_bufferSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetGrid::setBufferObject(
|
void TileSheetGrid::setBufferObject(
|
||||||
@@ -89,6 +89,7 @@ void TileSheetGrid::setBufferObject(
|
|||||||
|
|
||||||
void TileSheetGrid::setBufferObjects(ox::Vec2 const &paneSize, TileSheet::SubSheet const &subsheet) noexcept {
|
void TileSheetGrid::setBufferObjects(ox::Vec2 const &paneSize, TileSheet::SubSheet const &subsheet) noexcept {
|
||||||
if (subsheet.columns < 1 || subsheet.rows < 1) {
|
if (subsheet.columns < 1 || subsheet.rows < 1) {
|
||||||
|
m_bufferSet.elements.clear();
|
||||||
m_bufferSet.vertices.clear();
|
m_bufferSet.vertices.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,11 +285,11 @@ static void handleKeyPress(Context &ctx, int const key, bool const down) noexcep
|
|||||||
map[GLFW_KEY_ESCAPE] = Key::Escape;
|
map[GLFW_KEY_ESCAPE] = Key::Escape;
|
||||||
return map;
|
return map;
|
||||||
}();
|
}();
|
||||||
|
auto const eventHandler = keyEventHandler(ctx);
|
||||||
auto const keyIdx = static_cast<std::size_t>(key);
|
auto const keyIdx = static_cast<std::size_t>(key);
|
||||||
if (keyIdx < keyMap.size()) {
|
if (keyIdx < keyMap.size()) {
|
||||||
auto const k = keyMap[keyIdx];
|
auto const k = keyMap[keyIdx];
|
||||||
setKeyDownStatus(ctx, k, down);
|
setKeyDownStatus(ctx, k, down);
|
||||||
auto const eventHandler = keyEventHandler(ctx);
|
|
||||||
if (eventHandler) {
|
if (eventHandler) {
|
||||||
eventHandler(ctx, k, down);
|
eventHandler(ctx, k, down);
|
||||||
}
|
}
|
||||||
@@ -306,10 +306,8 @@ static void handleGlfwMouseButtonEvent(
|
|||||||
int) noexcept {
|
int) noexcept {
|
||||||
auto &ctx = *static_cast<Context*>(glfwGetWindowUserPointer(window));
|
auto &ctx = *static_cast<Context*>(glfwGetWindowUserPointer(window));
|
||||||
setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod);
|
setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod);
|
||||||
if (ctx.mouseButtonEventHandler) {
|
|
||||||
ctx.mouseButtonEventHandler(ctx, btn, action == 1);
|
ctx.mouseButtonEventHandler(ctx, btn, action == 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const action, int) noexcept {
|
static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const action, int) noexcept {
|
||||||
auto &ctx = *static_cast<Context*>(glfwGetWindowUserPointer(window));
|
auto &ctx = *static_cast<Context*>(glfwGetWindowUserPointer(window));
|
||||||
|
|||||||
Reference in New Issue
Block a user