Compare commits
No commits in common. "92d85d1145c065164a0cdea37d5693a2730fb6ca" and "5f10edd35fbc3ab4964619e299d5d555ace35a31" have entirely different histories.
92d85d1145
...
5f10edd35f
1
.gitignore
vendored
1
.gitignore
vendored
@ -20,4 +20,3 @@ imgui.ini
|
|||||||
*.sav
|
*.sav
|
||||||
studio_state.json
|
studio_state.json
|
||||||
tags
|
tags
|
||||||
*-manifest.json
|
|
||||||
|
@ -28,7 +28,7 @@ set(CMAKE_CXX_STANDARD 23)
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_MACOSX_RPATH OFF)
|
set(CMAKE_MACOSX_RPATH OFF)
|
||||||
else()
|
else()
|
||||||
if(UNIX AND NOT DEFINED BUILD_SHARED_LIBS)
|
if(UNIX)
|
||||||
set(BUILD_SHARED_LIBS ON)
|
set(BUILD_SHARED_LIBS ON)
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
||||||
|
7
deps/buildcore/base.mk
vendored
7
deps/buildcore/base.mk
vendored
@ -44,9 +44,6 @@ ifdef BC_VAR_USE_DOCKER_DEVENV
|
|||||||
exit 1
|
exit 1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifndef BC_VAR_DEVENV_ROOT
|
|
||||||
BC_VAR_DEVENV_ROOT="."
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
BC_CMD_PY3=${BC_CMD_HOST_PY3}
|
BC_CMD_PY3=${BC_CMD_HOST_PY3}
|
||||||
endif
|
endif
|
||||||
@ -93,7 +90,7 @@ purge:
|
|||||||
${BC_CMD_RM_RF} compile_commands.json
|
${BC_CMD_RM_RF} compile_commands.json
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: build
|
test: build
|
||||||
${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS}
|
${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
|
||||||
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
|
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
|
||||||
.PHONY: test-verbose
|
.PHONY: test-verbose
|
||||||
test-verbose: build
|
test-verbose: build
|
||||||
@ -105,7 +102,7 @@ test-rerun-verbose: build
|
|||||||
ifdef BC_VAR_USE_DOCKER_DEVENV
|
ifdef BC_VAR_USE_DOCKER_DEVENV
|
||||||
.PHONY: devenv-image
|
.PHONY: devenv-image
|
||||||
devenv-image:
|
devenv-image:
|
||||||
docker build ${BC_VAR_DEVENV_ROOT} -t ${BC_VAR_DEVENV_IMAGE}
|
docker build . -t ${BC_VAR_DEVENV_IMAGE}
|
||||||
.PHONY: devenv-create
|
.PHONY: devenv-create
|
||||||
devenv-create:
|
devenv-create:
|
||||||
docker run -d \
|
docker run -d \
|
||||||
|
@ -315,7 +315,7 @@ Error FileStoreTemplate<size_t>::remove(uint64_t id) {
|
|||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
|
Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize, FsSize_t *size) const {
|
||||||
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read inode {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read", "Attempting to read from inode {}", id);
|
||||||
auto src = find(static_cast<size_t>(id));
|
auto src = find(static_cast<size_t>(id));
|
||||||
// error check
|
// error check
|
||||||
if (!src.valid()) {
|
if (!src.valid()) {
|
||||||
@ -333,7 +333,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
|
|||||||
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
|
oxTracef("ox.fs.FileStoreTemplate.read.fail", "Could not read data section of item: {}", id);
|
||||||
oxTracef("ox.fs.FileStoreTemplate.read.fail",
|
oxTracef("ox.fs.FileStoreTemplate.read.fail",
|
||||||
"Item data section size: {}, Expected size: {}", srcData.size(), outSize);
|
"Item data section size: {}, Expected size: {}", srcData.size(), outSize);
|
||||||
return OxError(1, "Invalid inode");
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::memcpy(out, srcData, srcData.size());
|
ox::memcpy(out, srcData, srcData.size());
|
||||||
@ -341,7 +341,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
|
|||||||
*size = src.size();
|
*size = src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
|
117
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
117
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
@ -43,15 +43,13 @@ struct OX_PACKED DirectoryEntry {
|
|||||||
public:
|
public:
|
||||||
constexpr DirectoryEntry() noexcept = default;
|
constexpr DirectoryEntry() noexcept = default;
|
||||||
|
|
||||||
Error init(InodeId_t inode, ox::CRStringView name, size_t bufferSize) noexcept {
|
Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) noexcept {
|
||||||
oxTracef("ox.fs.DirectoryEntry.init", "inode: {}, name: {}, bufferSize: {}", inode, name, bufferSize);
|
m_bufferSize = bufferSize;
|
||||||
m_bufferSize = static_cast<InodeId_t>(bufferSize);
|
|
||||||
auto d = data();
|
auto d = data();
|
||||||
if (d.valid()) {
|
if (d.valid()) {
|
||||||
d->inode = inode;
|
d->inode = inode;
|
||||||
auto const maxStrSz = bufferSize - 1 - sizeof(*this);
|
ox::strncpy(d->name, name, ox::min(bufferSize, static_cast<InodeId_t>(MaxFileNameLength)));
|
||||||
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
|
return OxError(0);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
@ -105,23 +103,23 @@ class Directory {
|
|||||||
*/
|
*/
|
||||||
Error init() noexcept;
|
Error init() noexcept;
|
||||||
|
|
||||||
Error mkdir(PathIterator path, bool parents);
|
Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parents indicates the operation should create non-existent directories in the path, like mkdir -p
|
* @param parents indicates the operation should create non-existent directories in the path, like mkdir -p
|
||||||
*/
|
*/
|
||||||
Error write(PathIterator path, uint64_t inode64) noexcept;
|
Error write(PathIterator path, uint64_t inode64, FileName *nameBuff = nullptr) noexcept;
|
||||||
|
|
||||||
Error remove(PathIterator path) noexcept;
|
Error remove(PathIterator path, FileName *nameBuff = nullptr) noexcept;
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
Error ls(F cb) noexcept;
|
Error ls(F cb) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Result<typename FileStore::InodeId_t> findEntry(const StringView &name) const noexcept;
|
Result<typename FileStore::InodeId_t> findEntry(const FileName &name) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Result<typename FileStore::InodeId_t> find(PathIterator path) const noexcept;
|
Result<typename FileStore::InodeId_t> find(PathIterator name, FileName *nameBuff = nullptr) const noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,17 +145,22 @@ Error Directory<FileStore, InodeId_t>::init() noexcept {
|
|||||||
}
|
}
|
||||||
new (buff) Buffer(Size);
|
new (buff) Buffer(Size);
|
||||||
m_size = Size;
|
m_size = Size;
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
|
Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents, FileName *nameBuff) {
|
||||||
if (path.valid()) {
|
if (path.valid()) {
|
||||||
oxTrace("ox.fs.Directory.mkdir", path.fullPath());
|
oxTrace("ox.fs.Directory.mkdir", path.fullPath());
|
||||||
|
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
||||||
|
if (nameBuff == nullptr) {
|
||||||
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
|
}
|
||||||
|
|
||||||
// determine if already exists
|
// determine if already exists
|
||||||
ox::StringView name;
|
auto name = nameBuff;
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(*name));
|
||||||
auto childInode = find(PathIterator(name));
|
auto childInode = find(PathIterator(*name));
|
||||||
if (!childInode.ok()) {
|
if (!childInode.ok()) {
|
||||||
// if this is not the last item in the path and parents is disabled,
|
// if this is not the last item in the path and parents is disabled,
|
||||||
// return an error
|
// return an error
|
||||||
@ -168,10 +171,12 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
|
|||||||
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
|
oxTracef("ox.fs.Directory.mkdir", "Generated Inode ID: {}", childInode.value);
|
||||||
oxLogError(childInode.error);
|
oxLogError(childInode.error);
|
||||||
oxReturnError(childInode.error);
|
oxReturnError(childInode.error);
|
||||||
|
|
||||||
// initialize the directory
|
// initialize the directory
|
||||||
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
|
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
|
||||||
oxReturnError(child.init());
|
oxReturnError(child.init());
|
||||||
auto err = write(PathIterator(name), childInode.value);
|
|
||||||
|
auto err = write(PathIterator(*name), childInode.value);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxLogError(err);
|
oxLogError(err);
|
||||||
// could not index the directory, delete it
|
// could not index the directory, delete it
|
||||||
@ -179,35 +184,46 @@ Error Directory<FileStore, InodeId_t>::mkdir(PathIterator path, bool parents) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
|
Directory<FileStore, InodeId_t> child(m_fs, childInode.value);
|
||||||
if (path.hasNext()) {
|
if (path.hasNext()) {
|
||||||
oxReturnError(child.mkdir(path.next(), parents));
|
oxReturnError(child.mkdir(path.next(), parents, nameBuff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64) noexcept {
|
Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64, FileName *nameBuff) noexcept {
|
||||||
const auto inode = static_cast<InodeId_t>(inode64);
|
const auto inode = static_cast<InodeId_t>(inode64);
|
||||||
ox::StringView name;
|
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
||||||
|
if (nameBuff == nullptr) {
|
||||||
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
|
}
|
||||||
|
auto name = nameBuff;
|
||||||
|
|
||||||
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
|
if (path.next().hasNext()) { // not yet at target directory, recurse to next one
|
||||||
|
oxReturnError(path.get(*name));
|
||||||
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
|
oxTracef("ox.fs.Directory.write", "Attempting to write to next sub-Directory: {} of {}",
|
||||||
name, path.fullPath());
|
*name, path.fullPath());
|
||||||
oxReturnError(path.get(name));
|
oxRequire(nextChild, findEntry(*name));
|
||||||
oxRequire(nextChild, findEntry(name));
|
oxTracef("ox.fs.Directory.write", "{}: {}", *name, nextChild);
|
||||||
oxTracef("ox.fs.Directory.write", "{}: {}", name, nextChild);
|
|
||||||
if (nextChild) {
|
if (nextChild) {
|
||||||
return Directory(m_fs, nextChild).write(path.next(), inode);
|
// reuse name because it is a rather large variable and will not be used again
|
||||||
|
// be attentive that this remains true
|
||||||
|
name = nullptr;
|
||||||
|
return Directory(m_fs, nextChild).write(path.next(), inode, nameBuff);
|
||||||
} else {
|
} else {
|
||||||
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", name);
|
oxTracef("ox.fs.Directory.write", "{} not found and not allowed to create it.", *name);
|
||||||
return OxError(1, "File not found and not allowed to create it.");
|
return OxError(1, "File not found and not allowed to create it.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox.fs.Directory.write", path.fullPath());
|
oxTrace("ox.fs.Directory.write", path.fullPath());
|
||||||
oxReturnError(path.next(name));
|
|
||||||
// insert the new entry on this directory
|
// insert the new entry on this directory
|
||||||
|
|
||||||
// get the name
|
// get the name
|
||||||
|
oxReturnError(path.next(*name));
|
||||||
|
|
||||||
// find existing version of directory
|
// find existing version of directory
|
||||||
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
|
oxTracef("ox.fs.Directory.write", "Searching for directory inode {}", m_inodeId);
|
||||||
oxRequire(oldStat, m_fs.stat(m_inodeId));
|
oxRequire(oldStat, m_fs.stat(m_inodeId));
|
||||||
@ -217,7 +233,8 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
|
|||||||
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
|
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
|
||||||
return OxError(1, "Could not read existing version of Directory");
|
return OxError(1, "Could not read existing version of Directory");
|
||||||
}
|
}
|
||||||
const auto pathSize = name.len() + 1;
|
|
||||||
|
const auto pathSize = name->len() + 1;
|
||||||
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
|
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
|
||||||
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
|
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
|
||||||
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
|
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);
|
||||||
@ -225,22 +242,29 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
|
|||||||
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
|
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for copy of Directory");
|
||||||
return OxError(1, "Could not allocate memory for copy of Directory");
|
return OxError(1, "Could not allocate memory for copy of Directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
oxReturnError(cpy->setSize(newSize));
|
oxReturnError(cpy->setSize(newSize));
|
||||||
auto val = cpy->malloc(entryDataSize).value;
|
auto val = cpy->malloc(entryDataSize).value;
|
||||||
if (!val.valid()) {
|
if (!val.valid()) {
|
||||||
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
|
oxTrace("ox.fs.Directory.write.fail", "Could not allocate memory for new directory entry");
|
||||||
return OxError(1, "Could not allocate memory for new directory entry");
|
return OxError(1, "Could not allocate memory for new directory entry");
|
||||||
}
|
}
|
||||||
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name);
|
|
||||||
oxReturnError(val->init(inode, name, val.size()));
|
oxTracef("ox.fs.Directory.write", "Attempting to write Directory entry: {}", name->data());
|
||||||
|
oxReturnError(val->init(inode, name->data(), val.size()));
|
||||||
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
|
return m_fs.write(m_inodeId, cpy.get(), cpy->size(), static_cast<uint8_t>(FileType::Directory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
|
Error Directory<FileStore, InodeId_t>::remove(PathIterator path, FileName *nameBuff) noexcept {
|
||||||
ox::StringView name;
|
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
||||||
|
if (nameBuff == nullptr) {
|
||||||
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
|
}
|
||||||
|
auto &name = *nameBuff;
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(name));
|
||||||
|
|
||||||
oxTrace("ox.fs.Directory.remove", name);
|
oxTrace("ox.fs.Directory.remove", name);
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (buff.valid()) {
|
if (buff.valid()) {
|
||||||
@ -259,7 +283,7 @@ Error Directory<FileStore, InodeId_t>::remove(PathIterator path) noexcept {
|
|||||||
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
|
oxTrace("ox.fs.Directory.remove.fail", "Could not find directory buffer");
|
||||||
return OxError(1, "Could not find directory buffer");
|
return OxError(1, "Could not find directory buffer");
|
||||||
}
|
}
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
@ -271,6 +295,7 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
|
|||||||
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
|
oxTrace("ox.fs.Directory.ls.fail", "Could not directory buffer");
|
||||||
return OxError(1, "Could not directory buffer");
|
return OxError(1, "Could not directory buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
|
oxTrace("ox.fs.Directory.ls", "Found directory buffer.");
|
||||||
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
for (auto i = buff->iterator(); i.valid(); i.next()) {
|
||||||
auto data = i->data();
|
auto data = i->data();
|
||||||
@ -280,11 +305,12 @@ Error Directory<FileStore, InodeId_t>::ls(F cb) noexcept {
|
|||||||
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
|
oxTrace("ox.fs.Directory.ls", "INVALID DIRECTORY ENTRY");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(CRStringView name) const noexcept {
|
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry(const FileName &name) const noexcept {
|
||||||
oxTrace("ox.fs.Directory.findEntry", name);
|
oxTrace("ox.fs.Directory.findEntry", name);
|
||||||
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
auto buff = m_fs.read(m_inodeId).template to<Buffer>();
|
||||||
if (!buff.valid()) {
|
if (!buff.valid()) {
|
||||||
@ -301,7 +327,7 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
|
|||||||
return static_cast<InodeId_t>(data->inode);
|
return static_cast<InodeId_t>(data->inode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox.fs.Directory.findEntry", "INVALID DIRECTORY ENTRY");
|
oxTrace("ox.fs.Directory.findEntry") << "INVALID DIRECTORY ENTRY";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
|
oxTrace("ox.fs.Directory.findEntry.fail", "Entry not present");
|
||||||
@ -309,15 +335,22 @@ Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path) const noexcept {
|
Result<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(PathIterator path, FileName *nameBuff) const noexcept {
|
||||||
|
// reuse nameBuff if it has already been allocated, as it is a rather large variable
|
||||||
|
if (nameBuff == nullptr) {
|
||||||
|
nameBuff = new (ox_alloca(sizeof(FileName))) FileName;
|
||||||
|
}
|
||||||
|
|
||||||
// determine if already exists
|
// determine if already exists
|
||||||
ox::StringView name;
|
auto name = nameBuff;
|
||||||
oxReturnError(path.get(name));
|
oxReturnError(path.get(*name));
|
||||||
oxRequire(v, findEntry(name));
|
|
||||||
|
oxRequire(v, findEntry(*name));
|
||||||
// recurse if not at end of path
|
// recurse if not at end of path
|
||||||
if (auto p = path.next(); p.valid()) {
|
if (auto p = path.next(); p.valid()) {
|
||||||
Directory dir(m_fs, v);
|
Directory dir(m_fs, v);
|
||||||
return dir.find(p);
|
name = nullptr;
|
||||||
|
return dir.find(p, nameBuff);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
17
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
17
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -323,7 +323,6 @@ Error FileSystemTemplate<FileStore, Directory>::move(CRStringView src, CRStringV
|
|||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept {
|
Error FileSystemTemplate<FileStore, Directory>::readFilePath(CRStringView path, void *buffer, std::size_t buffSize) noexcept {
|
||||||
oxTrace("ox.fs.FileSystemTemplate.readFilePath", path);
|
|
||||||
oxRequire(fd, fileSystemData());
|
oxRequire(fd, fileSystemData());
|
||||||
Directory rootDir(m_fs, fd.rootDirInode);
|
Directory rootDir(m_fs, fd.rootDirInode);
|
||||||
oxRequire(s, stat(path));
|
oxRequire(s, stat(path));
|
||||||
@ -343,7 +342,6 @@ Result<const char*> FileSystemTemplate<FileStore, Directory>::directAccessPath(C
|
|||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
Error FileSystemTemplate<FileStore, Directory>::readFileInode(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
||||||
oxTracef("ox.fs.FileSystemTemplate.readFileInode", "{}", inode);
|
|
||||||
oxRequire(s, stat(inode));
|
oxRequire(s, stat(inode));
|
||||||
if (s.size > buffSize) {
|
if (s.size > buffSize) {
|
||||||
return OxError(1, "Buffer to small to load file");
|
return OxError(1, "Buffer to small to load file");
|
||||||
@ -411,29 +409,24 @@ Error FileSystemTemplate<FileStore, Directory>::resize() noexcept {
|
|||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
|
Error FileSystemTemplate<FileStore, Directory>::resize(uint64_t size, void *buffer) noexcept {
|
||||||
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer));
|
oxReturnError(m_fs.resize(static_cast<size_t>(size), buffer));
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::writeFilePath(
|
Error FileSystemTemplate<FileStore, Directory>::writeFilePath(CRStringView path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
CRStringView path,
|
|
||||||
const void *buffer,
|
|
||||||
uint64_t size,
|
|
||||||
FileType fileType) noexcept {
|
|
||||||
oxTrace("ox.fs.FileSystemTemplate.writeFilePath", path);
|
|
||||||
auto [inode, err] = find(path);
|
auto [inode, err] = find(path);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxReturnError(m_fs.generateInodeId().moveTo(inode));
|
oxRequire(generatedId, m_fs.generateInodeId());
|
||||||
|
inode = generatedId;
|
||||||
oxRequireM(rootDir, this->rootDir());
|
oxRequireM(rootDir, this->rootDir());
|
||||||
oxReturnError(rootDir.write(path, inode));
|
oxReturnError(rootDir.write(path, inode));
|
||||||
}
|
}
|
||||||
oxReturnError(writeFileInode(inode, buffer, size, fileType));
|
oxReturnError(writeFileInode(inode, buffer, size, fileType));
|
||||||
return {};
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
Error FileSystemTemplate<FileStore, Directory>::writeFileInode(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
oxTrace("ox.fs.FileSystemTemplate.writeFileInode", ox::itoa(inode));
|
|
||||||
return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType));
|
return m_fs.write(inode, buffer, static_cast<size_t>(size), static_cast<uint8_t>(fileType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ Result<FileStat> PassThroughFS::statPath(CRStringView path) const noexcept {
|
|||||||
FileType::Directory : FileType::NormalFile;
|
FileType::Directory : FileType::NormalFile;
|
||||||
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
|
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
|
||||||
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
|
const uint64_t size = type == FileType::Directory ? 0 : std::filesystem::file_size(p, ec);
|
||||||
|
oxTracef("ox.fs.PassThroughFS.statInode", "{} {}", ec.message(), path);
|
||||||
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
|
oxTracef("ox.fs.PassThroughFS.statInode.size", "{} {}", path, size);
|
||||||
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
|
oxReturnError(OxError(static_cast<ox::ErrorCode>(ec.value()), "PassThroughFS: stat failed"));
|
||||||
return FileStat{0, 0, size, type};
|
return FileStat{0, 0, size, type};
|
||||||
|
47
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
47
deps/ox/src/ox/fs/filesystem/pathiterator.cpp
vendored
@ -40,9 +40,30 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
|
Error PathIterator::fileName(char *out, std::size_t outSize) {
|
||||||
|
auto idx = ox::lastIndexOf(m_path, '/', m_maxSize);
|
||||||
|
if (idx >= 0) {
|
||||||
|
idx++; // pass up the preceding /
|
||||||
|
std::size_t fileNameSize = static_cast<size_t>(ox::strlen(&m_path[idx]));
|
||||||
|
if (fileNameSize < outSize) {
|
||||||
|
ox::memcpy(out, &m_path[idx], fileNameSize);
|
||||||
|
out[fileNameSize] = 0;
|
||||||
|
return OxError(0);
|
||||||
|
} else {
|
||||||
|
return OxError(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return OxError(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the get item in the path
|
// Gets the get item in the path
|
||||||
Error PathIterator::get(StringView &fileName) {
|
Error PathIterator::get(IString<MaxFileNameLength> &fileName) {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
|
std::ignore = fileName.resize(MaxFileNameLength);
|
||||||
if (m_iterator >= m_maxSize) {
|
if (m_iterator >= m_maxSize) {
|
||||||
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
|
oxTracef("ox.fs.PathIterator.get", "m_iterator ({}) >= m_maxSize ({})", m_iterator, m_maxSize);
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
@ -67,21 +88,22 @@ Error PathIterator::get(StringView &fileName) {
|
|||||||
if (size >= MaxFileNameLength || size == 0) {
|
if (size >= MaxFileNameLength || size == 0) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
fileName = ox::substr(m_path, start, start + size);
|
ox::memcpy(fileName.data(), &m_path[start], size);
|
||||||
// truncate trailing /
|
// truncate trailing /
|
||||||
if (size && fileName[size - 1] == '/') {
|
if (size && fileName[size - 1] == '/') {
|
||||||
fileName = ox::substr(m_path, start, start + size - 1);
|
size--;
|
||||||
}
|
}
|
||||||
oxAssert(fileName[fileName.len()-1] != '/', "name ends in /");
|
oxReturnError(fileName.resize(size));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 0 if no error
|
* @return 0 if no error
|
||||||
*/
|
*/
|
||||||
Error PathIterator::next(StringView &fileName) {
|
Error PathIterator::next(IString<MaxFileNameLength> &fileName) {
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
auto retval = OxError(1);
|
auto retval = OxError(1);
|
||||||
|
std::ignore = fileName.resize(MaxFileNameLength);
|
||||||
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
|
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
|
||||||
retval = OxError(0);
|
retval = OxError(0);
|
||||||
if (m_path[m_iterator] == '/') {
|
if (m_path[m_iterator] == '/') {
|
||||||
@ -100,14 +122,15 @@ Error PathIterator::next(StringView &fileName) {
|
|||||||
if (size >= MaxFileNameLength) {
|
if (size >= MaxFileNameLength) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
fileName = ox::substr(m_path, start, start + size);
|
ox::memcpy(fileName.data(), &m_path[start], size);
|
||||||
// truncate trailing /
|
|
||||||
while (fileName.len() && fileName[fileName.len() - 1] == '/') {
|
|
||||||
fileName = ox::substr(m_path, start, start + size);
|
|
||||||
}
|
|
||||||
m_iterator += size;
|
|
||||||
oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /");
|
|
||||||
}
|
}
|
||||||
|
// truncate trailing /
|
||||||
|
if (size && fileName[size - 1] == '/') {
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
fileName[size] = 0; // end with null terminator
|
||||||
|
oxReturnError(fileName.resize(size));
|
||||||
|
m_iterator += size;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
22
deps/ox/src/ox/fs/filesystem/pathiterator.hpp
vendored
@ -13,6 +13,7 @@
|
|||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
constexpr std::size_t MaxFileNameLength = 255;
|
constexpr std::size_t MaxFileNameLength = 255;
|
||||||
|
using FileName = IString<MaxFileNameLength>;
|
||||||
|
|
||||||
class PathIterator {
|
class PathIterator {
|
||||||
private:
|
private:
|
||||||
@ -27,12 +28,29 @@ class PathIterator {
|
|||||||
|
|
||||||
PathIterator(CRStringView path);
|
PathIterator(CRStringView path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
Error dirPath(char *pathOut, std::size_t pathOutSize);
|
Error dirPath(char *pathOut, std::size_t pathOutSize);
|
||||||
|
|
||||||
Error next(StringView &fileName);
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
|
Error fileName(char *out, std::size_t outSize);
|
||||||
|
|
||||||
Error get(StringView &fileName);
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
|
Error next(FileName &fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
|
Error get(FileName &fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 if no error
|
||||||
|
*/
|
||||||
Result<std::size_t> nextSize() const;
|
Result<std::size_t> nextSize() const;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
2
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
2
deps/ox/src/ox/fs/ptrarith/nodebuffer.hpp
vendored
@ -174,7 +174,7 @@ template<typename size_t, typename Item>
|
|||||||
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
|
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
|
||||||
m_header.size = static_cast<size_t>(size);
|
m_header.size = static_cast<size_t>(size);
|
||||||
ox::memset(this + 1, 0, size - sizeof(*this));
|
ox::memset(this + 1, 0, size - sizeof(*this));
|
||||||
oxTracef("ox.ptrarith.NodeBuffer.constructor", "{}", m_header.firstItem.get());
|
oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
|
4
deps/ox/src/ox/fs/ptrarith/ptr.hpp
vendored
4
deps/ox/src/ox/fs/ptrarith/ptr.hpp
vendored
@ -224,7 +224,7 @@ constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(s
|
|||||||
template<typename T, typename size_t, size_t minOffset>
|
template<typename T, typename size_t, size_t minOffset>
|
||||||
template<typename SubT>
|
template<typename SubT>
|
||||||
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
|
constexpr const Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) const noexcept {
|
||||||
oxTracef("ox.ptrarith.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
||||||
return subPtr<SubT>(offset, m_itemSize - offset);
|
return subPtr<SubT>(offset, m_itemSize - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t
|
|||||||
template<typename T, typename size_t, size_t minOffset>
|
template<typename T, typename size_t, size_t minOffset>
|
||||||
template<typename SubT>
|
template<typename SubT>
|
||||||
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
|
constexpr Ptr<SubT, size_t, sizeof(T)> Ptr<T, size_t, minOffset>::subPtr(size_t offset) noexcept {
|
||||||
oxTracef("ox.ptrarith.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
oxTracef("ox.fs.Ptr.subPtr", "{} {} {} {} {}", m_itemOffset, this->size(), offset, m_itemSize, (m_itemSize - offset));
|
||||||
return subPtr<SubT>(offset, m_itemSize - offset);
|
return subPtr<SubT>(offset, m_itemSize - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/fs/test/CMakeLists.txt
vendored
@ -19,6 +19,7 @@ add_test("[ox/fs] PathIterator::next5" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests
|
|||||||
add_test("[ox/fs] PathIterator::hasNext" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::hasNext)
|
add_test("[ox/fs] PathIterator::hasNext" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::hasNext)
|
||||||
|
|
||||||
add_test("[ox/fs] PathIterator::dirPath" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::dirPath)
|
add_test("[ox/fs] PathIterator::dirPath" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::dirPath)
|
||||||
|
add_test("[ox/fs] PathIterator::fileName" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests PathIterator::fileName)
|
||||||
|
|
||||||
add_test("[ox/fs] NodeBuffer::insert" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "NodeBuffer::insert")
|
add_test("[ox/fs] NodeBuffer::insert" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "NodeBuffer::insert")
|
||||||
add_test("[ox/fs] FileStore::readWrite" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileStore::readWrite")
|
add_test("[ox/fs] FileStore::readWrite" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FSTests "FileStore::readWrite")
|
||||||
|
52
deps/ox/src/ox/fs/test/tests.cpp
vendored
52
deps/ox/src/ox/fs/test/tests.cpp
vendored
@ -58,9 +58,9 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
{
|
{
|
||||||
"PathIterator::next1",
|
"PathIterator::next1",
|
||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
ox::StringView buff;
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
|
||||||
@ -70,13 +70,11 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
{
|
{
|
||||||
"PathIterator::next2",
|
"PathIterator::next2",
|
||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
auto constexpr path = ox::StringView("/usr/share/");
|
auto const path = ox::String("/usr/share/");
|
||||||
ox::PathIterator it(path);
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
ox::StringView buff;
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff), "PathIterator::next returned error");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxExpect(buff, "usr");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff), "PathIterator::next returned error");
|
|
||||||
oxExpect(buff, "share");
|
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -85,20 +83,20 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
auto const path = ox::String("/");
|
auto const path = ox::String("/");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
ox::StringView buff;
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::next4",
|
"PathIterator::next4",
|
||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
auto constexpr path = ox::StringLiteral("usr/share/charset.gbag");
|
auto const path = ox::String("usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path);
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
ox::StringView buff;
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff) == 0 && buff == "charset.gbag", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -107,22 +105,32 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
auto const path = ox::String("usr/share/");
|
auto const path = ox::String("usr/share/");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
ox::StringView buff;
|
ox::FileName buff;
|
||||||
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||||
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
|
oxAssert(it.next(buff) == 0 && ox::strcmp(buff, "share") == 0, "PathIterator shows wrong next");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::dirPath",
|
"PathIterator::dirPath",
|
||||||
[] (ox::StringView) {
|
[] (ox::StringView) {
|
||||||
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
ox::PathIterator it(path.c_str(), path.len());
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||||
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"PathIterator::fileName",
|
||||||
|
[](ox::StringView) {
|
||||||
|
auto const path = ox::String("/usr/share/charset.gbag");
|
||||||
|
ox::PathIterator it(path.c_str(), path.len());
|
||||||
|
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||||
|
oxAssert(it.fileName(buff, path.len()) == 0 && ox::strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
|
||||||
|
return OxError(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"PathIterator::hasNext",
|
"PathIterator::hasNext",
|
||||||
[](ox::StringView) {
|
[](ox::StringView) {
|
||||||
@ -213,6 +221,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
oxTrace("ox.fs.test.FileSystem") << "format";
|
oxTrace("ox.fs.test.FileSystem") << "format";
|
||||||
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
||||||
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
|
ox::FileSystem32 fs(ox::FileStore32(fsBuff.data(), fsBuff.size()));
|
||||||
|
|
||||||
oxTrace("ox.fs.test.FileSystem") << "mkdir";
|
oxTrace("ox.fs.test.FileSystem") << "mkdir";
|
||||||
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
|
oxAssert(fs.mkdir("/dir", true), "mkdir failed");
|
||||||
oxAssert(fs.stat("/dir").error, "mkdir failed");
|
oxAssert(fs.stat("/dir").error, "mkdir failed");
|
||||||
@ -220,6 +229,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
|||||||
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
|
oxAssert(fs.stat("/l1d1/l2d1/l3d1").error, "mkdir failed");
|
||||||
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
|
oxAssert(fs.mkdir("/l1d1/l2d2", true), "mkdir failed");
|
||||||
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
|
oxAssert(fs.stat("/l1d1/l2d2").error, "mkdir failed");
|
||||||
|
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
4
deps/ox/src/ox/model/def.hpp
vendored
4
deps/ox/src/ox/model/def.hpp
vendored
@ -10,10 +10,8 @@
|
|||||||
|
|
||||||
#include <ox/std/concepts.hpp>
|
#include <ox/std/concepts.hpp>
|
||||||
|
|
||||||
// oxModelFwdDecl is necessary because Apple-Clang is broken...
|
|
||||||
#define oxModelFwdDecl(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
|
|
||||||
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>());
|
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { oxReturnError(io->template setTypeInfo<modelName>());
|
||||||
#define oxModelEnd() return OxError(0); }
|
#define oxModelEnd() return OxError(0); }
|
||||||
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
|
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
|
||||||
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
|
#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
|
||||||
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
|
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith<modelName> auto*) noexcept
|
||||||
|
4
deps/ox/src/ox/std/array.hpp
vendored
4
deps/ox/src/ox/std/array.hpp
vendored
@ -41,7 +41,7 @@ class Array {
|
|||||||
|
|
||||||
constexpr Array(Array &&other) noexcept;
|
constexpr Array(Array &&other) noexcept;
|
||||||
|
|
||||||
constexpr ~Array() = default;
|
~Array() = default;
|
||||||
|
|
||||||
constexpr iterator<> begin() noexcept {
|
constexpr iterator<> begin() noexcept {
|
||||||
return iterator<>(&m_items[0], 0, ArraySize);
|
return iterator<>(&m_items[0], 0, ArraySize);
|
||||||
@ -81,10 +81,8 @@ class Array {
|
|||||||
|
|
||||||
constexpr Array &operator=(Array &&other) noexcept;
|
constexpr Array &operator=(Array &&other) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr T &operator[](std::size_t i) noexcept;
|
constexpr T &operator[](std::size_t i) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr const T &operator[](std::size_t i) const noexcept;
|
constexpr const T &operator[](std::size_t i) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
15
deps/ox/src/ox/std/assert.hpp
vendored
15
deps/ox/src/ox/std/assert.hpp
vendored
@ -36,8 +36,8 @@ constexpr void assertFunc(CRStringView file, int line, bool pass, [[maybe_unused
|
|||||||
if (!pass) {
|
if (!pass) {
|
||||||
if (!std::is_constant_evaluated()) {
|
if (!std::is_constant_evaluated()) {
|
||||||
#ifdef OX_USE_STDLIB
|
#ifdef OX_USE_STDLIB
|
||||||
auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
|
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
|
||||||
output += genStackTrace(2);
|
printStackTrace(2);
|
||||||
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
|
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
|
||||||
std::abort();
|
std::abort();
|
||||||
#else
|
#else
|
||||||
@ -55,16 +55,15 @@ constexpr void assertFunc(CRStringView file, int line, const Error &err, CRStrin
|
|||||||
if (err) {
|
if (err) {
|
||||||
if (!std::is_constant_evaluated()) {
|
if (!std::is_constant_evaluated()) {
|
||||||
#if defined(OX_USE_STDLIB)
|
#if defined(OX_USE_STDLIB)
|
||||||
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
|
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
|
||||||
if (err.msg) {
|
if (err.msg) {
|
||||||
msg += sfmt("\tError Message:\t{}\n", err.msg);
|
oxErrf("\tError Message:\t{}\n", err.msg);
|
||||||
}
|
}
|
||||||
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
|
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
|
||||||
if (err.file != nullptr) {
|
if (err.file != nullptr) {
|
||||||
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
|
oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
|
||||||
}
|
}
|
||||||
msg += genStackTrace(2);
|
printStackTrace(2);
|
||||||
oxErr(msg);
|
|
||||||
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
|
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
|
||||||
std::abort();
|
std::abort();
|
||||||
#else
|
#else
|
||||||
|
9
deps/ox/src/ox/std/defer.hpp
vendored
9
deps/ox/src/ox/std/defer.hpp
vendored
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "error.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -16,12 +18,13 @@ class Defer {
|
|||||||
T m_deferredFunc;
|
T m_deferredFunc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr Defer(T deferredFunc) noexcept: m_deferredFunc(deferredFunc) {
|
Defer(T deferredFunc) {
|
||||||
|
m_deferredFunc = deferredFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Defer(const Defer&) = delete;
|
Defer(const Defer&) = delete;
|
||||||
|
|
||||||
constexpr ~Defer() {
|
~Defer() {
|
||||||
m_deferredFunc();
|
m_deferredFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,4 +34,4 @@ class Defer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define oxDefer ox::Defer const oxConcat(oxDefer_, __LINE__) =
|
#define oxDefer ox::Defer oxConcat(oxDefer_, __LINE__) = [&]
|
||||||
|
9
deps/ox/src/ox/std/error.hpp
vendored
9
deps/ox/src/ox/std/error.hpp
vendored
@ -165,24 +165,21 @@ struct [[nodiscard]] Result {
|
|||||||
return error == 0;
|
return error == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
constexpr Error copyTo(type &val) const& noexcept {
|
||||||
constexpr Error copyTo(U &val) const& noexcept {
|
|
||||||
if (!error) [[likely]] {
|
if (!error) [[likely]] {
|
||||||
val = value;
|
val = value;
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
constexpr Error copyTo(type &val) && noexcept {
|
||||||
constexpr Error copyTo(U &val) && noexcept {
|
|
||||||
if (!error) [[likely]] {
|
if (!error) [[likely]] {
|
||||||
val = std::move(value);
|
val = std::move(value);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
constexpr Error moveTo(type &val) noexcept {
|
||||||
constexpr Error moveTo(U &val) noexcept {
|
|
||||||
if (!error) [[likely]] {
|
if (!error) [[likely]] {
|
||||||
val = std::move(value);
|
val = std::move(value);
|
||||||
}
|
}
|
||||||
|
22
deps/ox/src/ox/std/stacktrace.cpp
vendored
22
deps/ox/src/ox/std/stacktrace.cpp
vendored
@ -57,28 +57,6 @@ static auto symbolicate([[maybe_unused]]void **frames,
|
|||||||
}
|
}
|
||||||
#endif // defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
|
#endif // defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
|
||||||
|
|
||||||
ox::String genStackTrace([[maybe_unused]]unsigned shave) noexcept {
|
|
||||||
ox::String out;
|
|
||||||
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>) && __has_include(<execinfo.h>)
|
|
||||||
constexpr auto FrameCnt = 100;
|
|
||||||
Vector<void*, FrameCnt> frames(FrameCnt);
|
|
||||||
#ifdef OX_OS_FreeBSD
|
|
||||||
using FrameCnt_t = unsigned;
|
|
||||||
#else
|
|
||||||
using FrameCnt_t = signed;
|
|
||||||
#endif
|
|
||||||
frames.resize(static_cast<std::size_t>(backtrace(frames.data(), static_cast<FrameCnt_t>(frames.size()))));
|
|
||||||
if (frames.size() - shave > 2) {
|
|
||||||
const auto symbolicatedStacktrace = symbolicate(frames.data() + shave, frames.size() - shave, "\t");
|
|
||||||
out+= "Stacktrace:\n";
|
|
||||||
for (const auto &s : symbolicatedStacktrace) {
|
|
||||||
out += sfmt("\t{}\n", s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printStackTrace([[maybe_unused]]unsigned shave) noexcept {
|
void printStackTrace([[maybe_unused]]unsigned shave) noexcept {
|
||||||
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>) && __has_include(<execinfo.h>)
|
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>) && __has_include(<execinfo.h>)
|
||||||
constexpr auto FrameCnt = 100;
|
constexpr auto FrameCnt = 100;
|
||||||
|
5
deps/ox/src/ox/std/stacktrace.hpp
vendored
5
deps/ox/src/ox/std/stacktrace.hpp
vendored
@ -8,13 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "string.hpp"
|
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::String genStackTrace([[maybe_unused]]unsigned shave) noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints a stack trace to stderr.
|
* Prints a stack trace to stderr.
|
||||||
*
|
*
|
||||||
|
27
deps/ox/src/ox/std/tracehook.cpp
vendored
27
deps/ox/src/ox/std/tracehook.cpp
vendored
@ -65,28 +65,23 @@ void oxTraceInitHook() {
|
|||||||
void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
|
void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
|
||||||
[[maybe_unused]] const char *ch, [[maybe_unused]] const char *msg) {
|
[[maybe_unused]] const char *ch, [[maybe_unused]] const char *msg) {
|
||||||
#if defined(OX_USE_STDLIB)
|
#if defined(OX_USE_STDLIB)
|
||||||
auto const chv = ox::StringView{ch};
|
|
||||||
if (OxPrintTrace) {
|
if (OxPrintTrace) {
|
||||||
auto m = std::string_view{msg};
|
|
||||||
if (m.ends_with('\n')) {
|
|
||||||
m = std::string_view{msg, m.size() - 1};
|
|
||||||
}
|
|
||||||
std::cout << std::setw(53) << std::left << ch << "| ";
|
std::cout << std::setw(53) << std::left << ch << "| ";
|
||||||
std::cout << std::setw(65) << std::left << m << '|';
|
std::cout << std::setw(65) << std::left << msg << '|';
|
||||||
std::cout << " " << file << ':' << line << "\n";
|
std::cout << " " << file << ':' << line << "\n";
|
||||||
} else if (chv == "debug" || chv == "info") {
|
} else if (ox::strcmp(ch, "debug") == 0 || ox::strcmp(ch, "info") == 0) {
|
||||||
printf("%s\n", msg);
|
printf("%s\n", msg);
|
||||||
std::ignore = fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (chv == "stdout") {
|
} else if (ox::strcmp(ch, "stdout") == 0) {
|
||||||
printf("%s", msg);
|
printf("%s", msg);
|
||||||
std::ignore = fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (chv == "stderr") {
|
} else if (ox::strcmp(ch, "stderr") == 0) {
|
||||||
std::ignore = fprintf(stderr, "%s", msg);
|
printf("%s", msg);
|
||||||
std::ignore = fflush(stderr);
|
fflush(stdout);
|
||||||
} else if (chv == "error") {
|
} else if (ox::strcmp(ch, "error") == 0) {
|
||||||
//std::cerr << "\033[31;1;1mERROR:\033[0m (" << file << ':' << line << "): " << msg << '\n';
|
//std::cerr << "\033[31;1;1mERROR:\033[0m (" << file << ':' << line << "): " << msg << '\n';
|
||||||
std::ignore = fprintf(stderr, "\033[31;1;1mERROR:\033[0m (%s:%d): %s\n", file, line, msg);
|
fprintf(stderr, "\033[31;1;1mERROR:\033[0m (%s:%d): %s\n", file, line, msg);
|
||||||
std::ignore = fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (ox::strcmp(ch, "info") == 0) {
|
if (ox::strcmp(ch, "info") == 0) {
|
||||||
|
2
deps/ox/src/ox/std/vector.hpp
vendored
2
deps/ox/src/ox/std/vector.hpp
vendored
@ -222,10 +222,8 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
|||||||
|
|
||||||
constexpr Vector &operator=(Vector &&other) noexcept;
|
constexpr Vector &operator=(Vector &&other) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr T &operator[](std::size_t i) noexcept;
|
constexpr T &operator[](std::size_t i) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr const T &operator[](std::size_t i) const noexcept;
|
constexpr const T &operator[](std::size_t i) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
@ -28,12 +28,8 @@ project_name = sys.argv[2]
|
|||||||
bin = f'./build/{host_env}-{current_build}/bin/'
|
bin = f'./build/{host_env}-{current_build}/bin/'
|
||||||
project_bin = f'build/gba-release/bin/{project_name}.bin'
|
project_bin = f'build/gba-release/bin/{project_name}.bin'
|
||||||
project_gba = f'{project_name}.gba'
|
project_gba = f'{project_name}.gba'
|
||||||
project_manifest = f'{project_name}-manifest.json'
|
|
||||||
|
|
||||||
shutil.copyfile(project_bin, project_gba)
|
shutil.copyfile(project_bin, project_gba)
|
||||||
subprocess.run([
|
subprocess.run([
|
||||||
f'{bin}/{project_name}-pack',
|
f'{bin}/{project_name}-pack', '-src', project_dir, '-rom-bin', project_gba])
|
||||||
'-src', project_dir,
|
|
||||||
'-rom-bin', project_gba,
|
|
||||||
'-manifest', project_manifest])
|
|
||||||
subprocess.run(['gbafix', project_gba])
|
subprocess.run(['gbafix', project_gba])
|
||||||
|
@ -139,15 +139,7 @@ ox::Error loadBgTileSheet(
|
|||||||
Context &ctx,
|
Context &ctx,
|
||||||
unsigned cbb,
|
unsigned cbb,
|
||||||
CompactTileSheet const&ts,
|
CompactTileSheet const&ts,
|
||||||
size_t dstTileIdx,
|
ox::Optional<unsigned> const&paletteBank) noexcept;
|
||||||
size_t srcTileIdx,
|
|
||||||
size_t tileCnt) noexcept;
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
unsigned cbb,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
|
@ -31,12 +31,6 @@ struct TileSheetV1 {
|
|||||||
ox::Vector<uint8_t> pixels = {};
|
ox::Vector<uint8_t> pixels = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(TileSheetV1 const&ts) noexcept {
|
|
||||||
return ts.bpp == 4 || ts.bpp == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct TileSheetV2 {
|
struct TileSheetV2 {
|
||||||
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
||||||
|
|
||||||
@ -49,8 +43,8 @@ struct TileSheetV2 {
|
|||||||
ox::Vector<SubSheet> subsheets;
|
ox::Vector<SubSheet> subsheets;
|
||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels;
|
||||||
constexpr SubSheet() noexcept = default;
|
constexpr SubSheet() noexcept = default;
|
||||||
constexpr SubSheet(ox::StringParam pName, int pColumns, int pRows, int bpp) noexcept:
|
constexpr SubSheet(ox::CRStringView pName, int pColumns, int pRows, int bpp) noexcept:
|
||||||
name(std::move(pName)),
|
name(pName),
|
||||||
columns(pColumns),
|
columns(pColumns),
|
||||||
rows(pRows),
|
rows(pRows),
|
||||||
pixels(static_cast<size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
pixels(static_cast<size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||||
@ -65,12 +59,6 @@ struct TileSheetV2 {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(TileSheetV2 const&ts) noexcept {
|
|
||||||
return ts.bpp == 4 || ts.bpp == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
using SubSheetId = int32_t;
|
using SubSheetId = int32_t;
|
||||||
|
|
||||||
struct TileSheetV3 {
|
struct TileSheetV3 {
|
||||||
@ -86,14 +74,14 @@ struct TileSheetV3 {
|
|||||||
ox::Vector<SubSheet> subsheets;
|
ox::Vector<SubSheet> subsheets;
|
||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels;
|
||||||
constexpr SubSheet() noexcept = default;
|
constexpr SubSheet() noexcept = default;
|
||||||
SubSheet(
|
inline SubSheet(
|
||||||
SubSheetId pId,
|
SubSheetId pId,
|
||||||
ox::StringParam pName,
|
ox::CRStringView pName,
|
||||||
int pColumns,
|
int pColumns,
|
||||||
int pRows,
|
int pRows,
|
||||||
int bpp) noexcept:
|
int bpp) noexcept:
|
||||||
id(pId),
|
id(pId),
|
||||||
name(std::move(pName)),
|
name(pName),
|
||||||
columns(pColumns),
|
columns(pColumns),
|
||||||
rows(pRows),
|
rows(pRows),
|
||||||
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||||
@ -110,13 +98,7 @@ struct TileSheetV3 {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
struct TileSheet {
|
||||||
constexpr bool valid(TileSheetV3 const&ts) noexcept {
|
|
||||||
return ts.bpp == 4 || ts.bpp == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct TileSheetV4 {
|
|
||||||
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
||||||
|
|
||||||
struct SubSheet {
|
struct SubSheet {
|
||||||
@ -130,26 +112,26 @@ struct TileSheetV4 {
|
|||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels;
|
||||||
|
|
||||||
constexpr SubSheet() noexcept = default;
|
constexpr SubSheet() noexcept = default;
|
||||||
SubSheet(
|
inline SubSheet(
|
||||||
SubSheetId pId,
|
SubSheetId pId,
|
||||||
ox::StringParam pName,
|
ox::CRStringView pName,
|
||||||
int pColumns,
|
int pColumns,
|
||||||
int pRows,
|
int pRows,
|
||||||
int bpp) noexcept:
|
int bpp) noexcept:
|
||||||
id(pId),
|
id(pId),
|
||||||
name(std::move(pName)),
|
name(pName),
|
||||||
columns(pColumns),
|
columns(pColumns),
|
||||||
rows(pRows),
|
rows(pRows),
|
||||||
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||||
}
|
}
|
||||||
SubSheet(
|
inline SubSheet(
|
||||||
SubSheetId pId,
|
SubSheetId pId,
|
||||||
ox::StringParam pName,
|
ox::CRStringView pName,
|
||||||
int pColumns,
|
int pColumns,
|
||||||
int pRows,
|
int pRows,
|
||||||
ox::Vector<uint8_t> pPixels) noexcept:
|
ox::Vector<uint8_t> pPixels) noexcept:
|
||||||
id(pId),
|
id(pId),
|
||||||
name(std::move(pName)),
|
name(pName),
|
||||||
columns(pColumns),
|
columns(pColumns),
|
||||||
rows(pRows),
|
rows(pRows),
|
||||||
pixels(std::move(pPixels)) {
|
pixels(std::move(pPixels)) {
|
||||||
@ -169,18 +151,10 @@ struct TileSheetV4 {
|
|||||||
ox::FileAddress defaultPalette;
|
ox::FileAddress defaultPalette;
|
||||||
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
||||||
|
|
||||||
constexpr TileSheetV4() noexcept = default;
|
constexpr TileSheet() noexcept = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(TileSheetV4 const&ts) noexcept {
|
|
||||||
return ts.bpp == 4 || ts.bpp == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
using TileSheet = TileSheetV4;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
|
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
|
||||||
|
|
||||||
@ -312,11 +286,12 @@ ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::CRStringView pNamePat
|
|||||||
|
|
||||||
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept;
|
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept;
|
||||||
|
|
||||||
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept;
|
ox::Result<ox::StringView> getNameFor(TileSheet const&ss, SubSheetId pId) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept;
|
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept;
|
||||||
|
|
||||||
|
using TileSheetV4 = TileSheet;
|
||||||
|
|
||||||
struct CompactTileSheetV1 {
|
struct CompactTileSheetV1 {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
||||||
@ -327,34 +302,8 @@ struct CompactTileSheetV1 {
|
|||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(CompactTileSheetV1 const&ts) noexcept {
|
|
||||||
return ts.bpp == 4 || ts.bpp == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
using CompactTileSheet = CompactTileSheetV1;
|
using CompactTileSheet = CompactTileSheetV1;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
uint8_t getPixel4Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t idx) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
uint8_t getPixel8Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t idx) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Pair<uint8_t> get2Pixels4Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t idx) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Pair<uint8_t> get2Pixels8Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t idx) noexcept;
|
|
||||||
|
|
||||||
oxModelBegin(TileSheetV1)
|
oxModelBegin(TileSheetV1)
|
||||||
oxModelField(bpp)
|
oxModelField(bpp)
|
||||||
oxModelField(rows)
|
oxModelField(rows)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
|
#include <ox/mc/mc.hpp>
|
||||||
#include <ox/std/array.hpp>
|
#include <ox/std/array.hpp>
|
||||||
|
|
||||||
#include <teagba/addresses.hpp>
|
#include <teagba/addresses.hpp>
|
||||||
@ -10,7 +11,9 @@
|
|||||||
#include <teagba/registers.hpp>
|
#include <teagba/registers.hpp>
|
||||||
|
|
||||||
#include <keel/keel.hpp>
|
#include <keel/keel.hpp>
|
||||||
|
#include <turbine/turbine.hpp>
|
||||||
|
|
||||||
|
#include <nostalgia/core/color.hpp>
|
||||||
#include <nostalgia/core/context.hpp>
|
#include <nostalgia/core/context.hpp>
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
#include <nostalgia/core/tilesheet.hpp>
|
#include <nostalgia/core/tilesheet.hpp>
|
||||||
@ -19,7 +22,7 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
static constexpr auto SpriteCount = 128;
|
constexpr auto SpriteCount = 128;
|
||||||
|
|
||||||
ox::Error initGfx(Context&, InitParams const&) noexcept {
|
ox::Error initGfx(Context&, InitParams const&) noexcept {
|
||||||
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
||||||
@ -78,7 +81,7 @@ ox::Error loadSpritePalette(
|
|||||||
|
|
||||||
static ox::Error loadTileSheetSet(
|
static ox::Error loadTileSheetSet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
ox::Span<uint16_t> tileMapTargetMem,
|
uint16_t *tileMapTargetMem,
|
||||||
TileSheetSet const&set) noexcept {
|
TileSheetSet const&set) noexcept {
|
||||||
size_t tileWriteIdx = 0;
|
size_t tileWriteIdx = 0;
|
||||||
size_t const bppMod = set.bpp == 4;
|
size_t const bppMod = set.bpp == 4;
|
||||||
@ -103,34 +106,6 @@ static ox::Error loadTileSheetSet(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
unsigned const cbb,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const dstTileIdx,
|
|
||||||
size_t const srcTileIdx,
|
|
||||||
size_t const tileCnt) noexcept {
|
|
||||||
size_t const bppMod = ts.bpp == 4;
|
|
||||||
size_t const bytesPerTile = PixelsPerTile >> bppMod;
|
|
||||||
auto const pixCnt = tileCnt * bytesPerTile;
|
|
||||||
auto const srcPxIdx = srcTileIdx * bytesPerTile;
|
|
||||||
auto const dstPxIdx = (dstTileIdx * bytesPerTile) / 2;
|
|
||||||
for (size_t i = 0; i < pixCnt; ++i) {
|
|
||||||
auto const srcIdx = srcPxIdx + i * 2;
|
|
||||||
auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]);
|
|
||||||
auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]);
|
|
||||||
MEM_BG_TILES[cbb][dstPxIdx + i] = static_cast<uint16_t>(p1 | (p2 << 8));
|
|
||||||
}
|
|
||||||
// update bpp of all bgs with the updated cbb
|
|
||||||
auto const bpp = ctx.cbbData[cbb].bpp;
|
|
||||||
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
|
|
||||||
if (teagba::bgCbb(bgCtl) == cbb) {
|
|
||||||
teagba::bgSetBpp(bgCtl, bpp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
unsigned cbb,
|
unsigned cbb,
|
||||||
@ -167,10 +142,10 @@ ox::Error loadBgTileSheet(
|
|||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
unsigned const cbb,
|
unsigned cbb,
|
||||||
TileSheetSet const&set) noexcept {
|
TileSheetSet const&set) noexcept {
|
||||||
auto const bpp = static_cast<unsigned>(set.bpp);
|
auto const bpp = static_cast<unsigned>(set.bpp);
|
||||||
oxReturnError(loadTileSheetSet(ctx, MEM_BG_TILES[cbb], set));
|
oxReturnError(loadTileSheetSet(ctx, MEM_BG_TILES[cbb].data(), set));
|
||||||
// update bpp of all bgs with the updated cbb
|
// update bpp of all bgs with the updated cbb
|
||||||
ctx.cbbData[cbb].bpp = bpp;
|
ctx.cbbData[cbb].bpp = bpp;
|
||||||
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
|
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
|
||||||
@ -218,7 +193,7 @@ ox::Error loadSpriteTileSheet(
|
|||||||
Context &ctx,
|
Context &ctx,
|
||||||
TileSheetSet const&set) noexcept {
|
TileSheetSet const&set) noexcept {
|
||||||
auto const bpp = static_cast<unsigned>(set.bpp);
|
auto const bpp = static_cast<unsigned>(set.bpp);
|
||||||
oxReturnError(loadTileSheetSet(ctx, {MEM_SPRITE_TILES, 32 * ox::units::KB}, set));
|
oxReturnError(loadTileSheetSet(ctx, MEM_SPRITE_TILES, set));
|
||||||
setSpritesBpp(bpp);
|
setSpritesBpp(bpp);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
namespace renderer {
|
namespace renderer {
|
||||||
|
|
||||||
static constexpr auto Scale = 1;
|
constexpr auto Scale = 1;
|
||||||
static constexpr auto PriorityScale = 0.01f;
|
constexpr auto PriorityScale = 0.01f;
|
||||||
|
|
||||||
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
|
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ void Drawer::draw(turbine::Context &tctx) noexcept {
|
|||||||
core::gl::draw(m_ctx, turbine::getScreenSize(tctx));
|
core::gl::draw(m_ctx, turbine::getScreenSize(tctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr ox::CStringView bgvshadTmpl = R"glsl(
|
constexpr ox::CStringView bgvshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
in vec3 vPosition;
|
in vec3 vPosition;
|
||||||
@ -55,7 +55,7 @@ static constexpr ox::CStringView bgvshadTmpl = R"glsl(
|
|||||||
fPalOffset = vPalOffset;
|
fPalOffset = vPalOffset;
|
||||||
})glsl";
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::CStringView bgfshadTmpl = R"glsl(
|
constexpr ox::CStringView bgfshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
in float fPalOffset;
|
in float fPalOffset;
|
||||||
@ -71,7 +71,7 @@ static constexpr ox::CStringView bgfshadTmpl = R"glsl(
|
|||||||
}
|
}
|
||||||
})glsl";
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::CStringView spritevshadTmpl = R"glsl(
|
constexpr ox::CStringView spritevshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
in float vEnabled;
|
in float vEnabled;
|
||||||
in vec3 vPosition;
|
in vec3 vPosition;
|
||||||
@ -90,7 +90,7 @@ static constexpr ox::CStringView spritevshadTmpl = R"glsl(
|
|||||||
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
||||||
})glsl";
|
})glsl";
|
||||||
|
|
||||||
static constexpr ox::CStringView spritefshadTmpl = R"glsl(
|
constexpr ox::CStringView spritefshadTmpl = R"glsl(
|
||||||
{}
|
{}
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
in vec2 fTexCoord;
|
in vec2 fTexCoord;
|
||||||
@ -279,7 +279,7 @@ static void initBackgroundBufferset(
|
|||||||
static glutils::GLTexture createTexture(
|
static glutils::GLTexture createTexture(
|
||||||
GLsizei w,
|
GLsizei w,
|
||||||
GLsizei h,
|
GLsizei h,
|
||||||
void const*pixels) noexcept {
|
const void *pixels) noexcept {
|
||||||
GLuint texId = 0;
|
GLuint texId = 0;
|
||||||
glGenTextures(1, &texId);
|
glGenTextures(1, &texId);
|
||||||
glutils::GLTexture tex(texId);
|
glutils::GLTexture tex(texId);
|
||||||
@ -492,22 +492,22 @@ struct TileSheetData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static ox::Result<TileSheetData> normalizeTileSheet(
|
static ox::Result<TileSheetData> normalizeTileSheet(
|
||||||
CompactTileSheet const&ts) noexcept {
|
CompactTileSheet const&tilesheet) noexcept {
|
||||||
const uint_t bytesPerTile = ts.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
|
const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
|
||||||
const auto tiles = ts.pixels.size() / bytesPerTile;
|
const auto tiles = tilesheet.pixels.size() / bytesPerTile;
|
||||||
constexpr int width = 8;
|
constexpr int width = 8;
|
||||||
const int height = 8 * static_cast<int>(tiles);
|
const int height = 8 * static_cast<int>(tiles);
|
||||||
ox::Vector<uint32_t> pixels;
|
ox::Vector<uint32_t> pixels;
|
||||||
if (bytesPerTile == 64) { // 8 BPP
|
if (bytesPerTile == 64) { // 8 BPP
|
||||||
pixels.resize(ts.pixels.size());
|
pixels.resize(tilesheet.pixels.size());
|
||||||
for (std::size_t i = 0; i < ts.pixels.size(); ++i) {
|
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
|
||||||
pixels[i] = ts.pixels[i];
|
pixels[i] = tilesheet.pixels[i];
|
||||||
}
|
}
|
||||||
} else { // 4 BPP
|
} else { // 4 BPP
|
||||||
pixels.resize(ts.pixels.size() * 2);
|
pixels.resize(tilesheet.pixels.size() * 2);
|
||||||
for (std::size_t i = 0; i < ts.pixels.size(); ++i) {
|
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
|
||||||
pixels[i * 2 + 0] = ts.pixels[i] & 0xF;
|
pixels[i * 2 + 0] = tilesheet.pixels[i] & 0xF;
|
||||||
pixels[i * 2 + 1] = ts.pixels[i] >> 4;
|
pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TileSheetData{std::move(pixels), width, height};
|
return TileSheetData{std::move(pixels), width, height};
|
||||||
@ -572,58 +572,14 @@ static ox::Result<TileSheetData> buildSetTsd(
|
|||||||
return setTsd;
|
return setTsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyPixels(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
uint32_t *dst,
|
|
||||||
size_t const srcPxIdx,
|
|
||||||
size_t pxlCnt) noexcept {
|
|
||||||
if (ts.bpp == 4) {
|
|
||||||
for (size_t i = 0; i < pxlCnt; i += 2) {
|
|
||||||
auto const [a, b] = get2Pixels4Bpp(ts, i + srcPxIdx);
|
|
||||||
*(dst++) = a;
|
|
||||||
*(dst++) = b;
|
|
||||||
}
|
|
||||||
} else if (ts.bpp == 8) {
|
|
||||||
for (size_t i = 0; i < pxlCnt; i += 2) {
|
|
||||||
auto const [a, b] = get2Pixels8Bpp(ts, i + srcPxIdx);
|
|
||||||
*(dst++) = a;
|
|
||||||
*(dst++) = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
|
||||||
Context &ctx,
|
|
||||||
unsigned const cbb,
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const dstTileIdx,
|
|
||||||
size_t const srcTileIdx,
|
|
||||||
size_t const tileCnt) noexcept {
|
|
||||||
auto &cbbPxls = ctx.cbbs[cbb].pixels;
|
|
||||||
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
|
|
||||||
auto const pxlCnt = tileCnt * PixelsPerTile;
|
|
||||||
auto const srcPxIdx = srcTileIdx * PixelsPerTile;
|
|
||||||
auto const dstPxIdx = dstTileIdx * PixelsPerTile;
|
|
||||||
if (dstPxIdx + pxlCnt >= cbbPxls.size()) {
|
|
||||||
return OxError(1, "video mem dst overflow");
|
|
||||||
}
|
|
||||||
auto const dst = &cbbPxls[dstPxIdx];
|
|
||||||
copyPixels(ts, dst, srcPxIdx, pxlCnt);
|
|
||||||
auto const cbbTiles = cbbPxls.size() / bytesPerTile;
|
|
||||||
int constexpr cbbWidth = 8;
|
|
||||||
int const cbbHeight = 8 * static_cast<int>(cbbTiles);
|
|
||||||
ctx.cbbs[cbb].tex = renderer::createTexture(cbbWidth, cbbHeight, cbbPxls.data());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error loadBgTileSheet(
|
ox::Error loadBgTileSheet(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
uint_t cbb,
|
uint_t cbb,
|
||||||
CompactTileSheet const&ts,
|
CompactTileSheet const&ts,
|
||||||
ox::Optional<unsigned> const&paletteBank) noexcept {
|
ox::Optional<unsigned> const&paletteBank) noexcept {
|
||||||
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
|
oxRequire(tsd, normalizeTileSheet(ts));
|
||||||
auto const tiles = ts.pixels.size() / bytesPerTile;
|
oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbb, tsd.width, tsd.height);
|
||||||
oxReturnError(loadBgTileSheet(ctx, cbb, ts, 0, 0, tiles));
|
ctx.cbbs[cbb].tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
|
||||||
if (paletteBank.has_value() && ts.defaultPalette) {
|
if (paletteBank.has_value() && ts.defaultPalette) {
|
||||||
oxReturnError(loadBgPalette(ctx, *paletteBank, ts.defaultPalette));
|
oxReturnError(loadBgPalette(ctx, *paletteBank, ts.defaultPalette));
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ constexpr uint64_t SpriteVertexEboLength = 6;
|
|||||||
|
|
||||||
struct CBB: public glutils::BufferSet {
|
struct CBB: public glutils::BufferSet {
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
ox::Array<uint32_t, 32768> pixels;
|
|
||||||
constexpr CBB() noexcept {
|
constexpr CBB() noexcept {
|
||||||
vertices.resize(TileCount * BgVertexVboLength);
|
vertices.resize(TileCount * BgVertexVboLength);
|
||||||
elements.resize(TileCount * BgVertexEboLength);
|
elements.resize(TileCount * BgVertexEboLength);
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
oxModelFwdDecl(class TileSheetClipboard);
|
|
||||||
|
|
||||||
class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> {
|
class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> {
|
||||||
public:
|
public:
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
|
||||||
|
@ -312,8 +312,9 @@ void TileSheetEditorImGui::drawSubsheetSelector(
|
|||||||
for (auto i = 0ul; auto &child : subsheet.subsheets) {
|
for (auto i = 0ul; auto &child : subsheet.subsheets) {
|
||||||
path.push_back(i);
|
path.push_back(i);
|
||||||
ImGui::PushID(static_cast<int>(i));
|
ImGui::PushID(static_cast<int>(i));
|
||||||
ig::IndentStackItem const indentStackItem{-indentReduce};
|
ImGui::Indent(-indentReduce);
|
||||||
drawSubsheetSelector(child, path);
|
drawSubsheetSelector(child, path);
|
||||||
|
ImGui::Indent(indentReduce);
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
path.pop_back();
|
path.pop_back();
|
||||||
++i;
|
++i;
|
||||||
@ -439,7 +440,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
}
|
}
|
||||||
auto const pages = m_model.pal().pages.size();
|
auto const pages = m_model.pal().pages.size();
|
||||||
if (pages > 1) {
|
if (pages > 1) {
|
||||||
ig::IndentStackItem const indentStackItem{20};
|
ImGui::Indent(20);
|
||||||
using Str = ox::IString<55>;
|
using Str = ox::IString<55>;
|
||||||
auto numStr = ox::sfmt<Str>(
|
auto numStr = ox::sfmt<Str>(
|
||||||
"{} - {}", m_model.palettePage() + 1, m_model.pal().pages[m_model.palettePage()].name);
|
"{} - {}", m_model.palettePage() + 1, m_model.pal().pages[m_model.palettePage()].name);
|
||||||
@ -457,6 +458,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
ImGui::Indent(-20);
|
||||||
}
|
}
|
||||||
// header
|
// header
|
||||||
if (ImGui::BeginTable(
|
if (ImGui::BeginTable(
|
||||||
|
@ -280,7 +280,7 @@ uint8_t getPixel4Bpp(
|
|||||||
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
|
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
|
||||||
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
|
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
|
||||||
auto &s = getSubSheet(ts, subsheetIdx);
|
auto &s = getSubSheet(ts, subsheetIdx);
|
||||||
auto const idx = ptToIdx(pt, s.columns);
|
const auto idx = ptToIdx(pt, s.columns);
|
||||||
return getPixel4Bpp(s, idx);
|
return getPixel4Bpp(s, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,49 +290,10 @@ uint8_t getPixel8Bpp(
|
|||||||
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
|
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
|
||||||
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
|
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
|
||||||
auto &s = getSubSheet(ts, subsheetIdx);
|
auto &s = getSubSheet(ts, subsheetIdx);
|
||||||
auto const idx = ptToIdx(pt, s.columns);
|
const auto idx = ptToIdx(pt, s.columns);
|
||||||
return getPixel8Bpp(s, idx);
|
return getPixel8Bpp(s, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getPixel4Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const idx) noexcept {
|
|
||||||
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
|
|
||||||
if (idx & 1) {
|
|
||||||
return ts.pixels[idx / 2] >> 4;
|
|
||||||
} else {
|
|
||||||
return ts.pixels[idx / 2] & 0b0000'1111;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getPixel8Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const idx) noexcept {
|
|
||||||
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
|
|
||||||
return ts.pixels[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Pair<uint8_t> get2Pixels4Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const idx) noexcept {
|
|
||||||
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
|
|
||||||
auto const out = ts.pixels[idx / 2];
|
|
||||||
return {
|
|
||||||
static_cast<uint8_t>(out & 0x0f),
|
|
||||||
static_cast<uint8_t>(out >> 4),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Pair<uint8_t> get2Pixels8Bpp(
|
|
||||||
CompactTileSheet const&ts,
|
|
||||||
size_t const idx) noexcept {
|
|
||||||
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
|
|
||||||
return {
|
|
||||||
static_cast<uint8_t>(ts.pixels[idx]),
|
|
||||||
static_cast<uint8_t>(ts.pixels[idx + 1]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static ox::Result<SubSheetId> getIdFor(
|
static ox::Result<SubSheetId> getIdFor(
|
||||||
TileSheet::SubSheet const&ss,
|
TileSheet::SubSheet const&ss,
|
||||||
ox::SpanView<ox::StringView> const&pNamePath,
|
ox::SpanView<ox::StringView> const&pNamePath,
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#include <ox/std/hashmap.hpp>
|
#include <ox/std/hashmap.hpp>
|
||||||
#include <ox/std/utility.hpp>
|
#include <ox/std/utility.hpp>
|
||||||
|
|
||||||
#include "validation.hpp"
|
|
||||||
|
|
||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
class AssetManager;
|
class AssetManager;
|
||||||
@ -23,6 +21,17 @@ class AssetManager;
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class AssetRef;
|
class AssetRef;
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr bool valid(auto const&) noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr ox::Error repair(auto const&) noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class AssetContainer {
|
class AssetContainer {
|
||||||
@ -217,7 +226,9 @@ class AssetManager {
|
|||||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
||||||
auto &p = m_cache[assetId];
|
auto &p = m_cache[assetId];
|
||||||
oxRequireM(obj, m_loader(assetId));
|
oxRequireM(obj, m_loader(assetId));
|
||||||
oxReturnError(ensureValid(obj));
|
if (!valid(obj) && repair(obj)) {
|
||||||
|
return OxError(1, "asset is invalid state and could not be repaired");
|
||||||
|
}
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,6 +57,8 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noex
|
|||||||
|
|
||||||
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
|
||||||
|
|
||||||
|
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -12,31 +12,6 @@
|
|||||||
|
|
||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
struct ManifestEntry {
|
|
||||||
static constexpr auto TypeName = "net.drinkingtea.keel.ManifestEntry";
|
|
||||||
static constexpr auto TypeVersion = 1;
|
|
||||||
uint64_t inode{};
|
|
||||||
bool preloaded{};
|
|
||||||
ox::String type;
|
|
||||||
};
|
|
||||||
|
|
||||||
oxModelBegin(ManifestEntry)
|
|
||||||
oxModelField(inode)
|
|
||||||
oxModelField(preloaded)
|
|
||||||
oxModelField(type)
|
|
||||||
oxModelEnd()
|
|
||||||
|
|
||||||
struct Manifest {
|
|
||||||
static constexpr auto TypeName = "net.drinkingtea.keel.Manifest";
|
|
||||||
static constexpr auto TypeVersion = 1;
|
|
||||||
ox::HashMap<ox::String, ManifestEntry> files;
|
|
||||||
};
|
|
||||||
|
|
||||||
oxModelBegin(Manifest)
|
|
||||||
oxModelField(files)
|
|
||||||
oxModelEnd()
|
|
||||||
|
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
struct GbaPlatSpec {
|
struct GbaPlatSpec {
|
||||||
@ -138,7 +113,6 @@ ox::Error preloadObj(
|
|||||||
// transformations need to be done after the copy to the new FS is complete
|
// transformations need to be done after the copy to the new FS is complete
|
||||||
template<typename PlatSpec>
|
template<typename PlatSpec>
|
||||||
ox::Error preloadDir(
|
ox::Error preloadDir(
|
||||||
Manifest &manifest,
|
|
||||||
ox::TypeStore &ts,
|
ox::TypeStore &ts,
|
||||||
ox::FileSystem &romFs,
|
ox::FileSystem &romFs,
|
||||||
ox::Preloader<PlatSpec> &pl,
|
ox::Preloader<PlatSpec> &pl,
|
||||||
@ -151,14 +125,13 @@ ox::Error preloadDir(
|
|||||||
oxRequire(stat, romFs.stat(filePath));
|
oxRequire(stat, romFs.stat(filePath));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
auto const dir = ox::sfmt("{}{}/", path, name);
|
auto const dir = ox::sfmt("{}{}/", path, name);
|
||||||
oxReturnError(preloadDir(manifest, ts, romFs, pl, dir));
|
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
||||||
} else {
|
} else {
|
||||||
auto const err = preloadObj(ts, romFs, pl, filePath);
|
auto const err = preloadObj(ts, romFs, pl, filePath);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxErrf("\033[31;1;1mCould not preload {}:\n\t{}\n", filePath, toStr(err));
|
oxErrf("\033[31;1;1mCould not preload {}:\n\t{}\n", filePath, toStr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
manifest.files[filePath].preloaded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -189,15 +162,11 @@ ox::Error appendBinary(ox::Buffer &binBuff, ox::SpanView<char> const&fsBuff, ox:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename PlatSpec>
|
template<typename PlatSpec>
|
||||||
ox::Error preload(
|
ox::Error preload(ox::TypeStore &ts, ox::FileSystem &src, ox::Preloader<PlatSpec> &pl) noexcept {
|
||||||
Manifest &manifest,
|
|
||||||
ox::TypeStore &ts,
|
|
||||||
ox::FileSystem &src,
|
|
||||||
ox::Preloader<PlatSpec> &pl) noexcept {
|
|
||||||
oxOut("Preloading\n");
|
oxOut("Preloading\n");
|
||||||
return detail::preloadDir(manifest, ts, src, pl, "/");
|
return detail::preloadDir(ts, src, pl, "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error pack(Manifest &manifest, keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
|
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,27 +51,27 @@ constexpr T &wrapCast(Wrap &ptr) noexcept {
|
|||||||
|
|
||||||
class BaseConverter {
|
class BaseConverter {
|
||||||
public:
|
public:
|
||||||
constexpr virtual ~BaseConverter() noexcept = default;
|
virtual ~BaseConverter() noexcept = default;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr virtual ox::StringView srcTypeName() const noexcept = 0;
|
virtual ox::StringView srcTypeName() const noexcept = 0;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr virtual int srcTypeVersion() const noexcept = 0;
|
virtual int srcTypeVersion() const noexcept = 0;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr virtual bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept = 0;
|
virtual bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept = 0;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
||||||
|
|
||||||
virtual ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
|
virtual ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
|
||||||
|
|
||||||
virtual ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
|
virtual ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
|
||||||
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept = 0;
|
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept = 0;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool matches(
|
inline bool matches(
|
||||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||||
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
||||||
return srcMatches(srcTypeName, srcTypeVersion)
|
return srcMatches(srcTypeName, srcTypeVersion)
|
||||||
@ -84,17 +84,17 @@ template<typename SrcType, typename DstType>
|
|||||||
class Converter: public BaseConverter {
|
class Converter: public BaseConverter {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr ox::StringView srcTypeName() const noexcept final {
|
ox::StringView srcTypeName() const noexcept final {
|
||||||
return ox::ModelTypeName_v<SrcType>;
|
return ox::ModelTypeName_v<SrcType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int srcTypeVersion() const noexcept final {
|
int srcTypeVersion() const noexcept final {
|
||||||
return ox::ModelTypeVersion_v<SrcType>;
|
return ox::ModelTypeVersion_v<SrcType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept final {
|
bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept final {
|
||||||
constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
|
constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
|
||||||
constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
|
constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
|
||||||
return pSrcTypeName == SrcTypeName
|
return pSrcTypeName == SrcTypeName
|
||||||
@ -102,8 +102,8 @@ class Converter: public BaseConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
|
bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
|
||||||
constexpr auto DstTypeName = ox::StringView{ox::requireModelTypeName<DstType>()};
|
constexpr auto DstTypeName = ox::StringView(ox::requireModelTypeName<DstType>());
|
||||||
constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
return dstTypeName == DstTypeName
|
return dstTypeName == DstTypeName
|
||||||
&& dstTypeVersion == DstTypeVersion;
|
&& dstTypeVersion == DstTypeVersion;
|
||||||
@ -117,9 +117,8 @@ class Converter: public BaseConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
|
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
|
||||||
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept final {
|
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept final {
|
||||||
oxRequireM(src, readAsset<SrcType>(srcBuff));
|
oxRequireM(src, readAsset<SrcType>(srcBuff));
|
||||||
oxReturnError(ensureValid(src));
|
|
||||||
auto dst = makeWrap<DstType>();
|
auto dst = makeWrap<DstType>();
|
||||||
oxReturnError(convert(ctx, src, wrapCast<DstType>(*dst)));
|
oxReturnError(convert(ctx, src, wrapCast<DstType>(*dst)));
|
||||||
return {std::move(dst)};
|
return {std::move(dst)};
|
||||||
@ -132,12 +131,12 @@ class Converter: public BaseConverter {
|
|||||||
|
|
||||||
ox::Result<ox::UPtr<Wrap>> convert(
|
ox::Result<ox::UPtr<Wrap>> convert(
|
||||||
keel::Context &ctx,
|
keel::Context &ctx,
|
||||||
ox::BufferView const&srcBuffer,
|
ox::Buffer const&srcBuffer,
|
||||||
ox::CRStringView dstTypeName,
|
ox::CRStringView dstTypeName,
|
||||||
int dstTypeVersion) noexcept;
|
int dstTypeVersion) noexcept;
|
||||||
|
|
||||||
template<typename DstType>
|
template<typename DstType>
|
||||||
ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&srcBuffer) noexcept {
|
ox::Result<DstType> convert(keel::Context &ctx, ox::Buffer const&srcBuffer) noexcept {
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||||
@ -145,7 +144,7 @@ ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&srcBuffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename DstType>
|
template<typename DstType>
|
||||||
ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType *outObj) noexcept {
|
ox::Error convert(keel::Context &ctx, ox::Buffer const&buff, DstType *outObj) noexcept {
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
||||||
@ -155,7 +154,7 @@ ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType *outObj
|
|||||||
|
|
||||||
template<typename DstType>
|
template<typename DstType>
|
||||||
ox::Result<ox::Buffer> convertBuffToBuff(
|
ox::Result<ox::Buffer> convertBuffToBuff(
|
||||||
keel::Context &ctx, ox::BufferView const&srcBuffer, ox::ClawFormat fmt) noexcept {
|
keel::Context &ctx, ox::Buffer const&srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/std/error.hpp>
|
|
||||||
|
|
||||||
namespace keel {
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr bool valid(auto const&) noexcept {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ox::Error repair(auto const&) noexcept {
|
|
||||||
return OxError(1, "No repair function for this type");
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ox::Error ensureValid(auto &o) noexcept {
|
|
||||||
if (!valid(o)) {
|
|
||||||
return repair(o);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -154,6 +154,18 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexce
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
|
||||||
|
oxRequireM(typeId, readAssetTypeId(clawData));
|
||||||
|
for (auto const tr : packTransforms(ctx)) {
|
||||||
|
bool changed{};
|
||||||
|
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
|
||||||
|
if (changed) {
|
||||||
|
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept {
|
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept {
|
||||||
ox::UUIDStr uuidStr;
|
ox::UUIDStr uuidStr;
|
||||||
if (beginsWith(assetId, "uuid://")) {
|
if (beginsWith(assetId, "uuid://")) {
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/logconn/def.hpp>
|
#include <ox/logconn/def.hpp>
|
||||||
#include <ox/logconn/logconn.hpp>
|
#include <ox/logconn/logconn.hpp>
|
||||||
#include <ox/oc/write.hpp>
|
|
||||||
|
|
||||||
#include <keel/keel.hpp>
|
#include <keel/keel.hpp>
|
||||||
|
|
||||||
@ -49,21 +48,16 @@ static ox::Error generateTypes(ox::TypeStore &ts) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error pack(
|
static ox::Error pack(ox::StringView argSrc, ox::StringView argRomBin, ox::StringView projectDataDir) noexcept {
|
||||||
ox::StringView argSrc,
|
|
||||||
ox::StringView argRomBin,
|
|
||||||
ox::StringView argManifest,
|
|
||||||
ox::StringView projectDataDir) noexcept {
|
|
||||||
ox::Buffer dstBuff(32 * ox::units::MB);
|
ox::Buffer dstBuff(32 * ox::units::MB);
|
||||||
oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
|
oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
|
||||||
ox::FileSystem32 dst(dstBuff);
|
ox::FileSystem32 dst(dstBuff);
|
||||||
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack"));
|
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack"));
|
||||||
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
|
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
|
||||||
oxReturnError(generateTypes(ts));
|
oxReturnError(generateTypes(ts));
|
||||||
keel::Manifest manifest;
|
oxReturnError(keel::pack(*ctx, ts, dst));
|
||||||
oxReturnError(keel::pack(manifest, *ctx, ts, dst));
|
|
||||||
oxRequireM(pl, keel::GbaPreloader::make());
|
oxRequireM(pl, keel::GbaPreloader::make());
|
||||||
oxReturnError(preload(manifest, ts, dst, *pl));
|
oxReturnError(preload(ts, dst, *pl));
|
||||||
oxReturnError(dst.resize());
|
oxReturnError(dst.resize());
|
||||||
// resize buffer
|
// resize buffer
|
||||||
oxRequire(dstSize, dst.size());
|
oxRequire(dstSize, dst.size());
|
||||||
@ -76,8 +70,6 @@ static ox::Error pack(
|
|||||||
oxReturnError(appendBinary(romBuff, dstBuff, *pl));
|
oxReturnError(appendBinary(romBuff, dstBuff, *pl));
|
||||||
oxOutf("Final ROM buff size: {} bytes\n", romBuff.size());
|
oxOutf("Final ROM buff size: {} bytes\n", romBuff.size());
|
||||||
oxReturnError(writeFileBuff(argRomBin, romBuff));
|
oxReturnError(writeFileBuff(argRomBin, romBuff));
|
||||||
oxRequire(manifestJson, ox::writeOC(manifest));
|
|
||||||
oxReturnError(writeFileBuff(argManifest, manifestJson));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +77,6 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
|
|||||||
ox::ClArgs const args(argc, argv);
|
ox::ClArgs const args(argc, argv);
|
||||||
auto const argSrc = args.getString("src", "");
|
auto const argSrc = args.getString("src", "");
|
||||||
auto const argRomBin = args.getString("rom-bin", "");
|
auto const argRomBin = args.getString("rom-bin", "");
|
||||||
auto const argManifest = args.getString("manifest", "");
|
|
||||||
if (argSrc == "") {
|
if (argSrc == "") {
|
||||||
oxErr("\033[31;1;1merror:\033[0m must specify a source directory\n");
|
oxErr("\033[31;1;1merror:\033[0m must specify a source directory\n");
|
||||||
return OxError(1, "must specify a source directory");
|
return OxError(1, "must specify a source directory");
|
||||||
@ -94,7 +85,7 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
|
|||||||
oxErr("\033[31;1;1merror:\033[0m must specify a path for ROM file\n");
|
oxErr("\033[31;1;1merror:\033[0m must specify a path for ROM file\n");
|
||||||
return OxError(1, "must specify a path for preload file");
|
return OxError(1, "must specify a path for preload file");
|
||||||
}
|
}
|
||||||
return pack(argSrc, argRomBin, argManifest, projectDataDir);
|
return pack(argSrc, argRomBin, projectDataDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace olympic {
|
namespace olympic {
|
||||||
|
@ -6,14 +6,13 @@
|
|||||||
#include <ox/model/modelvalue.hpp>
|
#include <ox/model/modelvalue.hpp>
|
||||||
|
|
||||||
#include <keel/media.hpp>
|
#include <keel/media.hpp>
|
||||||
|
|
||||||
#include <keel/pack.hpp>
|
#include <keel/pack.hpp>
|
||||||
|
|
||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
static ox::Error pathToInode(
|
static ox::Error pathToInode(
|
||||||
keel::Context &ctx,
|
keel::Context &ctx, ox::FileSystem &dest, ox::ModelObject &obj) noexcept {
|
||||||
ox::FileSystem &dest,
|
|
||||||
ox::ModelObject &obj) noexcept {
|
|
||||||
auto &o = obj;
|
auto &o = obj;
|
||||||
auto type = static_cast<ox::FileAddressType>(o.at("type").unwrap()->get<int8_t>());
|
auto type = static_cast<ox::FileAddressType>(o.at("type").unwrap()->get<int8_t>());
|
||||||
auto &data = o.at("data").unwrap()->get<ox::ModelUnion>();
|
auto &data = o.at("data").unwrap()->get<ox::ModelUnion>();
|
||||||
@ -86,24 +85,7 @@ static ox::Error transformFileAddressesObj(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error performPackTransforms(
|
|
||||||
ManifestEntry &entry,
|
|
||||||
Context &ctx,
|
|
||||||
ox::Buffer &clawData) noexcept {
|
|
||||||
oxRequireM(typeId, readAssetTypeId(clawData));
|
|
||||||
for (auto const tr : packTransforms(ctx)) {
|
|
||||||
bool changed{};
|
|
||||||
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
|
|
||||||
if (changed) {
|
|
||||||
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.type = ox::String{typeId};
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static ox::Error doTransformations(
|
static ox::Error doTransformations(
|
||||||
Manifest &manifest,
|
|
||||||
keel::Context &ctx,
|
keel::Context &ctx,
|
||||||
ox::TypeStore &ts,
|
ox::TypeStore &ts,
|
||||||
ox::FileSystem &dest,
|
ox::FileSystem &dest,
|
||||||
@ -112,7 +94,7 @@ static ox::Error doTransformations(
|
|||||||
oxRequire(s, dest.stat(filePath));
|
oxRequire(s, dest.stat(filePath));
|
||||||
// do transformations
|
// do transformations
|
||||||
oxRequireM(buff, dest.read(s.inode));
|
oxRequireM(buff, dest.read(s.inode));
|
||||||
oxReturnError(keel::performPackTransforms(manifest.files[filePath], ctx, buff));
|
oxReturnError(keel::performPackTransforms(ctx, buff));
|
||||||
// transform FileAddresses
|
// transform FileAddresses
|
||||||
oxRequireM(obj, keel::readAsset(ts, buff));
|
oxRequireM(obj, keel::readAsset(ts, buff));
|
||||||
oxOutf("transforming {}\n", filePath);
|
oxOutf("transforming {}\n", filePath);
|
||||||
@ -126,7 +108,6 @@ static ox::Error doTransformations(
|
|||||||
// claw file transformations are broken out from copy because path to inode
|
// claw file transformations are broken out from copy because path to inode
|
||||||
// transformations need to be done after the copy to the new FS is complete
|
// transformations need to be done after the copy to the new FS is complete
|
||||||
static ox::Error transformClaw(
|
static ox::Error transformClaw(
|
||||||
Manifest &manifest,
|
|
||||||
keel::Context &ctx,
|
keel::Context &ctx,
|
||||||
ox::TypeStore &ts,
|
ox::TypeStore &ts,
|
||||||
ox::FileSystem &dest,
|
ox::FileSystem &dest,
|
||||||
@ -139,9 +120,9 @@ static ox::Error transformClaw(
|
|||||||
oxRequire(stat, dest.stat(filePath));
|
oxRequire(stat, dest.stat(filePath));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
auto const dir = ox::sfmt("{}{}/", path, name);
|
auto const dir = ox::sfmt("{}{}/", path, name);
|
||||||
oxReturnError(transformClaw(manifest, ctx, ts, dest, dir));
|
oxReturnError(transformClaw(ctx, ts, dest, dir));
|
||||||
} else {
|
} else {
|
||||||
auto const err = doTransformations(manifest, ctx, ts, dest, filePath);
|
auto const err = doTransformations(ctx, ts, dest, filePath);
|
||||||
if (err) {
|
if (err) {
|
||||||
oxErrf("\033[31;1;1mCould not do transformations for {}:\n\t{}\n", filePath, toStr(err));
|
oxErrf("\033[31;1;1mCould not do transformations for {}:\n\t{}\n", filePath, toStr(err));
|
||||||
return err;
|
return err;
|
||||||
@ -152,13 +133,10 @@ static ox::Error transformClaw(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error copy(
|
static ox::Error copy(
|
||||||
Manifest &manifest,
|
|
||||||
ox::FileSystem &src,
|
ox::FileSystem &src,
|
||||||
ox::FileSystem &dest,
|
ox::FileSystem &dest,
|
||||||
ox::CRStringView path,
|
ox::CRStringView path) noexcept {
|
||||||
ox::CRStringView logPrefix = "") noexcept {
|
oxOutf("copying directory: {}\n", path);
|
||||||
oxOutf("{}copying directory: {}\n", logPrefix, path);
|
|
||||||
auto const childLogPrefix = ox::sfmt("{}\t", logPrefix);
|
|
||||||
// copy
|
// copy
|
||||||
oxRequire(fileList, src.ls(path));
|
oxRequire(fileList, src.ls(path));
|
||||||
for (auto const&name : fileList) {
|
for (auto const&name : fileList) {
|
||||||
@ -169,36 +147,27 @@ static ox::Error copy(
|
|||||||
oxRequire(stat, src.stat(currentFile));
|
oxRequire(stat, src.stat(currentFile));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
oxReturnError(dest.mkdir(currentFile, true));
|
oxReturnError(dest.mkdir(currentFile, true));
|
||||||
oxReturnError(copy(manifest, src, dest, currentFile + '/', childLogPrefix));
|
oxReturnError(copy(src, dest, currentFile + '/'));
|
||||||
} else {
|
} else {
|
||||||
// load file
|
// load file
|
||||||
oxOutf("{}copying file: {}...", childLogPrefix, currentFile);
|
oxOutf("copying file: {}\n", currentFile);
|
||||||
ox::StringView status = "failed";
|
|
||||||
oxDefer [&status] {
|
|
||||||
oxOutf(" {}\n", status);
|
|
||||||
};
|
|
||||||
oxRequireM(buff, src.read(currentFile));
|
oxRequireM(buff, src.read(currentFile));
|
||||||
// write file to dest
|
// write file to dest
|
||||||
oxReturnError(dest.write(currentFile, buff));
|
oxReturnError(dest.write(currentFile, buff));
|
||||||
status = "OK";
|
|
||||||
oxRequire(stat, dest.stat(currentFile));
|
|
||||||
manifest.files[currentFile] = {
|
|
||||||
.inode = stat.inode,
|
|
||||||
.type = ox::String{keel::readAssetTypeId(buff).or_value({})},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error pack(
|
static ox::Error copyFS(ox::FileSystem &src, ox::FileSystem &dest) noexcept {
|
||||||
Manifest &manifest,
|
oxReturnError(copy(src, dest, "/"));
|
||||||
keel::Context &ctx,
|
return {};
|
||||||
ox::TypeStore &ts,
|
}
|
||||||
ox::FileSystem &dest) noexcept {
|
|
||||||
oxReturnError(copy(manifest, *ctx.rom, dest, "/"));
|
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept {
|
||||||
|
oxReturnError(copyFS(*ctx.rom, dest));
|
||||||
oxOut("Doing transforms\n");
|
oxOut("Doing transforms\n");
|
||||||
oxReturnError(transformClaw(manifest, ctx, ts, dest, "/"));
|
oxReturnError(transformClaw(ctx, ts, dest, "/"));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
static ox::Result<BaseConverter const*> findConverter(
|
static ox::Result<BaseConverter const*> findConverter(
|
||||||
ox::SpanView<BaseConverter const*> const&converters,
|
ox::SpanView<BaseConverter const*> const&converters,
|
||||||
ox::CRStringView srcTypeName,
|
ox::CRStringView srcTypeName,
|
||||||
@ -26,7 +27,7 @@ static ox::Result<BaseConverter const*> findConverter(
|
|||||||
static ox::Result<ox::UPtr<Wrap>> convert(
|
static ox::Result<ox::UPtr<Wrap>> convert(
|
||||||
keel::Context &ctx,
|
keel::Context &ctx,
|
||||||
ox::SpanView<BaseConverter const*> const&converters,
|
ox::SpanView<BaseConverter const*> const&converters,
|
||||||
ox::BufferView const&srcBuffer,
|
ox::Buffer const&srcBuffer,
|
||||||
ox::CRStringView srcTypeName,
|
ox::CRStringView srcTypeName,
|
||||||
int srcTypeVersion,
|
int srcTypeVersion,
|
||||||
ox::CRStringView dstTypeName,
|
ox::CRStringView dstTypeName,
|
||||||
@ -54,7 +55,7 @@ static ox::Result<ox::UPtr<Wrap>> convert(
|
|||||||
|
|
||||||
ox::Result<ox::UPtr<Wrap>> convert(
|
ox::Result<ox::UPtr<Wrap>> convert(
|
||||||
keel::Context &ctx,
|
keel::Context &ctx,
|
||||||
ox::BufferView const&srcBuffer,
|
ox::Buffer const&srcBuffer,
|
||||||
ox::CRStringView dstTypeName,
|
ox::CRStringView dstTypeName,
|
||||||
int dstTypeVersion) noexcept {
|
int dstTypeVersion) noexcept {
|
||||||
oxRequire(hdr, readAssetHeader(srcBuffer));
|
oxRequire(hdr, readAssetHeader(srcBuffer));
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
ClawEditor::ClawEditor(StudioContext &sctx, ox::StringParam path):
|
ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
|
||||||
Editor(std::move(path)),
|
Editor(path),
|
||||||
m_obj(sctx.project->loadObj<ox::ModelObject>(itemPath()).unwrapThrow()) {
|
m_obj(std::move(obj)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClawEditor::draw(StudioContext&) noexcept {
|
void ClawEditor::draw(studio::StudioContext&) noexcept {
|
||||||
ImGui::BeginChild("PaletteEditor");
|
ImGui::BeginChild("PaletteEditor");
|
||||||
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||||
if (ImGui::BeginTable("ObjTree", 3, flags)) {
|
if (ImGui::BeginTable("ObjTree", 3, flags)) {
|
||||||
|
@ -11,14 +11,14 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
class ClawEditor: public Editor {
|
class ClawEditor: public studio::Editor {
|
||||||
private:
|
private:
|
||||||
using ObjPath = ox::Vector<ox::StringView, 8>;
|
using ObjPath = ox::Vector<ox::StringView, 8>;
|
||||||
ox::ModelObject m_obj;
|
ox::ModelObject m_obj;
|
||||||
public:
|
public:
|
||||||
ClawEditor(StudioContext &sctx, ox::StringParam path);
|
ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept;
|
||||||
|
|
||||||
void draw(StudioContext&) noexcept final;
|
void draw(studio::StudioContext&) noexcept final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void drawRow(ox::ModelValue const&value) noexcept;
|
static void drawRow(ox::ModelValue const&value) noexcept;
|
||||||
|
@ -366,17 +366,23 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
|||||||
}
|
}
|
||||||
oxRequire(ext, studio::fileExt(path));
|
oxRequire(ext, studio::fileExt(path));
|
||||||
// create Editor
|
// create Editor
|
||||||
BaseEditor *editor = nullptr;
|
studio::BaseEditor *editor = nullptr;
|
||||||
auto const err = m_editorMakers.contains(ext) ?
|
if (!m_editorMakers.contains(ext)) {
|
||||||
m_editorMakers[ext](path).moveTo(editor) :
|
auto [obj, err] = m_project->loadObj<ox::ModelObject>(path);
|
||||||
ox::makeCatch<ClawEditor>(m_sctx, path).moveTo(editor);
|
if (err) {
|
||||||
if (err) {
|
return OxError(1, "There is no editor for this file extension");
|
||||||
if constexpr(!ox::defines::Debug) {
|
}
|
||||||
oxErrf("Could not open Editor: {}\n", toStr(err));
|
editor = ox::make<ClawEditor>(path, std::move(obj));
|
||||||
} else {
|
} else {
|
||||||
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
|
auto const err = m_editorMakers[ext](path).moveTo(editor);
|
||||||
|
if (err) {
|
||||||
|
if constexpr(!ox::defines::Debug) {
|
||||||
|
oxErrf("Could not open Editor: {}\n", toStr(err));
|
||||||
|
} else {
|
||||||
|
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
editor->closed.connect(this, &StudioUI::closeFile);
|
editor->closed.connect(this, &StudioUI::closeFile);
|
||||||
m_editors.emplace_back(editor);
|
m_editors.emplace_back(editor);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user