Compare commits

...

181 Commits

Author SHA1 Message Date
4aa8255c55 [ox] Update formatting in recently edited files
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-25 21:26:44 -06:00
bfdfc10425 [nostalgia/gfx] Update panic
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-25 21:11:54 -06:00
cdd574d873 [ox] Change panic and assert to use std::source_location 2026-01-25 21:11:22 -06:00
bc05bd12e5 [ox/model] Rename and fix isBString helpers
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-25 02:06:14 -06:00
b754c66cf5 [ox] Remove enable_if
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-23 01:38:53 -06:00
6a42303239 [ox/std] Slight optimization 2026-01-23 01:38:31 -06:00
7477ede222 [ox/std] Cleanup some enable_ifs
All checks were successful
Build / build (push) Successful in 1m7s
2026-01-21 23:35:19 -06:00
65e3153dda [ox/std] Add Union_c concept 2026-01-21 23:35:02 -06:00
53a224cf8f [ox/std] Cleanup 2026-01-21 23:34:36 -06:00
592e641ba9 [ox/std] Fix writeItoa to work with max length 64 bit ints
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-21 23:28:13 -06:00
689da4a019 [ox] Update docs
All checks were successful
Build / build (push) Successful in 1m10s
2026-01-21 21:04:17 -06:00
bdf7755ee2 [nostalgia/developer-handbook] Update developer handbook 2026-01-21 21:03:47 -06:00
63f627377d [ox/std] Remove excess char from intToStr return
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-20 01:29:37 -06:00
ff9002ad9a [nostalgia/developer-handbook] Update error handling section
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 01:22:05 -06:00
4d0da022cf [ox] Update error handling docs
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 00:47:51 -06:00
02332d99b5 [ox] Fix issues in String Types section of docs
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-20 00:26:38 -06:00
a566ed2a8b [ox/std] Fix writeItoa to work with negatives
All checks were successful
Build / build (push) Successful in 1m9s
2026-01-19 23:00:16 -06:00
815c3d19bf [ox/std] Make StringLiteral constructors non-explicit
All checks were successful
Build / build (push) Successful in 1m8s
2026-01-19 21:00:58 -06:00
522bb14f18 [ox/std] Fix intToStr to have room for negatives 2026-01-19 21:00:12 -06:00
f40d5515f9 [ox] Add strings section to docs
All checks were successful
Build / build (push) Successful in 1m11s
2026-01-18 19:00:24 -06:00
941d1d90dc [ox/std] Add Vector::reserveResize
All checks were successful
Build / build (push) Successful in 1m15s
2026-01-07 21:48:04 -06:00
3e880dcdcc [nostalgia/gfx/studio] Remove unused EBO management
All checks were successful
Build / build (push) Successful in 1m16s
2026-01-07 21:33:16 -06:00
03328ac10f [turbine/glfw] Fix to handle null click handler
All checks were successful
Build / build (push) Successful in 1m9s
2025-12-03 20:44:01 -06:00
63d0abaa3c [nostalgia/gfx/gba] Remove teagba scroll bg function call
All checks were successful
Build / build (push) Successful in 1m15s
2025-11-22 23:53:18 -06:00
ef2a8cda77 [teagba] Remove bg scroll, cleanup 2025-11-22 23:53:04 -06:00
671fa54f6f [ox/std] Make ox::Vector::push_back comply with std::vector::push_back
All checks were successful
Build / build (push) Successful in 1m12s
2025-09-10 23:47:36 -05:00
517432679b [nostalgia/gfx/studio] Cleanup includes
All checks were successful
Build / build (push) Successful in 1m15s
2025-09-04 22:40:58 -05:00
b31c01f724 [keel,studio] Cleanup 2025-09-04 22:37:01 -05:00
f41213f13f [ox/std] Fix channel format for oxLogError
All checks were successful
Build / build (push) Successful in 1m8s
2025-09-04 21:11:52 -05:00
28be7c4650 [ox/fs] Fix write functions to take SpanViews 2025-09-04 21:11:52 -05:00
2f340b13b2 [ox/std] Fix Windows GCC build
All checks were successful
Build / build (push) Successful in 1m15s
2025-09-04 01:21:13 -05:00
312c818866 [nostalgia/gfx/studio] Remove unused variable
All checks were successful
Build / build (push) Successful in 1m10s
2025-08-29 22:18:37 -05:00
0d69d0c4a2 [ox/std] Remove oxDebug line
All checks were successful
Build / build (push) Successful in 1m18s
2025-08-19 21:02:13 -05:00
81a0b8c820 [ox/mc] Remove an oxDebug line
Some checks failed
Build / build (push) Failing after 22s
2025-08-19 20:59:51 -05:00
172b5aee90 [ox/oc] Remove an oxDebug line
Some checks failed
Build / build (push) Failing after 17s
2025-08-19 20:58:32 -05:00
2b5338a9df [nostalgia] Improve Makefile dependency handling
Some checks failed
Build / build (push) Failing after 9s
2025-08-17 14:10:45 -05:00
8a430faf4c [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-08-12 22:57:13 -05:00
e59382dd60 [keel] Address undefined behavior 2025-08-12 22:39:08 -05:00
3006e77ef3 [ox/std] Add and integrate std::launder
All checks were successful
Build / build (push) Successful in 1m30s
2025-08-12 22:37:21 -05:00
59c112a69c [studio] Fix navigate back not to iterate on the first item twice
All checks were successful
Build / build (push) Successful in 1m55s
2025-08-09 15:15:34 -05:00
31b39982c5 [keel] Fix AssetRef to call incRef on initial creation of ref, not just copy
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-31 22:06:52 -05:00
5476417be2 [nostalgia] Add release notes for d2025.07.0
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-31 01:05:29 -05:00
e03be694c2 Merge commit 'b67b95767b7bfcd5f618ebc8e14ddbc83edcbe36'
All checks were successful
Build / build (push) Successful in 1m37s
2025-07-31 00:41:06 -05:00
490c0368bc [nostalgia/gfx] Add lists for file extensions 2025-07-31 00:39:55 -05:00
a24fc407c5 [ox/std] Fix MSVC build 2025-07-31 00:38:26 -05:00
e38b85b4f4 [studio] Eliminate redundant serialization and deserialization
All checks were successful
Build / build (push) Successful in 1m42s
2025-07-30 21:48:44 -05:00
f7c3c02c4c Merge commit '1bfb7f99c215e2c74556bd3281f44962b8faaa96'
All checks were successful
Build / build (push) Successful in 1m35s
2025-07-30 00:42:42 -05:00
8f0f1fea39 [nostalgia/gfx/studio] Make editors use Project::loadObj for their primary assets 2025-07-30 00:37:59 -05:00
2f36a3f6f0 [studio] Add File -> Reload Project menu item 2025-07-30 00:37:23 -05:00
07e5bf9054 [keel] Make keel attempt to delete all existing assets when FS is changed 2025-07-30 00:36:56 -05:00
aacff3daf9 [ox/std] Fix UPtr::reset to conform to unique_ptr::reset 2025-07-30 00:29:34 -05:00
e27eee50f0 [teagba] Add set and scroll background offset functions
All checks were successful
Build / build (push) Successful in 1m15s
2025-07-29 00:34:41 -05:00
fd610454d6 [nostalgia/gfx] Fix compiler warning
Some checks failed
Build / build (push) Failing after 24s
2025-07-29 00:30:17 -05:00
e61d4647b5 [nostalgia/gfx] Fix BG tilesheet loading, add background offset functions
Some checks failed
Build / build (push) Failing after 20s
2025-07-28 21:54:50 -05:00
c275c5f5e6 [hull] Disable building hull for now
All checks were successful
Build / build (push) Successful in 1m22s
2025-07-26 18:33:24 -05:00
fbf49ba511 [ox/std] Add pre- and post-increment operators to Span
Some checks failed
Build / build (push) Failing after 8s
2025-07-26 18:31:55 -05:00
92f74b27d1 [ox/std] Add null check for deallocating in consteval context Vector 2025-07-26 18:31:41 -05:00
934f0c9232 [ox/std] Add beginsWith and endsWith variants that that cingle chars 2025-07-26 18:31:03 -05:00
ee9a3e1152 [ox/std] Cleanup 2025-07-26 18:30:12 -05:00
16886cdf1c [hull] Add start on command interpreter 2025-07-26 18:29:51 -05:00
08b9508d83 [ox/std] Give std::ignore a named type 2025-07-26 15:09:10 -05:00
69bd968f98 [nostalgia/player] Fix build
All checks were successful
Build / build (push) Successful in 1m28s
2025-07-25 22:54:43 -05:00
4e7dc66610 [nostalgia,olympic] Rename string len() functions to size() 2025-07-25 22:48:08 -05:00
bea0cf5a0c [ox/std] Rename string len() functions to size() 2025-07-25 22:47:56 -05:00
c7bc2a954f [nostalgia/gfx] Style update
All checks were successful
Build / build (push) Successful in 1m15s
2025-07-24 21:35:21 -05:00
7372036a0a [nostalgia/gfx] Add function missing from header
All checks were successful
Build / build (push) Successful in 1m14s
2025-07-24 21:25:26 -05:00
7461d832b6 [nostalgia/gfx/studio,studio] Fix CLI tool output to only show usage if no args given
All checks were successful
Build / build (push) Successful in 1m19s
2025-07-24 21:17:58 -05:00
6052798fea Merge commit 'dceeaaa9302b7e9ce85fa773fc187bc593f3c93c'
All checks were successful
Build / build (push) Successful in 1m16s
2025-07-24 01:58:27 -05:00
fae1e73e54 [nostalgia/gfx] Make getSubSheet check root subsheet name
All checks were successful
Build / build (push) Successful in 1m17s
2025-07-24 01:54:06 -05:00
51f2905c9c [nostalgia/gfx/studio] Make TileSheetEditor use export-tilesheet functions for export, fix exporting Root subsheet
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-24 01:45:27 -05:00
0c866d1b96 [studio,nostalgia/gfx] Add system for adding sub-commands in Modules, add export-tilesheet command
All checks were successful
Build / build (push) Successful in 1m16s
2025-07-24 01:29:09 -05:00
fdf39d1a25 [ox/std] Add Result::transformError 2025-07-24 01:24:11 -05:00
a523a75e4b [ox/std] Add missing include to StringParam 2025-07-24 01:23:58 -05:00
cdaa64ed3f [ox/clargs] Fix arg parsing for first '-' 2025-07-24 01:23:31 -05:00
801d35c823 [keel] Make type converters work with functions that take const src arg 2025-07-23 00:41:33 -05:00
37b5fcc0f7 [teagba] Put parentheses around all registers
All checks were successful
Build / build (push) Successful in 1m18s
2025-07-07 23:36:34 -05:00
f5f2c3bee6 [studio/applib] Make Studio remove files unable to be opened from open file list in config 2025-07-07 23:35:28 -05:00
f6ef2b5acb [turbine,nostalgia] Make memory regions cast to bounded ox::Arrays
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-29 23:32:36 -05:00
bf958a4a6e [teagba] Make memory regions cast to bounded ox::Arrays 2025-06-29 23:32:11 -05:00
6a70e478a6 [nostalgia/gfx] Cleanup 2025-06-29 17:46:13 -05:00
671b8edaad [ox/std] Make StringLiteral constructors consteval
All checks were successful
Build / build (push) Successful in 1m29s
2025-06-27 23:05:42 -05:00
952637a1ea Merge commit 'cbf4414fcaf00c00a2abf73b5c04a055180ad980'
All checks were successful
Build / build (push) Successful in 1m37s
2025-06-25 21:33:16 -05:00
7569698e95 [nostalgia,studio] Add FileExts_TileSheet const, and corresponding FilePickerPopup constructor 2025-06-25 21:30:49 -05:00
21713ba945 [ox/std] Fix StringLiteral::operator= to work with DevkitARM 2025-06-25 21:29:41 -05:00
73273b6fa7 [nostalgia/gfx] Add isTileSheet function for checking paths against both file extensions 2025-06-25 21:03:45 -05:00
9f040392c7 [olympic,nostalgia] Cleanup style
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-24 01:59:22 -05:00
f4f7e5d053 Merge commit '9b5f7886cadc5c3dc826d00fa5b2e71696151dfd' 2025-06-23 20:49:01 -05:00
f847289bd4 [glutils] Cleanup
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-23 01:39:47 -05:00
94b0020d15 [nostalgia,olympic] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-23 01:30:33 -05:00
c54c0bad38 [teagba] Cleanup
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-23 01:03:33 -05:00
b9ffae0269 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-23 00:47:46 -05:00
003f3e01c6 [nostalgia] Update release notes 2025-06-22 01:01:09 -05:00
9028e74af0 [nostalgia/gfx/studio/tilesheet] Disable paste when nothing is selected 2025-06-22 01:00:56 -05:00
f5ccab5f2c [studio] Cleanup 2025-06-21 19:19:39 -05:00
c27726a4a9 Merge commit '6bbcae10cc7b21b73171ec0ff196f4baf6304404' 2025-06-21 14:29:47 -05:00
37cfa927d1 [nostalgia/gfx] Address a couple of implicit conversions
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-21 14:16:17 -05:00
0efed70b57 [studio] Fix Studio to clear editor pointers when opening a new project
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-21 14:12:45 -05:00
baf5fa3199 [nostalgia] Move d2025.05.2 release notes to d2025.06.0
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-21 08:54:57 -05:00
bd24a775b2 Merge commit '7371df429534f264c179684412f6197f7968ebfa' 2025-06-21 08:48:13 -05:00
857587c18b [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-21 08:31:27 -05:00
eb3d53c955 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-06-21 08:22:13 -05:00
14d58f3f5b [studio] Fix Navigation shortcuts for non-Mac systems
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-21 08:13:14 -05:00
5f2397903a [studio,nostalgia/gfx/studio/tilesheet] Fix copy/cut/paste enablement when there is no selection
All checks were successful
Build / build (push) Successful in 2m2s
2025-06-21 00:20:06 -05:00
58e0ecb469 [studio] Make FilePickerPopup accept on double click of a file
All checks were successful
Build / build (push) Successful in 1m22s
2025-06-20 23:58:29 -05:00
8838bf420e [studio] Fix to properly copy file that has the same name as deleted file
All checks were successful
Build / build (push) Successful in 1m24s
2025-06-20 23:36:20 -05:00
bddc544d7c [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m33s
2025-06-20 22:48:39 -05:00
a9437191bf [studio,turbine] Add support for mouse back/forward buttons
All checks were successful
Build / build (push) Successful in 1m30s
2025-06-20 22:44:09 -05:00
9d8da7ccda [ox/std] Make strToInt return error for empty string
Some checks failed
Build / build (push) Has been cancelled
2025-06-20 22:43:33 -05:00
394b568e72 [studio] Add Back/Forward navigation
All checks were successful
Build / build (push) Successful in 1m14s
2025-06-20 20:58:42 -05:00
78e9f70db6 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m20s
2025-06-19 23:58:42 -05:00
12e5623fe6 [ox/logconn] Add exception handling for logger thread
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-19 23:56:26 -05:00
cfdfb0a8c9 [studio] Fix file deletion to close file even if not active 2025-06-19 23:55:47 -05:00
56e665301f [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m29s
2025-06-19 21:37:57 -05:00
7415ce4bd9 [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 2m53s
2025-06-17 20:45:24 -05:00
05f42150a1 [olympic] Add new loc command to Makefile
All checks were successful
Build / build (push) Successful in 1m19s
2025-06-09 21:29:27 -05:00
8ea2bc6934 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-09 00:22:17 -05:00
c780924122 [studio] Add [DEBUG] tag to About in debug builds
All checks were successful
Build / build (push) Successful in 1m18s
2025-06-08 21:33:17 -05:00
8c538560ca [nostalgia/gfx/studio/palette] Make RGB key shortcuts work when color channel inputs are focused
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-08 17:00:52 -05:00
c3e75bdb55 [nostalgia/gfx/studio/tilesheet] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-08 16:26:55 -05:00
4419dff299 Merge commit '7688c05bac8c20bc267cae62ec78d55e5d0c493b' 2025-05-31 02:14:15 -05:00
e78c405046 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-31 01:53:59 -05:00
6b7c5d896e [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-31 01:48:07 -05:00
a33a73d73a [nostalgia/gfx/studio/palette] Add preview to color editor
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-31 01:34:00 -05:00
536999c070 Merge commit '47eee1d56d591e3631d16e95a78ea3629ee312ee' 2025-05-30 23:38:53 -05:00
e1cfcc8b5f [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m13s
2025-05-30 23:37:58 -05:00
514cb97835 [nostalgia/gfx/studio/tilesheet] Fix draw command to work on same pixel after switching subsheets 2025-05-30 23:32:51 -05:00
4b5218c4f1 [nostalgia/gfx] Cleanup 2025-05-30 23:32:27 -05:00
2ca77173d3 [keel] Add isUuidUrl function 2025-05-30 23:29:42 -05:00
cce5f52f96 [nostalgia/gfx/studio/tilesheet] Fix manual redo of draw actions, fix drawing to pixel 0, 0 as first action
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-29 22:12:10 -05:00
b55993294a [studio/modlib] Fix headerizeConfigFile to handle slashes in file name
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-25 01:20:20 -05:00
d8f847d707 [studio/applib] Move popup types into their own directory
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-24 15:01:17 -05:00
a5535ef59a Merge commit '08236fc790e711afe886b6ef545511d35e4e5c6c' 2025-05-24 01:44:07 -05:00
8419b137e5 [turbine,studio] Fix some popup window resize weirdness, cleanup some function names
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-24 01:32:14 -05:00
ed1160ec74 [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-24 00:50:22 -05:00
1e21778059 [nostalgia/gfx/studio/tilesheet] Ensure config file has a Claw header 2025-05-24 00:48:54 -05:00
78379f58c8 [studio] Add ability to remember recent projects in config 2025-05-24 00:48:10 -05:00
4322f720ba [keel] Fix ox::Result<DstType> convert(Context &ctx, ox::BufferView const&src) 2025-05-24 00:47:39 -05:00
26f1a6051f [ox/std] Make Vector::remove take a MaybeView_t
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-24 00:46:39 -05:00
c4c1d4777b [keel] Cleanup ox::Error(0) instance 2025-05-23 20:25:08 -05:00
fab012d3e7 [ox] Cleanup all ox::Error(0) instances 2025-05-23 20:24:58 -05:00
a90380f377 Merge commit 'e90dd887477452922f783535edb3d4c55e9a0d2c' 2025-05-23 03:23:17 -05:00
312097a799 [ox/std] Fix implementation of std cmp functions
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-23 03:22:27 -05:00
a40198ab8d [nostalgia] Update release-d2025.05.2 release notes
All checks were successful
Build / build (push) Successful in 1m23s
2025-05-22 20:45:34 -05:00
52d8c0bdc8 [nostalgia/gfx] Replace static_cast compare with std::cmp_equal 2025-05-22 20:43:27 -05:00
c19d7f4ea3 [nostalgia] Add .vs and cmake-build-* to .gitignore 2025-05-22 20:42:09 -05:00
159b7e7ee7 [buildcore] Make pybb cmake_build specify --config debug/release 2025-05-22 20:41:30 -05:00
c93eec4f05 [teagba] Make cstart.cpp only compile if GCC 2025-05-22 20:40:33 -05:00
e7e7a22390 [nostalgia/sample_project] Make sample_project exempt from autocrlf 2025-05-22 20:39:56 -05:00
26d5048e67 [ox/fs] Fix new build error in MSVC (VS 17.14) 2025-05-22 20:05:09 -05:00
3b8f97cc41 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-21 22:15:56 -05:00
f1e68e0a04 [nostalgia/gfx/studio/tilesheet] Fix overrun errors when switching subsheets, clear selection on switch 2025-05-21 22:15:07 -05:00
d6e4ab7a24 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m24s
2025-05-18 14:08:39 -05:00
2000b2deee [nostalgia/gfx/studio] Cleanup 2025-05-17 23:35:10 -05:00
7d92400f6d [nostalgia/gfx/studio] Add type specific navigateTo functions 2025-05-17 23:26:23 -05:00
cb304ecf28 [applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m12s
2025-05-17 17:46:38 -05:00
ea17377700 [ox/std] Make StringViewCR honest
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-17 17:34:22 -05:00
c424bde06d [nostalgia] Style cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 17:31:47 -05:00
ee7d5c6d51 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 17:22:13 -05:00
99247cee32 [nostalgia/gfx/test] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-17 17:18:51 -05:00
7b8ddc189a [nostalgia/gfx] Consolidate implementations into single files, remove unnecessary function exports
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-17 17:13:13 -05:00
a6814030ee [studio/applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m13s
2025-05-17 16:15:32 -05:00
9937a01042 [turbine] Cleanup 2025-05-17 16:12:16 -05:00
abcf2adc56 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 03:02:59 -05:00
05f9023550 [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-17 02:51:56 -05:00
5ba0bcf963 [turbine] Consolidate some files that didn't have sensible distinctions
Some checks failed
Build / build (push) Has been cancelled
2025-05-17 02:51:23 -05:00
3ccadba2f5 [nostalgia/gfx/studio/tilesheet] Fix dragging cursor on image
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-16 21:22:33 -05:00
00e52b6491 [nostalgia] Make pkg-dmg more versatile
All checks were successful
Build / build (push) Successful in 1m14s
2025-05-15 22:26:35 -05:00
ae40487990 [nostalgia/gfx] Add navigateTo handler to TileSheetEditor
All checks were successful
Build / build (push) Successful in 1m20s
2025-05-15 20:39:50 -05:00
84b612c693 [studio/modlib] Give navigateTo a default argument 2025-05-15 20:39:01 -05:00
3c2a6b047e [studio/applib] Make navigateTo handle UUID paths 2025-05-15 20:38:27 -05:00
626da322d9 [ox/std] Add StringParam(IString const&) constructor 2025-05-15 20:37:44 -05:00
0de428a2e5 [studio/applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-14 22:11:43 -05:00
8a52df4f76 [nostalgia/gfx] More cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-14 01:43:59 -05:00
efec6eb3c8 [nostalgia/gfx/studio/palette] Add RGB key shortcuts for focusing color channels
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-14 01:13:40 -05:00
56eeb24900 [nostalgia/gfx/opengl] More cleanup
All checks were successful
Build / build (push) Successful in 1m56s
2025-05-13 22:06:08 -05:00
ae81f6b3de [ox/std] Make Span::operator[] const
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-13 22:02:23 -05:00
c1108301c0 [nostalgia/gfx] Cleanup 2025-05-13 22:01:59 -05:00
83fbe6ac74 [keel,turbine,studio] Fix some install mistakes
All checks were successful
Build / build (push) Successful in 2m17s
2025-05-13 21:39:37 -05:00
80b452833f [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 2m28s
2025-05-13 21:24:04 -05:00
0fa394333b [nostalgia] Add release note about Mac menubar using Cmd
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 01:01:11 -05:00
cae7535034 [nostalgia] Fix typos in release notes
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 00:57:45 -05:00
247 changed files with 4036 additions and 2690 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
sample_project text eol=lf

2
.gitignore vendored
View File

@@ -6,12 +6,14 @@
.mypy_cache
.stfolder
.stignore
.vs
util/scripts/__pycache__
pyenv
CMakeLists.txt.user
ROM.oxfs
Session.vim
build
cmake-build-*
compile_commands.json
dist
graph_info.json

View File

@@ -14,37 +14,56 @@ endif
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
.PHONY: pkg-gba
pkg-gba: build
pkg-gba: build-pack build-gba-player
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
.PHONY: pkg-mac
pkg-mac: install
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-dmg.py
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-dmg.py NostalgiaStudio
.PHONY: generate-studio-rsrc
generate-studio-rsrc:
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/olympic/studio/applib/src/rsrc.json
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json
.PHONY: build-gba-player
build-gba-player:
cmake --build ./build/gba-*
.PHONY: build-player
build-player:
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME_CAP}
.PHONY: build-pack
build-pack:
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME}-pack
.PHONY: run
run: build-player
${PROJECT_PLAYER} sample_project
.PHONY: build-studio
build-studio:
cmake --build ./build/${BC_VAR_CURRENT_BUILD} --target ${BC_VAR_PROJECT_NAME_CAP}Studio
.PHONY: run-studio
run-studio: build
run-studio: build-studio
${PROJECT_STUDIO}
.PHONY: gba-run
gba-run: pkg-gba
${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba
.PHONY: debug
debug: build
${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project
.PHONY: debug-studio
debug-studio: build
${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}
.PHONY: configure-gba
configure-gba:
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=release --build_root=${BC_VAR_BUILD_PATH}
@@ -52,3 +71,25 @@ configure-gba:
.PHONY: configure-gba-debug
configure-gba-debug:
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
.PHONY: loc
loc:
${BC_PY3} util/scripts/loc.py \
--search-dirs \
src \
deps/ox/src \
deps/buildcore \
deps/gbabuildcore \
deps/glutils \
deps/teagba \
--include-exts \
.cpp \
.hpp \
.py \
.s \
.cmake \
--exclude-paths \
deps/teagba/src/gba_crt0.s \
src/olympic/studio/applib/src/font.cpp \
src/olympic/studio/applib/src/font.hpp \
src/nostalgia/studio/icondata.cpp

View File

@@ -11,6 +11,7 @@
# "Python Busy Box" - adds cross-platform equivalents to Unix commands that
# don't translate well to that other operating system
import multiprocessing
import os
import platform
import shutil
@@ -57,7 +58,11 @@ def cmake_build(base_path: str, target: Optional[str]) -> int:
path = os.path.join(base_path, d)
if not os.path.isdir(path):
continue
args = ['cmake', '--build', path]
args = ['cmake', '--build', path, f'-j{multiprocessing.cpu_count()}']
if path.endswith('release'):
args.append('--config=release')
elif path.endswith('debug'):
args.append('--config=debug')
if target is not None:
args.extend(['--target', target])
err = subprocess.run(args).returncode

View File

@@ -89,7 +89,7 @@ struct GLObject: public Base {
return id;
}
constexpr operator const GLuint&() const noexcept {
constexpr operator GLuint const&() const noexcept {
return id;
}
@@ -135,7 +135,7 @@ struct FrameBuffer {
return fbo.id;
}
constexpr operator const GLuint&() const noexcept {
constexpr operator GLuint const&() const noexcept {
return fbo.id;
}
@@ -158,14 +158,14 @@ struct FrameBuffer {
class FrameBufferBind {
private:
static const FrameBuffer *s_activeFb;
const FrameBuffer *m_restoreFb = nullptr;
static FrameBuffer const *s_activeFb;
FrameBuffer const *m_restoreFb = nullptr;
public:
explicit FrameBufferBind(const FrameBuffer &fb) noexcept;
explicit FrameBufferBind(FrameBuffer const &fb) noexcept;
~FrameBufferBind() noexcept;
};
void bind(const FrameBuffer &fb) noexcept;
void bind(FrameBuffer const &fb) noexcept;
struct ShaderVarSet {
GLsizei len{};
@@ -176,7 +176,7 @@ struct ProgramSource {
ox::Vector<glutils::ShaderVarSet> const shaderParams;
GLsizei const rowLen = [this] {
GLsizei len{};
for (auto const&v : shaderParams) {
for (auto const &v : shaderParams) {
len += v.len;
}
return len;
@@ -187,23 +187,23 @@ struct ProgramSource {
ox::String const geomShader{};
};
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept;
ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept;
ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&vert,
ox::CStringView const&frag,
ox::CStringView const&geo = "") noexcept;
ox::CStringView const &vert,
ox::CStringView const &frag,
ox::CStringView const &geo = "") noexcept;
void setupShaderParams(
GLProgram const&shader,
ox::Vector<ShaderVarSet> const&vars,
GLProgram const &shader,
ox::Vector<ShaderVarSet> const &vars,
GLsizei vertexRowLen) noexcept;
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept;
void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept;
glutils::GLVertexArray generateVertexArrayObject() noexcept;
GLVertexArray generateVertexArrayObject() noexcept;
glutils::GLBuffer generateBuffer() noexcept;
GLBuffer generateBuffer() noexcept;
[[nodiscard]]
FrameBuffer generateFrameBuffer(int width, int height) noexcept;
@@ -215,20 +215,20 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
*/
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept;
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept;
struct BufferSet {
glutils::GLVertexArray vao;
glutils::GLBuffer vbo;
glutils::GLBuffer ebo;
glutils::GLTexture tex;
GLVertexArray vao;
GLBuffer vbo;
GLBuffer ebo;
GLTexture tex;
ox::Vector<float> vertices;
ox::Vector<GLuint> elements;
};
void sendVbo(BufferSet const&bs) noexcept;
void sendVbo(BufferSet const &bs) noexcept;
void sendEbo(BufferSet const&bs) noexcept;
void sendEbo(BufferSet const &bs) noexcept;
void clearScreen() noexcept;

View File

@@ -46,9 +46,9 @@ template struct GLObject<deleteVertexArray>;
template struct GLObject<deleteProgram>;
template struct GLObject<deleteShader>;
const FrameBuffer *FrameBufferBind::s_activeFb = nullptr;
FrameBuffer const *FrameBufferBind::s_activeFb = nullptr;
FrameBufferBind::FrameBufferBind(const FrameBuffer &fb) noexcept: m_restoreFb(s_activeFb) {
FrameBufferBind::FrameBufferBind(FrameBuffer const &fb) noexcept: m_restoreFb(s_activeFb) {
s_activeFb = &fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0, 0, fb.width, fb.height);
@@ -64,15 +64,15 @@ FrameBufferBind::~FrameBufferBind() noexcept {
}
}
void bind(const FrameBuffer &fb) noexcept {
void bind(FrameBuffer const &fb) noexcept {
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0, 0, fb.width, fb.height);
}
static ox::Result<GLShader> buildShader(
GLuint shaderType,
const GLchar *src,
GLuint const shaderType,
GLchar const *src,
ox::StringViewCR shaderName) noexcept {
GLShader shader(glCreateShader(shaderType));
glShaderSource(shader, 1, &src, nullptr);
@@ -88,7 +88,7 @@ static ox::Result<GLShader> buildShader(
return shader;
}
ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
ox::Result<GLProgram> buildShaderProgram(ProgramSource const &src) noexcept {
OX_REQUIRE_M(program, buildShaderProgram(
src.vertShader,
src.fragShader,
@@ -98,11 +98,11 @@ ox::Result<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept {
}
void setupShaderParams(
GLProgram const&shader,
ox::Vector<ShaderVarSet> const&vars,
GLProgram const &shader,
ox::Vector<ShaderVarSet> const &vars,
GLsizei vertexRowLen) noexcept {
// setup vars
for (size_t lenWritten = 0; auto const&v : vars) {
for (size_t lenWritten = 0; auto const &v : vars) {
auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str()));
glEnableVertexAttribArray(attr);
glVertexAttribPointer(
@@ -113,19 +113,19 @@ void setupShaderParams(
}
}
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> const&vars) noexcept {
void setupShaderParams(GLProgram const &shader, ox::Vector<ShaderVarSet> const &vars) noexcept {
// get row len
GLsizei vertexRowLen{};
for (auto const&v : vars) {
for (auto const &v : vars) {
vertexRowLen += v.len;
}
setupShaderParams(shader, vars, vertexRowLen);
}
ox::Result<GLProgram> buildShaderProgram(
ox::CStringView const&vert,
ox::CStringView const&frag,
ox::CStringView const&geo) noexcept {
ox::CStringView const &vert,
ox::CStringView const &frag,
ox::CStringView const &geo) noexcept {
GLProgram prgm(glCreateProgram());
OX_REQUIRE(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
glAttachShader(prgm, vs);
@@ -162,16 +162,30 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
// color texture
glGenTextures(1, &fb.color.id);
glBindTexture(GL_TEXTURE_2D, fb.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
nullptr);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
glFramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
// depth texture
glGenRenderbuffers(1, &fb.depth.id);
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth);
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
fb.depth);
// verify FBO
oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete");
// restore primary FB
@@ -189,7 +203,16 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// color texture
glBindTexture(GL_TEXTURE_2D, fb.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// depth texture
@@ -201,7 +224,7 @@ void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
void resizeInitFrameBuffer(FrameBuffer &fb, int const width, int const height) noexcept {
if (!fb) {
fb = generateFrameBuffer(width, height);
return;
@@ -209,18 +232,18 @@ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept {
resizeFrameBuffer(fb, width, height);
}
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const &sz) noexcept {
resizeInitFrameBuffer(fb, sz.width, sz.height);
}
void sendVbo(BufferSet const&bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
void sendVbo(BufferSet const &bs) noexcept {
auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
}
void sendEbo(BufferSet const&bs) noexcept {
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
void sendEbo(BufferSet const &bs) noexcept {
auto const bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
}

217
deps/ox/ox-docs.md vendored
View File

@@ -28,10 +28,7 @@ All components have a platform indicator next to them:
Ox provides ```ox::Error``` to report errors.
```ox::Error``` is a struct that has overloaded operators to behave like an
integer error code, plus some extra fields to enhance debuggability.
If instantiated through the ```OxError(x)``` macro, it will also include the
file and line of the error.
The ```OxError(x)``` macro should only be used for the initial instantiation of
an ```ox::Error```.
```ox::Error```s will also include the file and line of the error.
In addition to ```ox::Error``` there is also the template ```ox::Result<T>```.
```ox::Result``` simply wraps the type T value in a struct that also includes
@@ -49,7 +46,7 @@ ox::Result<int> foo(int i) noexcept {
if (i < 10) {
return i + 1; // implicitly calls ox::Result<T>::Result(T)
}
return OxError(1); // implicitly calls ox::Result<T>::Result(ox::Error)
return ox::Error(1); // implicitly calls ox::Result<T>::Result(ox::Error)
}
int caller1() {
@@ -181,6 +178,216 @@ variant for creating a non-const value.
* ```OX_REQUIRE_M``` - OX_REQUIRE Mutable
### Ox String Types
Ox has six different major string types.
These types are divided into two categories: store types and view types.
String stores maintain a copy of the string data, whereas view types only
maintain a reference to the data.
Views should be used where you otherwise might use a const reference to a
string store type.
Having all of these different string types may sound like an interoperability
nightmare, but taking string view types extensively where applicable makes the
imagined interoperability issues virtually non-existent.
#### String Store Types
##### String / BasicString
```ox::String```, or really ```ox::BasicString```, is Ox's version of
```std::string```.
Like ```std::string```, ```String``` allocates to store the string data.
Also like ```std::string```, ```String``` allows for small string
optimization for strings under 8 bytes.
Unlike ```std::string```, the template that ```String``` is based on,
```BasicString```, takes a parameter that allows adjusting to different size
small string buffers.
```ox::String``` is an alias to ```ox::BasicString<8>```.
```cpp
// s can hold up to 100 bytes, plus one for a null terminator before allocating
ox::BasicString<100> s;
```
Also unlike ```std::string```, ```ox::String``` has an explicit C-string conversion
constructor.
This prevents accidental instantiations of ```String```.
Consider the following:
```cpp
void fStd(std::string const&);
void fOx(ox::String const&);
int main() {
// implicit and silent instantiation of std::string, which includes an
// allocation
fStd("123456789");
// Will fail to compile:
fOx("123456789");
// But explicit String instantiation will work:
fOx(ox::String{"123456789"});
}
```
##### IString
```IString```, or "inline string", is like ```BasicString```, but it will cut
off strings that exceed that limit.
```cpp
ox::IString<5> s; // s can hold up to 5 characters, plus a null terminator
s = "12345"; // valid
s = "123456"; // will compile and run, but will get cut off at '5'
```
This is useful for certain string categories that have fixed lengths, like UUID
strings or for numbers.
Ox makes use of ```IString``` in the following ways:
```cpp
using UUIDStr = ox::IString<36>;
// and
template<Integer_c Integer>
[[nodiscard]]
constexpr auto intToStr(Integer v) noexcept {
constexpr auto Cap = [] {
auto out = 0;
switch (sizeof(Integer)) {
case 1:
out = 3;
break;
case 2:
out = 5;
break;
case 4:
out = 10;
break;
case 8:
out = 21;
break;
}
return out + ox::is_signed_v<Integer>;
}();
ox::IString<Cap> out;
std::ignore = out.resize(out.cap());
ox::CharBuffWriter w{{out.data(), out.cap()}};
std::ignore = writeItoa(v, w);
std::ignore = out.resize(w.tellp());
return out;
}
```
##### StringParam
```StringParam``` is a weird type.
Because ```String::String(const char*)``` is explicit, it becomes a pain for
functions to take ```String```s.
```cpp
struct Type {
ox::String m_s;
explicit Type(ox::String p): m_s(std::move(p)) {
}
};
void f() {
ox::String s{"asdf"};
Type t1{"asdf"}; // invalid - will not compile
Type t2{s}; // invalid - will not compile
Type t3{std::move(s)}; // valid
Type t4{ox::String{"asdf"}}; // valid
}
```
```StringParam``` has implicit conversion constructors, and will appropriately
move from r-value ```String```s or create a ```String``` if not passed
ownership of an existing ```String```.
Think of ```StringParam``` as a way to opt-in to implicit instantiation with
strings.
```StringParam``` can access the string as a view through the ```view()```
function, and the ```String``` inside can be accessed by moving from the
```StringParam```.
```cpp
struct Type {
ox::String m_s;
explicit Type(ox::StringParam p): m_s(std::move(p)) {
}
};
void f() {
ox::String s{"asdf"};
Type t1{"asdf"}; // valid
Type t2{s}; // valid
Type t3{std::move(s)}; // valid
Type t4{ox::String{"asdf"}}; // valid
}
```
#### String View Types
##### StringView
```ox::StringView``` is Ox's version of ```std::string_view```.
```StringView``` contains a pointer to a string, along with its size.
This should be the normal type taken when a function needs a string that will
exist until it returns.
##### CStringView
```CStringView``` is like ```StringView```, but it comes with the promise that
the string ends with a null terminator.
Accordingly, it has a ```c_str()``` function in addition to the ```data()```
function that ```StringView``` has.
```CStringView``` should be used when wrapping a C API that only takes C
strings.
##### StringLiteral
```StringLiteral``` is a string view type, but it kind of straddles the line
between view and store types.
Creating a ```StringLiteral``` is a promise that you are passing a string
literal into the constructor.
This means you can treat it like a store, that can be safely used as a copy of
the data.
Functions that take ```StringLiteral```s are allowed to assume that the data
will have no lifetime concerns and hold onto it without any need to make a
copy.
It has a consteval constructor to enforce the promise that it is a compile time
string.
```cpp
void f(ox::StringLiteral const&);
int main() {
f("123456789"); // valid
f(ox::String{"123456789"}.c_str()); // invalid - will not compile
}
```
#### Other Variants
There are a few convenience aliases as well.
* StringCR = String const&
* StringViewCR = StringView const&
* CStringViewCR = CStringView const&
* CString = const char*
String views do not generally need const references, but it does make debugging
easier, as we can skip the constructor call if a string view already exists.
These kind of aliases probably should not exist for most types, but strings are
fundamental and ease of use is desirable.
### Logging and Output
Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.

View File

@@ -15,16 +15,16 @@ ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<
ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]);
auto arg = StringView{args[i]};
if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) {
while (arg[0] == '-' && arg.size()) {
arg = substr(arg, 1);
}
m_bools[arg] = true;
// parse additional arguments
if (i < args.size() && args[i + 1]) {
auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') {
auto const val = StringView{args[i + 1]};
if (val.size() && val[0] != '-') {
if (val == "false") {
m_bools[arg] = false;
}
@@ -40,17 +40,17 @@ ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
}
bool ClArgs::getBool(ox::StringViewCR arg, bool defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg);
auto const [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue;
}
String ClArgs::getString(ox::StringViewCR arg, ox::StringView defaultValue) const noexcept {
auto [value, err] = m_strings.at(arg);
auto const [value, err] = m_strings.at(arg);
return !err ? ox::String(*value) : ox::String(defaultValue);
}
int ClArgs::getInt(ox::StringViewCR arg, int defaultValue) const noexcept {
auto [value, err] = m_ints.at(arg);
auto const [value, err] = m_ints.at(arg);
return !err ? *value : defaultValue;
}

View File

@@ -109,7 +109,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader",
[] {
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
@@ -121,7 +121,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader2",
[] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.size() + 1});
oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
@@ -134,7 +134,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
OX_REQUIRE(actual, ox::readClawTypeId({hdr.data(), hdr.size() + 1}));
oxExpect(actual, expected);
return ox::Error{};
}

View File

@@ -39,7 +39,7 @@ struct TypeInfoCatcher {
}
constexpr Error field(...) noexcept {
return ox::Error(0);
return {};
}
static constexpr auto opType() {

View File

@@ -218,7 +218,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) {
f->call(args...);
}
return ox::Error(0);
return {};
} catch (const ox::Exception &ex) {
return ox::Error(ex.errCode, ex.msg, ex.src);
}
@@ -410,7 +410,7 @@ Error Signal<Error(Args...)>::emitCheckError(Args... args) const noexcept {
for (auto &f : m_slots) {
OX_RETURN_ERROR(f->call(ox::forward<Args>(args)...));
}
return ox::Error(0);
return {};
}
}

View File

@@ -230,7 +230,7 @@ template<typename size_t>
Error FileStoreTemplate<size_t>::incLinks(uint64_t id) {
OX_REQUIRE_M(item, find(static_cast<size_t>(id)).validate());
++item->links;
return ox::Error(0);
return {};
}
template<typename size_t>
@@ -240,7 +240,7 @@ Error FileStoreTemplate<size_t>::decLinks(uint64_t id) {
if (item->links == 0) {
OX_RETURN_ERROR(remove(item));
}
return ox::Error(0);
return {};
}
template<typename size_t>
@@ -298,7 +298,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
dest->id.get(), dest.offset(), destData.size());
fsData->rootNode = dest.offset();
oxTracef("ox.fs.FileStoreTemplate.write", "Root inode: {}", dest->id.get());
return ox::Error(0);
return {};
}
} else {
oxTrace("ox.fs.FileStoreTemplate.write.fail", "Could not place item due to absence of FileStore header.");
@@ -427,7 +427,7 @@ Error FileStoreTemplate<size_t>::resize() {
oxTracef("ox.fs.FileStoreTemplate.resize", "resize to: {}", newSize);
OX_RETURN_ERROR(m_buffer->setSize(newSize));
oxTracef("ox.fs.FileStoreTemplate.resize", "resized to: {}", m_buffer->size());
return ox::Error(0);
return {};
}
template<typename size_t>
@@ -479,7 +479,7 @@ Error FileStoreTemplate<size_t>::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) {
for (auto i = m_buffer->iterator(); i.valid(); i.next()) {
OX_RETURN_ERROR(cb(i->fileType, i.ptr().offset(), i.ptr().end()));
}
return ox::Error(0);
return {};
}
template<typename size_t>
@@ -503,7 +503,7 @@ Error FileStoreTemplate<size_t>::compact() {
return m_buffer->compact([this, &isFirstItem](uint64_t oldAddr, ItemPtr item) -> Error {
if (isFirstItem) {
isFirstItem = false;
return ox::Error(0);
return {};
}
if (!item.valid()) {
return ox::Error(1);
@@ -524,7 +524,7 @@ Error FileStoreTemplate<size_t>::compact() {
parent->right = item;
}
}
return ox::Error(0);
return {};
});
}
@@ -552,7 +552,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr item) {
item->left = root->left;
item->right = root->right;
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Overwrote Root Item: {}", item->id.get());
return ox::Error(0);
return {};
} else {
return placeItem(root, item);
}
@@ -573,7 +573,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = right->right;
}
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return ox::Error(0);
return {};
} else {
return placeItem(right, item, depth + 1);
}
@@ -586,7 +586,7 @@ Error FileStoreTemplate<size_t>::placeItem(ItemPtr root, ItemPtr item, int depth
item->right = left->right;
}
oxTracef("ox.fs.FileStoreTemplate.placeItem", "Placed Item: {}", item->id.get());
return ox::Error(0);
return {};
} else {
return placeItem(left, item, depth + 1);
}
@@ -624,7 +624,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr item) {
} else {
fsData->rootNode = 0;
}
return ox::Error(0);
return {};
} else {
return unplaceItem(root, item);
}
@@ -661,7 +661,7 @@ Error FileStoreTemplate<size_t>::unplaceItem(ItemPtr root, ItemPtr item, int dep
if (item->left) {
OX_RETURN_ERROR(placeItem(m_buffer->ptr(item->left)));
}
return ox::Error(0);
return {};
}
template<typename size_t>
@@ -669,7 +669,7 @@ Error FileStoreTemplate<size_t>::remove(ItemPtr item) {
if (item.valid()) {
OX_RETURN_ERROR(unplaceItem(item));
OX_RETURN_ERROR(m_buffer->free(item));
return ox::Error(0);
return {};
}
return ox::Error(1);
}

View File

@@ -52,7 +52,7 @@ struct OX_PACKED DirectoryEntry {
if (d.valid()) {
d->inode = inode;
auto const maxStrSz = bufferSize - 1 - sizeof(*this);
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.len()));
ox::strncpy(d->name, name.data(), ox::min(maxStrSz, name.size()));
return {};
}
return ox::Error(1);
@@ -219,7 +219,7 @@ Error Directory<FileStore, InodeId_t>::write(PathIterator path, uint64_t inode64
oxTrace("ox.fs.Directory.write.fail", "Could not read existing version of Directory");
return ox::Error(1, "Could not read existing version of Directory");
}
const auto pathSize = name.len() + 1;
const auto pathSize = name.size() + 1;
const auto entryDataSize = DirectoryEntry<InodeId_t>::DirectoryEntryData::spaceNeeded(pathSize);
const auto newSize = oldStat.size + Buffer::spaceNeeded(entryDataSize);
auto cpy = ox_malloca(newSize, Buffer, *old, oldStat.size);

View File

@@ -24,9 +24,6 @@ enum class FileAddressType: int8_t {
Inode,
};
template<typename T>
constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept;
class FileAddress {
template<typename T>

View File

@@ -87,7 +87,7 @@ class FileSystem {
return writeFilePath(path, buffer, size, FileType::NormalFile);
}
Error write(StringViewCR path, ox::Span<char> const&buff) noexcept {
Error write(StringViewCR path, ox::SpanView<char> const&buff) noexcept {
return write(path, buff.data(), buff.size(), FileType::NormalFile);
}
@@ -95,7 +95,7 @@ class FileSystem {
return write(inode, buffer, size, FileType::NormalFile);
}
Error write(uint64_t inode, ox::Span<char> const&buff) noexcept {
Error write(uint64_t inode, ox::SpanView<char> const&buff) noexcept {
return write(inode, buff.data(), buff.size(), FileType::NormalFile);
}
@@ -329,7 +329,7 @@ Error FileSystemTemplate<FileStore, Directory>::format(void *buff, uint64_t buff
return ox::Error(1);
}
return ox::Error(0);
return {};
}
template<typename FileStore, typename Directory>
@@ -346,7 +346,7 @@ Error FileSystemTemplate<FileStore, Directory>::move(StringViewCR src, StringVie
OX_REQUIRE_M(inode, rootDir.find(src));
OX_RETURN_ERROR(rootDir.write(dest, inode));
OX_RETURN_ERROR(rootDir.remove(src));
return ox::Error(0);
return {};
}
template<typename FileStore, typename Directory>
@@ -407,7 +407,7 @@ Error FileSystemTemplate<FileStore, Directory>::removePath(StringViewCR path, bo
oxTrace("FileSystemTemplate.remove.fail", "Tried to remove directory without recursive setting.");
return ox::Error(1);
}
return ox::Error(0);
return {};
}
template<typename FileStore, typename Directory>
@@ -424,7 +424,7 @@ Result<Vector<String>> FileSystemTemplate<FileStore, Directory>::ls(StringViewCR
Vector<String> out;
OX_RETURN_ERROR(ls(path, [&out](StringViewCR name, typename FileStore::InodeId_t) {
out.emplace_back(name);
return ox::Error(0);
return ox::Error{};
}));
return out;
}

View File

@@ -60,7 +60,7 @@ Error PassThroughFS::move(StringViewCR src, StringViewCR dest) noexcept {
if (ec.value()) {
return ox::Error(1);
}
return ox::Error(0);
return {};
}
Result<Vector<String>> PassThroughFS::ls(StringViewCR dir) const noexcept {
@@ -148,7 +148,7 @@ Error PassThroughFS::readFilePath(StringViewCR path, void *buffer, std::size_t b
oxTracef("ox.fs.PassThroughFS.read.error", "Read of {} failed: {}", path, f.what());
return ox::Error(2);
}
return ox::Error(0);
return {};
}
Error PassThroughFS::readFileInode(uint64_t, void*, std::size_t) noexcept {
@@ -197,7 +197,7 @@ Error PassThroughFS::writeFilePath(StringViewCR path, const void *buffer, uint64
oxTracef("ox.fs.PassThroughFS.read.error", "Write of {} failed: {}", path, f.what());
return ox::Error(1);
}
return ox::Error(0);
return {};
}
Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) noexcept {
@@ -206,7 +206,7 @@ Error PassThroughFS::writeFileInode(uint64_t, const void*, uint64_t, FileType) n
}
std::string_view PassThroughFS::stripSlash(StringView path) noexcept {
for (auto i = 0u; i < path.len() && path[0] == '/'; i++) {
for (auto i = 0u; i < path.size() && path[0] == '/'; i++) {
path = substr(path, 1);
}
return {path.data(), path.bytes()};

View File

@@ -99,7 +99,7 @@ Error PassThroughFS::ls(StringViewCR dir, F cb) const noexcept {
for (auto &p : di) {
OX_RETURN_ERROR(cb(p.path().filename().c_str(), 0));
}
return ox::Error(0);
return {};
}
}

View File

@@ -36,7 +36,7 @@ Error PathIterator::dirPath(char *out, std::size_t outSize) {
if (idx >= 0 && size < outSize) {
ox::memcpy(out, m_path, size);
out[size] = 0;
return ox::Error(0);
return {};
} else {
return ox::Error(1);
}
@@ -74,7 +74,7 @@ Error PathIterator::get(StringView &fileName) {
if (size && fileName[size - 1] == '/') {
fileName = ox::substr(m_path, start, start + size - 1);
}
oxAssert(fileName[fileName.len()-1] != '/', "name ends in /");
oxAssert(fileName[fileName.size()-1] != '/', "name ends in /");
return {};
}
@@ -85,7 +85,7 @@ Error PathIterator::next(StringView &fileName) {
std::size_t size = 0;
auto retval = ox::Error(1);
if (m_iterator < m_maxSize && ox::strlen(&m_path[m_iterator])) {
retval = ox::Error(0);
retval = {};
if (m_path[m_iterator] == '/') {
m_iterator++;
}
@@ -104,11 +104,11 @@ Error PathIterator::next(StringView &fileName) {
}
fileName = ox::substr(m_path, start, start + size);
// truncate trailing /
while (fileName.len() && fileName[fileName.len() - 1] == '/') {
while (fileName.size() && fileName[fileName.size() - 1] == '/') {
fileName = ox::substr(m_path, start, start + size);
}
m_iterator += size;
oxAssert(fileName.len() == 0 || fileName[fileName.len()-1] != '/', "name ends in /");
oxAssert(fileName.size() == 0 || fileName[fileName.size()-1] != '/', "name ends in /");
}
return retval;
}
@@ -118,7 +118,7 @@ Result<std::size_t> PathIterator::nextSize() const {
auto retval = ox::Error(1);
auto it = m_iterator;
if (it < m_maxSize && ox::strlen(&m_path[it])) {
retval = ox::Error(0);
retval = {};
if (m_path[it] == '/') {
it++;
}

View File

@@ -354,7 +354,7 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) noexcept {
}
}
m_header.bytesUsed -= item.size();
return ox::Error(0);
return {};
}
template<typename size_t, typename Item>
@@ -370,7 +370,7 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end;
ox::memset(data, 0, size - end);
return ox::Error(0);
return {};
}
}
@@ -422,7 +422,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
src = ptr(dest->next);
dest = uninitializedPtr(dest.offset() + dest->fullSize());
}
return ox::Error(0);
return {};
}
template<typename size_t, typename Item>

View File

@@ -59,7 +59,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next1",
[](ox::StringView) {
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
@@ -84,7 +84,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next3",
[](ox::StringView) {
auto const path = ox::String("/");
ox::PathIterator it(path.c_str(), path.len());
ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "\0", "PathIterator shows wrong next");
return ox::Error(0);
@@ -106,7 +106,7 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::next5",
[](ox::StringView) {
auto const path = ox::String("usr/share/");
ox::PathIterator it(path.c_str(), path.len());
ox::PathIterator it(path.c_str(), path.size());
ox::StringView buff;
oxAssert(it.next(buff) == 0 && buff == "usr", "PathIterator shows wrong next");
oxAssert(it.next(buff) == 0 && buff == "share", "PathIterator shows wrong next");
@@ -117,10 +117,10 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
"PathIterator::dirPath",
[] (ox::StringView) {
auto constexpr path = ox::StringLiteral("/usr/share/charset.gbag");
ox::PathIterator it(path.c_str(), path.len());
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
ox::PathIterator it(path.c_str(), path.size());
auto buff = static_cast<char*>(ox_alloca(path.size() + 1));
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
oxAssert(it.dirPath(buff, path.len()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
oxAssert(it.dirPath(buff, path.size()) == 0 && ox::strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(0);
}

View File

@@ -48,7 +48,7 @@ static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept
for (const auto &file : files) {
oxOutf("{}\n", file);
}
return ox::Error(0);
return {};
}
static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
@@ -60,7 +60,7 @@ static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcep
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
std::ignore = fwrite(buff.data(), sizeof(decltype(buff)::value_type), buff.size(), stdout);
OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(0);
return {};
}
static ox::Error run(int argc, const char **argv) noexcept {

View File

@@ -91,23 +91,28 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
}
void LoggerConn::msgSend() noexcept {
while (true) {
std::unique_lock lk(m_waitMut);
m_waitCond.wait(lk);
if (!m_running) {
break;
}
std::lock_guard const buffLk(m_buffMut);
try {
while (true) {
Array<char, units::KB> tmp;
const auto read = m_buff.read(tmp.data(), tmp.size());
if (!read) {
std::unique_lock lk(m_waitMut);
m_waitCond.wait(lk);
if (!m_running) {
break;
}
oxAssert(read <= tmp.size(), "logger trying to read too much data");
//std::printf("LoggerConn: sending %lu bytes\n", read);
std::ignore = send(tmp.data(), read);
std::lock_guard const buffLk(m_buffMut);
while (true) {
Array<char, units::KB> tmp;
const auto read = m_buff.read(tmp.data(), tmp.size());
if (!read) {
break;
}
oxAssert(read <= tmp.size(), "logger trying to read too much data");
//std::printf("LoggerConn: sending %lu bytes\n", read);
std::ignore = send(tmp.data(), read);
}
}
} catch (std::exception const &e) {
oxErrf("Exception in logger thread: {}\n", e.what());
oxAssert(false, "logger thread exception");
}
}

View File

@@ -197,7 +197,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) n
OX_RETURN_ERROR(result);
}
++m_field;
return ox::Error(0);
return {};
}
// array handler
@@ -256,7 +256,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<Stri
}
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -330,7 +330,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<
}
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -370,7 +370,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
data[size] = 0;
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -388,7 +388,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
data[size] = 0;
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -416,7 +416,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char
}
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -464,7 +464,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
}
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>
@@ -487,7 +487,7 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexc
}
}
++m_field;
return ox::Error(0);
return {};
}
template<Reader_c Reader>

View File

@@ -157,7 +157,6 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch");
oxDebugf("{}", testOut.IString.len());
oxExpect(testIn.IString, testOut.IString);
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");

View File

@@ -122,7 +122,7 @@ class MetalClawWriter {
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
};
@@ -184,30 +184,30 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noe
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
}
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>
template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
bool fieldSet = false;
if (val->len() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length
const auto strLen = mc::encodeInteger(val->len());
const auto strLen = mc::encodeInteger(val->size());
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length));
// write the string
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->size())));
fieldSet = true;
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>
template<std::size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept {
return fieldCString(name, val->data(), val->len());
return fieldCString(name, val->data(), val->size());
}
template<Writer_c Writer>
@@ -229,7 +229,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *c
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>
@@ -255,7 +255,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>
@@ -319,7 +319,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>
@@ -339,7 +339,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
const auto keyLen = key.len();
const auto keyLen = key.size();
auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1);
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
@@ -356,7 +356,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
}
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field;
return ox::Error(0);
return {};
}
template<Writer_c Writer>

View File

@@ -13,7 +13,7 @@
// oxModelFwdDecl is necessary because Apple-Clang is broken...
#define OX_MODEL_FWD_DECL(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept
#define OX_MODEL_BEGIN(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith<modelName> auto *o) noexcept { OX_RETURN_ERROR(io->template setTypeInfo<modelName>());
#define OX_MODEL_END() return ox::Error(0); }
#define OX_MODEL_END() return {}; }
#define OX_MODEL_FIELD(fieldName) OX_RETURN_ERROR(io->field(#fieldName, &o->fieldName));
#define OX_MODEL_FIELD_RENAME(objFieldName, serFieldName) OX_RETURN_ERROR(io->field(#serFieldName, &o->objFieldName));
#define OX_MODEL_FRIEND(modelName) friend constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept

View File

@@ -43,7 +43,7 @@ static constexpr auto buildTypeId(
for (const auto &p : typeParams) {
tp += p + ",";
}
tp.resize(tp.len() - 1);
tp.resize(tp.size() - 1);
tp += "#";
}
return ox::sfmt("{}{};{}", name, tp, version);
@@ -244,7 +244,7 @@ constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto
// defaultValue is unused now, but placeholder for backwards compatibility
int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue));
return ox::Error(0);
return {};
}
#endif

View File

@@ -187,7 +187,7 @@ constexpr ox::Error TypeDescWriter::setTypeInfo(
PrimitiveType pt;
if constexpr(is_union_v<T>) {
pt = PrimitiveType::Union;
} else if constexpr(isBasicString_v<T> || isBString_v<T>) {
} else if constexpr(isBasicString_v<T> || isIString_v<T>) {
pt = PrimitiveType::String;
} else {
pt = PrimitiveType::Struct;
@@ -205,7 +205,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t,
const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
return ox::Error(0);
return {};
}
return ox::Error(1);
}
@@ -220,7 +220,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t)
auto const lvls = detail::indirectionLevels_v<T> + 1;
SubscriptStack subscriptStack{lvls};
m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t));
return ox::Error(0);
return {};
}
return ox::Error(1);
}
@@ -231,7 +231,7 @@ constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> val
const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return ox::Error(0);
return {};
}
return ox::Error(1);
}
@@ -357,7 +357,7 @@ constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept
template<std::size_t sz>
constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept {
constexpr auto PT = PrimitiveType::String;
return getType(types::BString, 0, PT, 0);
return getType(types::IString, 0, PT, 0);
}
constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b,

View File

@@ -31,25 +31,25 @@ class FieldCounter {
template<typename U>
constexpr ox::Error field(StringViewCR, U) noexcept {
++fields;
return ox::Error(0);
return {};
}
template<typename U>
constexpr ox::Error field(StringViewCR, U, std::size_t) noexcept {
++fields;
return ox::Error(0);
return {};
}
template<typename U, typename Handler>
constexpr Error field(StringViewCR, Handler) {
++fields;
return ox::Error(0);
return {};
}
template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept {
++fields;
return ox::Error(0);
return {};
}
static constexpr auto opType() noexcept {

View File

@@ -135,7 +135,7 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>());
}
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(ox::Error(1), "invalid type");
ox::panic(ox::Error(1), "invalid type");
return ox::Error(1, "invalid type");
}

View File

@@ -56,19 +56,19 @@ class MemberList {
template<typename T>
constexpr Error field(const char*, T *v) noexcept {
vars[m_i++] = static_cast<void*>(v);
return ox::Error(0);
return {};
}
template<typename T>
constexpr Error field(const char*, T *v, int) noexcept {
vars[m_i++] = static_cast<void*>(v);
return ox::Error(0);
return {};
}
template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
vars[m_i++] = static_cast<void*>(u.get());
return ox::Error(0);
return {};
}
template<typename T>
@@ -107,7 +107,7 @@ class Copier {
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
dst = src;
++m_i;
return ox::Error(0);
return {};
}
}
@@ -119,7 +119,7 @@ class Copier {
dst = src;
}
++m_i;
return ox::Error(0);
return {};
}
template<typename U, bool force = false>
@@ -128,7 +128,7 @@ class Copier {
auto &src = *u.get();
dst = src;
++m_i;
return ox::Error(0);
return {};
}
template<typename T = void>
@@ -168,7 +168,7 @@ class Mover {
dst = std::move(src);
src = FT{};
++m_i;
return ox::Error(0);
return {};
}
}
@@ -181,7 +181,7 @@ class Mover {
src = FT{};
}
++m_i;
return ox::Error(0);
return {};
}
template<typename U, bool force = false>
@@ -190,7 +190,7 @@ class Mover {
auto &src = *u.get();
dst = std::move(src);
++m_i;
return ox::Error(0);
return {};
}
template<typename T = void>
@@ -228,7 +228,7 @@ class Equals {
const auto &dst = std::bit_cast<FT>(*m_other->vars[m_i]);
++m_i;
if (dst == src) {
return ox::Error(0);
return {};
} else {
this->value = false;
return ox::Error(1);
@@ -246,7 +246,7 @@ class Equals {
}
}
++m_i;
return ox::Error(0);
return {};
}
template<typename U, bool force = false>
@@ -255,7 +255,7 @@ class Equals {
const auto &src = *u.get();
++m_i;
if (dst == src) {
return ox::Error(0);
return {};
} else {
this->value = false;
return ox::Error(1);

View File

@@ -18,6 +18,9 @@ static_assert([]() -> ox::Error {
}
//oxReturnError(v.set<int32_t>(5));
return {};
}() == ox::Error(0));
}() == ox::Error{});
// a dummy function to prevent linker errors in a library that has no other symbols
void modelDummyFunc() noexcept {}
}

View File

@@ -100,7 +100,7 @@ class ModelValue {
return Type::Union;
} else if constexpr(is_same_v<U, ModelObject>) {
return Type::Object;
} else if constexpr(isBasicString_v<U> || isBString_v<U>) {
} else if constexpr(isBasicString_v<U> || isIString_v<U>) {
return Type::String;
} else if constexpr(is_same_v<U, ModelValueVector>) {
return Type::Vector;
@@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast");
ox::panic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}
@@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast");
ox::panic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}
@@ -187,7 +187,7 @@ class ModelValue {
constexpr Type type() const noexcept;
constexpr Error setType(
DescriptorType const*type,
DescriptorType const *type,
SubscriptStack const& = {},
int subscriptLevels = 0) noexcept;
@@ -275,7 +275,7 @@ class ModelValueArray {
}
constexpr Error setType(
DescriptorType const*type,
DescriptorType const *type,
SubscriptStack subscriptStack,
int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
@@ -418,7 +418,7 @@ class ModelValueVector {
}
constexpr Error setType(
DescriptorType const*type,
DescriptorType const *type,
SubscriptStack subscriptStack,
int subscriptLevels) noexcept {
oxAssert(subscriptLevels <= static_cast<int>(subscriptStack.size()), "subscript level mismatch");
@@ -821,7 +821,7 @@ class ModelUnion {
template<typename PlatSpec>
[[nodiscard]]
constexpr std::size_t sizeOf(ModelValueArray const*v) noexcept {
constexpr std::size_t sizeOf(ModelValueArray const *v) noexcept {
return sizeOf<PlatSpec>(&(*v)[0]) * v->size();
}
@@ -972,7 +972,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
for (auto &f : obj->m_fieldsOrder) {
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
}
return ox::Error(0);
return {};
}
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
@@ -981,7 +981,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
for (auto &f : obj->m_fieldsOrder) {
OX_RETURN_ERROR(h->field(f->name.c_str(), &f->value));
}
return ox::Error(0);
return {};
}
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
@@ -1098,7 +1098,7 @@ constexpr Error ModelValue::setType(
} else if (type->typeName == types::Bool) {
m_type = Type::Bool;
} else if (type->typeName == types::BasicString ||
type->typeName == types::BString ||
type->typeName == types::IString ||
type->typeName == types::String) {
m_type = Type::String;
m_data.str = new String;
@@ -1129,7 +1129,7 @@ constexpr Error ModelValue::setType(
OX_RETURN_ERROR(m_data.uni->setType(type));
}
oxAssert(m_type != Type::Undefined, "No type set");
return ox::Error(0);
return {};
}
template<typename T>
@@ -1184,7 +1184,7 @@ constexpr Error ModelValue::set(const T &v) noexcept {
safeDelete(&value);
}
value = v;
return ox::Error(0);
return {};
}
template<typename T>
@@ -1199,7 +1199,7 @@ constexpr Error ModelValue::set(T &&v) noexcept {
safeDelete(&value);
}
value = std::move(v);
return ox::Error(0);
return {};
}
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {

View File

@@ -38,17 +38,17 @@ struct TypeNameCatcher {
template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept {
return ox::Error(0);
return {};
}
template<typename T>
constexpr Error field(const char*, T) noexcept {
return ox::Error(0);
return {};
}
template<typename ...Args>
constexpr Error fieldCString(Args&&...) noexcept {
return ox::Error(0);
return {};
}
static constexpr auto opType() noexcept {
@@ -77,17 +77,17 @@ struct TypeInfoCatcher {
template<typename T>
constexpr Error field(const char*, T*, std::size_t) noexcept {
return ox::Error(0);
return {};
}
template<typename T>
constexpr Error field(const char*, T) noexcept {
return ox::Error(0);
return {};
}
template<typename T>
constexpr Error fieldCString(const char*, T) noexcept {
return ox::Error(0);
return {};
}
static constexpr auto opType() noexcept {
@@ -144,7 +144,7 @@ template<typename T, typename Str = const char*>
[[nodiscard]]
consteval auto requireModelTypeName() noexcept {
constexpr auto name = getModelTypeName<T, Str>();
static_assert(ox::StringView{name}.len(), "Type lacks required TypeName");
static_assert(ox::StringView{name}.size(), "Type lacks required TypeName");
return name;
}
@@ -159,7 +159,7 @@ constexpr auto ModelTypeId_v = [] {
constexpr auto name = ModelTypeName_v<T, ox::StringView>;
constexpr auto version = ModelTypeVersion_v<T>;
constexpr auto versionStr = ox::sfmt<ox::IString<19>>("{}", version);
return ox::sfmt<ox::IString<name.len() + versionStr.len() + 1>>("{};{}", name, versionStr);
return ox::sfmt<ox::IString<name.size() + versionStr.size() + 1>>("{};{}", name, versionStr);
}();
}

View File

@@ -31,18 +31,18 @@
namespace ox {
namespace types {
constexpr StringView BasicString = "net.drinkingtea.ox.BasicString";
constexpr StringView BString = "net.drinkingtea.ox.BString";
constexpr StringView String = "B.string";
constexpr StringView Bool = "B.bool";
constexpr StringView Uint8 = "B.uint8";
constexpr StringView Uint16 = "B.uint16";
constexpr StringView Uint32 = "B.uint32";
constexpr StringView Uint64 = "B.uint64";
constexpr StringView Int8 = "B.int8";
constexpr StringView Int16 = "B.int16";
constexpr StringView Int32 = "B.int32";
constexpr StringView Int64 = "B.int64";
constexpr StringLiteral BasicString = "net.drinkingtea.ox.BasicString";
constexpr StringLiteral IString = "net.drinkingtea.ox.IString";
constexpr StringLiteral String = "B.string";
constexpr StringLiteral Bool = "B.bool";
constexpr StringLiteral Uint8 = "B.uint8";
constexpr StringLiteral Uint16 = "B.uint16";
constexpr StringLiteral Uint32 = "B.uint32";
constexpr StringLiteral Uint64 = "B.uint64";
constexpr StringLiteral Int8 = "B.int8";
constexpr StringLiteral Int16 = "B.int16";
constexpr StringLiteral Int32 = "B.int32";
constexpr StringLiteral Int64 = "B.int64";
}
template<typename T>
@@ -63,17 +63,17 @@ static_assert(isBasicString_v<ox::BasicString<8ul>>);
static_assert(isBasicString_v<ox::String>);
template<typename T>
consteval bool isBString(const T*) noexcept {
consteval bool isIString(const T*) noexcept {
return false;
}
template<std::size_t SmallVecSize>
consteval bool isBString(const BasicString<SmallVecSize>*) noexcept {
consteval bool isIString(const BasicString<SmallVecSize>*) noexcept {
return true;
}
template<typename T>
constexpr bool isBString_v = isBasicString(static_cast<const T*>(nullptr));
constexpr bool isIString_v = isIString(static_cast<const T*>(nullptr));
static_assert(isBasicString_v<ox::BasicString<0ul>>);
static_assert(isBasicString_v<ox::BasicString<8ul>>);
@@ -169,12 +169,12 @@ constexpr bool isSmartPtr_v<::std::unique_ptr<T>> = true;
#endif
template<typename Union, bool force = false>
template<typename Union, bool force = false> requires(force || is_union_v<Union>)
class UnionView {
protected:
int m_idx = -1;
typename enable_if<is_union_v<Union> || force, Union>::type *m_union = nullptr;
Union *m_union = nullptr;
public:
constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {

View File

@@ -127,7 +127,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
}
}
walker->popNamePath();
return ox::Error(0);
return {};
}
template<typename Reader, typename FH>
@@ -141,7 +141,7 @@ constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
for (const auto &field : fields) {
OX_RETURN_ERROR(parseField(field, rdr, walker));
}
return ox::Error(0);
return {};
}
template<typename Reader, typename Handler>

View File

@@ -37,7 +37,7 @@ OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
}
Error OrganicClawReader::field(const char *key, bool *val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@@ -53,7 +53,7 @@ Error OrganicClawReader::field(const char *key, bool *val) noexcept {
}
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = ox::Error(0);
ox::Error err{};
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {
@@ -81,7 +81,7 @@ Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t bu
}
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
auto &data = *val;
@@ -106,7 +106,7 @@ Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
}
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
auto err = ox::Error(0);
ox::Error err{};
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {

View File

@@ -137,7 +137,7 @@ class OrganicClawReader {
template<typename T>
Error OrganicClawReader::field(const char *key, T *val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
try {
if constexpr (is_integer_v<T>) {
if (targetValid()) {
@@ -181,7 +181,6 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
}
}
} catch (Json::LogicError const&e) {
oxDebugf("JSON error: {}", e.what());
err = ox::Error(1, "error reading JSON data");
}
++m_fieldIt;
@@ -190,7 +189,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
@@ -207,7 +206,7 @@ Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcep
template<std::size_t L>
Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@@ -224,7 +223,7 @@ Error OrganicClawReader::field(const char *key, BasicString<L> *val) noexcept {
template<std::size_t L>
Error OrganicClawReader::field(const char *key, IString<L> *val) noexcept {
auto err = ox::Error(0);
ox::Error err{};
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty()) {
@@ -257,7 +256,7 @@ OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
}
return ox::Error(0);
return {};
}
template<typename T>
@@ -274,7 +273,7 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
const auto k = keys[i].c_str();
OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
}
return ox::Error(0);
return {};
}
Error readOC(BufferView buff, auto &val) noexcept {
@@ -307,7 +306,7 @@ Result<T> readOC(BufferView buff) noexcept {
template<typename T>
Result<T> readOC(ox::StringView json) noexcept {
return readOC<T>(ox::BufferView{json.data(), json.len()});
return readOC<T>(ox::BufferView{json.data(), json.size()});
}
}

View File

@@ -23,7 +23,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
@@ -32,7 +32,7 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) no
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept {
const auto uuidStr = uuid->toString();
if (targetValid() && uuidStr.len()) {
if (targetValid() && uuidStr.size()) {
value(key) = uuidStr.c_str();
}
++m_fieldIt;

View File

@@ -46,7 +46,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const int16_t *val) noexcept {
@@ -54,7 +54,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const int32_t *val) noexcept {
@@ -62,7 +62,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const int64_t *val) noexcept {
@@ -70,7 +70,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
@@ -79,7 +79,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const uint16_t *val) noexcept {
@@ -87,7 +87,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const uint32_t *val) noexcept {
@@ -95,7 +95,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(const char *key, const uint64_t *val) noexcept {
@@ -103,7 +103,7 @@ class OrganicClawWriter {
value(key) = *val;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error field(char const*key, bool const*val) noexcept {
@@ -138,7 +138,7 @@ class OrganicClawWriter {
template<std::size_t L>
Error field(char const*key, IString<L> const*val) noexcept {
if (targetValid() && val->len()) {
if (targetValid() && val->size()) {
value(key) = val->c_str();
}
++m_fieldIt;
@@ -147,11 +147,11 @@ class OrganicClawWriter {
template<std::size_t L>
Error field(char const*key, BasicString<L> const*val) noexcept {
if (targetValid() && val->len()) {
if (targetValid() && val->size()) {
value(key) = val->c_str();
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Error fieldCString(const char*, const char *const*val, int len) noexcept;
@@ -211,7 +211,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END
value(key) = w.m_json;
}
++m_fieldIt;
return ox::Error(0);
return {};
}
template<typename T>
@@ -237,7 +237,7 @@ Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
}
}
++m_fieldIt;
return ox::Error(0);
return {};
}
template<typename U, bool force>
@@ -251,7 +251,7 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
}
}
++m_fieldIt;
return ox::Error(0);
return {};
}
Result<ox::Buffer> writeOC(const auto &val) noexcept {

View File

@@ -181,13 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
boundsCheck(i, size(), "Array access overflow");
return m_items[i];
}
template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
boundsCheck(i, size(), "Array access overflow");
return m_items[i];
}

View File

@@ -15,8 +15,8 @@
namespace ox {
void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
void panic(Error const &err, StringViewCR panicMsg, std::source_location const &src) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", src.file_name(), src.line(), panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
@@ -26,41 +26,61 @@ void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const
}
#ifdef OX_USE_STDLIB
printStackTrace(2);
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << file << ":" << line << ")";
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << src.file_name() << ":" << src.line() << ")";
std::abort();
#else
while (1);
#endif
}
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
#if __GNUC__ && !_WIN32
__attribute__((weak))
#endif
void panic(Error const &err, char const*panicMsg, std::source_location const &src) noexcept {
panic(err, StringView{panicMsg}, src);
}
void assertFailFuncRuntime(
StringViewCR file,
int const line,
StringViewCR assertTxt,
StringViewCR msg) noexcept {
StringViewCR msg,
std::source_location const &src) noexcept {
#ifdef OX_USE_STDLIB
auto const st = genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st);
oxTracef(
"assert", "Failed assert: {} ({}) [{}:{}]:\n{}",
msg,
assertTxt,
src.file_name(),
src.line(),
st);
abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
oxErrf(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
msg);
oxTracef(
"assert", "Failed assert: {} ({}) [{}:{}]",
msg,
assertTxt,
src.file_name(),
src.line());
constexprPanic(msg, {}, src);
#endif
}
void assertFailFuncRuntime(
StringViewCR file,
int const line,
[[maybe_unused]] Error const&err,
[[maybe_unused]] Error const &err,
StringViewCR,
StringViewCR assertMsg) noexcept {
StringViewCR assertMsg,
std::source_location const &src) noexcept {
#if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
auto msg = sfmt(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
@@ -70,10 +90,10 @@ void assertFailFuncRuntime(
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, src.file_name(), src.line());
abort();
#else
constexprPanic(file, line, assertMsg);
constexprPanic(assertMsg, {}, src);
#endif
}

View File

@@ -23,42 +23,42 @@
namespace ox {
[[noreturn]]
void panic(StringViewCR file, int line, StringViewCR panicMsg, Error const&err = {}) noexcept;
void panic(
Error const&err,
StringViewCR panicMsg,
std::source_location const &src = std::source_location::current()) noexcept;
[[noreturn]]
constexpr void constexprPanic(
StringViewCR file,
int const line,
StringViewCR panicMsg,
Error const&err = {}) noexcept {
Error const &err = {},
std::source_location const &src = std::source_location::current()) noexcept {
if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err);
panic(err, panicMsg, src);
} else {
while (true);
}
}
void assertFailFuncRuntime(
StringViewCR file,
int line,
StringViewCR assertTxt,
StringViewCR msg) noexcept;
StringViewCR msg,
std::source_location const &src = std::source_location::current()) noexcept;
void assertFailFuncRuntime(
StringViewCR file,
int line,
Error const&err,
Error const &err,
StringViewCR,
StringViewCR assertMsg) noexcept;
StringViewCR assertMsg,
std::source_location const &src = std::source_location::current()) noexcept;
constexpr void assertFunc(
StringViewCR file,
int const line,
bool const pass,
[[maybe_unused]]StringViewCR assertTxt,
[[maybe_unused]]StringViewCR msg) noexcept {
[[maybe_unused]]StringViewCR msg,
std::source_location const &src = std::source_location::current()) noexcept {
if (!pass) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, assertTxt, msg);
assertFailFuncRuntime(assertTxt, msg, src);
} else {
while (true);
}
@@ -66,14 +66,13 @@ constexpr void assertFunc(
}
constexpr void assertFunc(
StringViewCR file,
int const line,
Error const&err,
Error const &err,
StringViewCR,
StringViewCR assertMsg) noexcept {
StringViewCR assertMsg,
std::source_location const &src = std::source_location::current()) noexcept {
if (err) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, err, {}, assertMsg);
assertFailFuncRuntime(err, {}, assertMsg, src);
} else {
while (true);
}
@@ -81,20 +80,31 @@ constexpr void assertFunc(
}
constexpr void expect(
StringViewCR file,
int const line,
auto const&actual,
auto const&expected) noexcept {
auto const &actual,
auto const &expected,
std::source_location const &src = std::source_location::current()) noexcept {
if (actual != expected) {
if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB)
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
oxErrf(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
"Value incorrect");
oxErrf(
"expected: {}\nactual: {}\n",
detail::toStringView<true>(expected),
detail::toStringView<true>(actual));
printStackTrace(2);
oxTracef("assert.expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
oxTracef(
"assert.expect", "Failed assert: {} == {} [{}:{}]",
detail::toStringView<true>(actual),
detail::toStringView<true>(expected),
src.file_name(),
src.line());
std::abort();
#else
constexprPanic(file, line, "Comparison failed");
constexprPanic("Comparison failed", {}, src);
#endif
} else {
while (true);

View File

@@ -185,7 +185,7 @@ class BaseStringView {
}
[[nodiscard]]
constexpr auto len() const noexcept {
constexpr auto size() const noexcept {
return m_len;
}

View File

@@ -17,19 +17,19 @@ namespace ox {
template<typename T>
[[nodiscard]]
constexpr T byteSwap(typename enable_if<sizeof(T) == 1, T>::type i) noexcept {
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 1) {
return i;
}
template<typename T>
[[nodiscard]]
constexpr T byteSwap(typename enable_if<sizeof(T) == 2, T>::type i) noexcept {
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 2) {
return static_cast<T>(i << 8) | static_cast<T>(i >> 8);
}
template<typename T>
[[nodiscard]]
constexpr T byteSwap(typename enable_if<sizeof(T) == 4, T>::type i) noexcept {
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 4) {
return ((i >> 24) & 0x000000ff) |
((i >> 8) & 0x0000ff00) |
((i << 8) & 0x00ff0000) |
@@ -38,7 +38,7 @@ constexpr T byteSwap(typename enable_if<sizeof(T) == 4, T>::type i) noexcept {
template<typename T>
[[nodiscard]]
constexpr T byteSwap(typename enable_if<sizeof(T) == 8, T>::type i) noexcept {
constexpr T byteSwap(T const i) noexcept requires(sizeof(T) == 8) {
return ((i >> 56) & 0x00000000000000ff) |
((i >> 40) & 0x000000000000ff00) |
((i >> 24) & 0x0000000000ff0000) |

View File

@@ -32,4 +32,8 @@ concept Integral_c = ox::is_integral_v<T>;
template<typename T, size_t max>
concept IntegerRange_c = ox::is_integer_v<T> && ox::MaxValue<T> >= max;
template<typename Union>
concept Union_c = is_union_v<Union>;
}

View File

@@ -21,13 +21,13 @@ class CStringView: public detail::BaseStringView {
constexpr CStringView(CStringView const&sv) noexcept = default;
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.size()) {}
template<std::size_t SmallStrSz>
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.size()) {}
template<std::size_t SmallStrSz>
constexpr CStringView(IString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr CStringView(IString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.size()) {}
constexpr CStringView(std::nullptr_t) noexcept {}
@@ -37,7 +37,7 @@ class CStringView: public detail::BaseStringView {
constexpr auto &operator=(CStringView const&other) noexcept {
if (&other != this) {
set(other.data(), other.len());
set(other.data(), other.size());
}
return *this;
}

View File

@@ -48,9 +48,8 @@
// Asserts
#define oxPanic(errCode, msg) ox::panic(__FILE__, __LINE__, msg, errCode)
#ifndef NDEBUG
#define oxAssert(pass, msg) ox::assertFunc(__FILE__, __LINE__, pass, #pass, msg)
#define oxAssert(pass, msg) ox::assertFunc(pass, #pass, msg)
#else
namespace ox {
struct [[nodiscard]] Error;
@@ -59,7 +58,7 @@ constexpr void oxAssert(bool, const char*) noexcept {}
constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
#endif
#define oxExpect(actual, expected) ox::expect(__FILE__, __LINE__, actual, expected)
#define oxExpect(actual, expected) ox::expect(actual, expected)
// Alloca

View File

@@ -17,7 +17,7 @@ class exception {
virtual ~exception() = default;
[[nodiscard]]
virtual char const*what() const noexcept {
virtual char const *what() const noexcept {
return "";
}
};
@@ -44,7 +44,7 @@ struct [[nodiscard]] Error {
explicit constexpr Error(
ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept:
std::source_location const &src = std::source_location::current()) noexcept:
src{src},
errCode{errCode}
{}
@@ -52,7 +52,7 @@ struct [[nodiscard]] Error {
explicit constexpr Error(
ErrorCode const errCode,
ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept:
std::source_location const &src = std::source_location::current()) noexcept:
src{src},
msg{msg},
errCode{errCode}
@@ -65,13 +65,13 @@ struct [[nodiscard]] Error {
};
[[nodiscard]]
constexpr auto errCode(Error const&err) noexcept {
constexpr auto errCode(Error const &err) noexcept {
return err.errCode;
}
template<typename T = char const*>
[[nodiscard]]
constexpr auto toStr(Error const&err) noexcept {
constexpr auto toStr(Error const &err) noexcept {
return err.msg ? T{err.msg} : "";
}
@@ -82,19 +82,19 @@ struct Exception: public std::exception {
explicit Exception(
ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept:
std::source_location const &src = std::source_location::current()) noexcept:
src{src},
errCode{errCode} {}
explicit Exception(
ErrorCode const errCode,
ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept:
std::source_location const &src = std::source_location::current()) noexcept:
src{src},
msg{msg},
errCode{errCode} {}
explicit Exception(Error const&err) noexcept:
explicit Exception(Error const &err) noexcept:
src{err.src},
msg{err.msg ? err.msg : ""},
errCode{err.errCode} {}
@@ -104,13 +104,16 @@ struct Exception: public std::exception {
}
[[nodiscard]]
char const*what() const noexcept override {
char const *what() const noexcept override {
return msg;
}
};
[[noreturn]]
void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
void panic(
Error const &err,
char const *panicMsg,
std::source_location const &src = std::source_location::current()) noexcept;
template<typename T>
struct [[nodiscard]] Result {
@@ -124,25 +127,25 @@ struct [[nodiscard]] Result {
}
template<typename U>
constexpr Result(Result<U> const&other) noexcept: value(other.value), error(other.error) {
constexpr Result(Result<U> const &other) noexcept: value(other.value), error(other.error) {
}
template<typename U>
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
}
constexpr Result(Error const&error) noexcept: value(), error(error) {
constexpr Result(Error const &error) noexcept: value(), error(error) {
}
constexpr Result(type const&value, Error const&error = {}) noexcept: value(value), error(error) {
constexpr Result(type const &value, Error const &error = {}) noexcept: value(value), error(error) {
}
constexpr Result(type &&value, Error const&error = {}) noexcept: value(std::move(value)), error(error) {
constexpr Result(type &&value, Error const &error = {}) noexcept: value(std::move(value)), error(error) {
}
constexpr ~Result() noexcept = default;
explicit constexpr operator type const&() const noexcept {
explicit constexpr operator type const &() const noexcept {
return value;
}
@@ -156,7 +159,7 @@ struct [[nodiscard]] Result {
}
template<typename U>
constexpr Error copyTo(U &val) const& noexcept {
constexpr Error copyTo(U &val) const & noexcept {
if (!error) [[likely]] {
val = value;
}
@@ -182,7 +185,7 @@ struct [[nodiscard]] Result {
[[nodiscard]]
constexpr T &unwrap() & noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return value;
}
@@ -190,15 +193,15 @@ struct [[nodiscard]] Result {
[[nodiscard]]
constexpr T &&unwrap() && noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return std::move(value);
}
[[nodiscard]]
constexpr T const&unwrap() const & noexcept {
constexpr T const &unwrap() const & noexcept {
if (error) [[unlikely]] {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return value;
}
@@ -220,7 +223,7 @@ struct [[nodiscard]] Result {
}
[[nodiscard]]
constexpr T const&unwrapThrow() const & {
constexpr T const &unwrapThrow() const & {
if (error) {
throw ox::Exception(error);
}
@@ -244,7 +247,7 @@ struct [[nodiscard]] Result {
}
template<typename U = T>
constexpr ox::Result<U> to(auto const&f) & noexcept {
constexpr ox::Result<U> to(auto const &f) & noexcept {
if (error) [[unlikely]] {
return error;
}
@@ -252,7 +255,7 @@ struct [[nodiscard]] Result {
}
template<typename U = T>
constexpr ox::Result<U> to(auto const&f) && noexcept {
constexpr ox::Result<U> to(auto const &f) && noexcept {
if (error) [[unlikely]] {
return error;
}
@@ -264,7 +267,7 @@ struct [[nodiscard]] Result {
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T &&alt) const& noexcept {
constexpr T or_value(T &&alt) const & noexcept {
if (error) {
return std::move(alt);
}
@@ -288,7 +291,7 @@ struct [[nodiscard]] Result {
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) const& noexcept {
constexpr T or_value(T const &alt) const & noexcept {
if (error) {
return alt;
}
@@ -300,45 +303,54 @@ struct [[nodiscard]] Result {
* @param alt
* @return value of Result or alt
*/
constexpr T or_value(T const&alt) && noexcept {
constexpr T or_value(T const &alt) && noexcept {
if (error) {
return alt;
}
return std::move(value);
}
constexpr Result transformError(ErrorCode const ec, CString const msg) && {
if (error) {
error = Error{ec, msg};
}
return *this;
}
};
namespace detail {
constexpr Error toError(Error const&e) noexcept {
constexpr Error toError(Error const &e) noexcept {
return e;
}
template<typename T>
constexpr Error toError(Result<T> const&r) noexcept {
constexpr Error toError(Result<T> const &r) noexcept {
return r.error;
}
}
constexpr void primitiveAssert(char const*file, int line, bool pass, char const*msg) noexcept {
constexpr void primitiveAssert(
bool const pass,
char const *msg,
std::source_location const &src = std::source_location::current()) noexcept {
if constexpr(ox::defines::Debug) {
if (!pass) [[unlikely]] {
panic(file, line, msg, ox::Error(1));
panic(ox::Error{1}, msg, src);
}
}
}
constexpr void boundsCheck(
char const*file,
int const line,
size_t const i,
size_t const sz,
char const*msg) noexcept {
char const *msg,
std::source_location const &src = std::source_location::current()) noexcept {
if constexpr(defines::CheckBounds) {
if (i >= sz) [[unlikely]] {
panic(file, line, msg, ox::Error{1});
panic(ox::Error{1}, msg, src);
}
}
}

View File

@@ -77,7 +77,7 @@ static HeapSegment *findSegmentFor(std::size_t sz) noexcept {
return s;
}
}
oxPanic(ox::Error(1), "malloc: could not find segment");
ox::panic(ox::Error(1), "malloc: could not find segment");
return nullptr;
}
@@ -102,7 +102,7 @@ void free(void *ptr) noexcept {
} else if (p.segment) {
p.segment->inUse = false;
} else {
oxPanic(ox::Error(1), "Bad heap free");
ox::panic(ox::Error(1), "Bad heap free");
}
}

View File

@@ -16,7 +16,7 @@
namespace std {
inline constexpr struct {
inline constexpr struct ignore_t {
constexpr void operator=(auto&&) const noexcept {}
} ignore;

View File

@@ -72,7 +72,7 @@ class IString {
* Returns the number of characters in this string.
*/
[[nodiscard]]
constexpr std::size_t len() const noexcept;
constexpr std::size_t size() const noexcept;
/**
* Returns the number of bytes used for this string.
@@ -121,7 +121,7 @@ constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
template<std::size_t size>
constexpr IString<size> &IString<size>::operator=(ox::StringViewCR str) noexcept {
std::size_t strLen = str.len();
std::size_t strLen = str.size();
if (cap() < strLen) {
strLen = cap();
}
@@ -171,7 +171,7 @@ constexpr char &IString<StrCap>::operator[](std::size_t i) noexcept {
template<std::size_t StrCap>
constexpr Error IString<StrCap>::append(const char *str, std::size_t strLen) noexcept {
Error err{};
auto const currentLen = len();
auto const currentLen = size();
if (cap() < currentLen + strLen) {
strLen = cap() - currentLen;
err = ox::Error(1, "Insufficient space for full string");
@@ -187,7 +187,7 @@ OX_CLANG_NOWARN_END
template<std::size_t StrCap>
constexpr Error IString<StrCap>::append(ox::StringView str) noexcept {
return append(str.data(), str.len());
return append(str.data(), str.size());
}
template<std::size_t StrCap>
@@ -207,7 +207,7 @@ constexpr const char *IString<StrCap>::c_str() const noexcept {
template<std::size_t StrCap>
constexpr std::size_t IString<StrCap>::len() const noexcept {
constexpr std::size_t IString<StrCap>::size() const noexcept {
return m_size;
}

View File

@@ -133,17 +133,17 @@ struct SpanIterator {
}
constexpr PtrType operator->() const noexcept {
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
return &m_t[m_offset];
}
constexpr RefType operator*() const noexcept {
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
return m_t[m_offset];
}
constexpr RefType operator[](std::size_t s) const noexcept {
boundsCheck(__FILE__, __LINE__, s, m_max, "SpanIterator access overflow");
boundsCheck(s, m_max, "SpanIterator access overflow");
return m_t[s];
}

View File

@@ -213,8 +213,7 @@ class UniquePtr {
return m_t;
}
template<typename U, typename UDeleter>
constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
constexpr void reset(UniquePtr &&other = UniquePtr()) {
auto t = m_t;
m_t = other.release();
Deleter()(t);

View File

@@ -30,22 +30,60 @@ constexpr void *operator new(std::size_t, void *addr) noexcept {
constexpr void *operator new[](std::size_t, void *addr) noexcept {
return addr;
}
namespace std {
template<typename T>
[[nodiscard]]
constexpr T* launder(T* __p) noexcept {
return __builtin_launder(__p);
}
template<typename T, typename... Args, bool noex>
void launder(T(*)(Args...) noexcept(noex)) = delete;
template<typename T, typename... Args, bool noex>
void launder(T(*)(Args......) noexcept(noex)) = delete;
void launder(void*) = delete;
void launder(void const*) = delete;
void launder(volatile void*) = delete;
void launder(volatile void const*) = delete;
}
#endif
namespace ox {
/**
* Aliases type T in size and alignment to allow allocating space for a T
* without running the constructor.
*/
template<typename T, std::size_t sz = sizeof(T)>
struct alignas(alignof(T)) AllocAlias {
char buff[sz];
constexpr AllocAlias() noexcept = default;
[[nodiscard]]
auto data() noexcept {
return reinterpret_cast<T*>(this);
}
[[nodiscard]]
auto data() const noexcept {
return reinterpret_cast<T const*>(this);
}
};
template<typename T, typename U = T, typename ...Args>
[[nodiscard]]
constexpr U *make(Args &&...args) noexcept {
#ifdef __cpp_exceptions
try {
return new T(ox::forward<Args>(args)...);
} catch (std::exception const&ex) {
oxPanic(ox::Error(1, ex.what()), ex.what());
} catch (std::exception const &ex) {
ox::panic(ox::Error(1, ex.what()), ex.what());
return nullptr;
} catch (...) {
oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
ox::panic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
return nullptr;
}
#else

View File

@@ -30,13 +30,15 @@ constexpr std::ios_base::seekdir sdMap(ox::ios_base::seekdir in) noexcept {
ox::Result<char> StreamReader::peek() const noexcept {
try {
if (m_strm.eof()) {
return Error{1, "EOF"};
}
char c{};
m_strm.get(c);
auto const ok = c != EOF;
if (ok && m_strm.unget()) [[unlikely]] {
return ox::Error(1, "Unable to unget character");
if (m_strm.unget()) [[unlikely]] {
return ox::Error{1, "Unable to unget character"};
}
return {static_cast<char>(c), ox::Error(!ok, "File peek failed")};
return static_cast<char>(c);
} catch (std::exception const&) {
return ox::Error(1, "peek failed");
}

View File

@@ -47,7 +47,7 @@ class Span {
}
template<std::size_t sz>
constexpr Span(std::array<ox::remove_const_t<T>, sz> const&a) noexcept:
constexpr Span(std::array<ox::remove_const_t<T>, sz> const &a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
@@ -60,7 +60,7 @@ class Span {
}
template<std::size_t sz>
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const&a) noexcept:
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const &a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
@@ -72,7 +72,7 @@ class Span {
}
template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const&v) noexcept:
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const &v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
@@ -146,28 +146,41 @@ class Span {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
constexpr T &operator[](std::size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
return m_items[i];
}
constexpr T const&operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
constexpr T &operator[](std::size_t i) const noexcept {
boundsCheck(i, size(), "Span access overflow");
return m_items[i];
}
constexpr Span operator+(size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
boundsCheck(i, size(), "Span access overflow");
return {m_items + i, m_size - i};
}
constexpr Span operator+=(size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
boundsCheck(i, size(), "Span access overflow");
m_items += i;
m_size -= i;
return *this;
}
constexpr Span operator++(int) noexcept {
++m_items;
--m_size;
if (!m_size) [[unlikely]] {
m_items = nullptr;
}
return *this;
}
constexpr Span operator++() noexcept {
++m_items;
--m_size;
if (!m_size) [[unlikely]] {
m_items = nullptr;
}
return *this;
}
[[nodiscard]]
constexpr auto data() const noexcept {
return m_items;

View File

@@ -17,35 +17,41 @@
namespace ox {
template<Integer_c Integer>
constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
OX_RETURN_ERROR(writer.put('-'));
constexpr ox::Error writeItoa(Integer const v, ox::Writer_c auto &writer) noexcept {
if (v) {
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
ox::ResizedInt_t<Integer, 64> val = v;
constexpr auto base = 10;
auto it = 0;
if (val < 0) {
OX_RETURN_ERROR(writer.put('-'));
val = ~val + 1;
}
if constexpr(sizeof(v) == 8 && !ox::is_signed_v<Integer>) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (digit) {
digit -= 10;
OX_RETURN_ERROR(writer.put('1'));
OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
++it;
}
while (mod) {
auto digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
ox::ResizedInt_t<Integer, 64> start = '0';
if (digit >= 10) {
start = 'a';
digit -= 10;
}
OX_RETURN_ERROR(writer.put(static_cast<char>(start + digit)));
++it;
}
}
} else {
// 0 is a special case
OX_RETURN_ERROR(writer.put('0'));
}
return {};
while (mod) {
auto const digit = val / mod;
val %= mod;
mod /= base;
if (it || digit) {
OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
++it;
}
}
} else {
// 0 is a special case
OX_RETURN_ERROR(writer.put('0'));
}
return {};
}
}

View File

@@ -139,7 +139,7 @@ class BasicString {
constexpr BasicString &operator+=(Integer_c auto i) noexcept;
constexpr BasicString &operator+=(StringView src) noexcept;
constexpr BasicString &operator+=(StringViewCR src) noexcept;
constexpr BasicString &operator+=(BasicString const&src) noexcept;
@@ -176,17 +176,17 @@ class BasicString {
constexpr char &operator[](std::size_t i) noexcept;
constexpr Error append(const char *str, std::size_t strLen) noexcept {
auto currentLen = len();
auto currentLen = size();
m_buff.resize(m_buff.size() + strLen);
ox::listcpy(&m_buff[currentLen], str, strLen);
// make sure last element is a null terminator
m_buff[currentLen + strLen] = 0;
// this can't fail, but it returns an Error to match BString::append
return ox::Error(0);
return {};
}
constexpr Error append(ox::StringView sv) noexcept {
return append(sv.data(), sv.len());
constexpr Error append(StringViewCR sv) noexcept {
return append(sv.data(), sv.size());
}
[[nodiscard]]
@@ -237,7 +237,7 @@ class BasicString {
* Returns the number of characters in this string.
*/
[[nodiscard]]
constexpr std::size_t len() const noexcept;
constexpr std::size_t size() const noexcept;
/**
* Returns the number of bytes used for this string.
@@ -277,7 +277,7 @@ constexpr BasicString<SmallStringSize_v>::BasicString(const char *str, std::size
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v>::BasicString(StringLiteral const&str) noexcept:
BasicString(StringView{str.data(), str.len()}) {
BasicString(StringView{str.data(), str.size()}) {
}
template<std::size_t SmallStringSize_v>
@@ -376,7 +376,7 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
}
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(StringView s) noexcept {
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(StringViewCR s) noexcept {
std::size_t strLen = s.bytes();
std::ignore = append(s.data(), strLen);
return *this;
@@ -384,14 +384,14 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(BasicString const&src) noexcept {
std::ignore = append(src.c_str(), src.len());
std::ignore = append(src.c_str(), src.size());
return *this;
}
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const char *str) const noexcept {
const std::size_t strLen = ox::strlen(str);
const auto currentLen = len();
const auto currentLen = size();
BasicString<SmallStringSize_v> cpy;
cpy.m_buff.resize(m_buff.size() + strLen);
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
@@ -420,8 +420,8 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(StringViewCR src) const noexcept {
const std::size_t strLen = src.len();
const auto currentLen = len();
const std::size_t strLen = src.size();
const auto currentLen = size();
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
cpy.m_buff.resize(m_buff.size() + strLen);
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
@@ -432,8 +432,8 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
template<std::size_t SmallStringSize_v>
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(BasicString const&src) const noexcept {
const std::size_t strLen = src.len();
const auto currentLen = len();
const std::size_t strLen = src.size();
const auto currentLen = size();
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
cpy.m_buff.resize(m_buff.size() + strLen);
ox::listcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
@@ -456,7 +456,7 @@ constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) con
template<std::size_t SmallStringSize_v>
constexpr bool BasicString<SmallStringSize_v>::operator==(OxString_c auto const&other) const noexcept {
return ox::StringView(*this) == ox::StringView(other);
return StringView(*this) == StringView(other);
}
template<std::size_t SmallStringSize_v>
@@ -521,7 +521,7 @@ constexpr std::size_t BasicString<SmallStringSize_v>::bytes() const noexcept {
}
template<std::size_t SmallStringSize_v>
constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
constexpr std::size_t BasicString<SmallStringSize_v>::size() const noexcept {
return m_buff.size() - 1;
}
@@ -548,28 +548,28 @@ using StringCR = String const&;
[[nodiscard]]
constexpr ox::String toString(ox::StringViewCR sv) noexcept {
constexpr String toString(StringViewCR sv) noexcept {
return ox::String(sv);
}
template<typename PlatSpec, std::size_t SmallStringSize_v>
[[nodiscard]]
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
constexpr auto sizeOf(BasicString<SmallStringSize_v> const*) noexcept {
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
return sizeOf<PlatSpec>(&v);
}
template<typename PlatSpec, std::size_t SmallStringSize_v>
[[nodiscard]]
constexpr auto alignOf(const ox::BasicString<SmallStringSize_v>&) noexcept {
constexpr auto alignOf(BasicString<SmallStringSize_v> const&) noexcept {
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
return alignOf<PlatSpec>(&v);
}
template<size_t sz>
struct MaybeView<ox::BasicString<sz>> {
using type = ox::StringView;
struct MaybeView<BasicString<sz>> {
using type = StringView;
};
}

View File

@@ -16,35 +16,28 @@ namespace ox {
* StringLiteral is used for functions that want to ensure that they are taking
* string literals, and not strings outside of the data section of the program
* that might get deleted.
* This type cannot force you to use it correctly, so don't give it something
* that is not a literal.
* If you do this:
* StringLiteral(str.c_str())
* the resulting segfault is on you.
*/
class StringLiteral: public detail::BaseStringView {
public:
constexpr StringLiteral() noexcept = default;
constexpr StringLiteral(StringLiteral const&sv) noexcept = default;
constexpr StringLiteral(StringLiteral const &sv) noexcept = default;
constexpr explicit StringLiteral(std::nullptr_t) noexcept {}
consteval StringLiteral(std::nullptr_t) noexcept {}
constexpr explicit StringLiteral(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
consteval StringLiteral(char const *str, std::size_t const len) noexcept: BaseStringView{str, len} {}
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
constexpr explicit StringLiteral(char const *str) noexcept: StringLiteral(str, ox::strlen(str)) {}
consteval StringLiteral(char const *str) noexcept: StringLiteral{str, ox::strlen(str)} {}
OX_ALLOW_UNSAFE_BUFFERS_END
constexpr StringLiteral &operator=(StringLiteral const&other) noexcept {
if (&other != this) {
set(other.data(), other.len());
}
constexpr StringLiteral &operator=(StringLiteral const &other) noexcept {
set(other.data(), other.size());
return *this;
}
[[nodiscard]]
constexpr const char *c_str() const noexcept {
constexpr char const *c_str() const noexcept {
return data();
}

View File

@@ -8,6 +8,7 @@
#pragma once
#include "cstringview.hpp"
#include "string.hpp"
namespace ox {
@@ -20,6 +21,8 @@ class StringParam {
constexpr StringParam(StringParam &&o) noexcept: m_value{std::move(o.m_value)} {}
constexpr StringParam(char const*value) noexcept: m_value{value} {}
constexpr StringParam(detail::BaseStringView const&value) noexcept: m_value{value} {}
template<size_t sz>
constexpr StringParam(ox::IString<sz> const&value) noexcept: m_value{value} {}
constexpr StringParam(ox::String const&value) noexcept: m_value{value} {}
constexpr StringParam(ox::String &&value) noexcept: m_value{std::move(value)} {}
constexpr operator ox::String() && noexcept { return std::move(m_value); }

View File

@@ -40,10 +40,10 @@ class StringView: public detail::BaseStringView {
constexpr StringView(BaseStringView const&str) noexcept: BaseStringView(str.data(), str.bytes()) {}
template<std::size_t SmallStrSz>
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.size()) {}
template<std::size_t SmallStrSz>
constexpr StringView(const IString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.len()) {}
constexpr StringView(const IString<SmallStrSz> &str) noexcept: BaseStringView(str.data(), str.size()) {}
constexpr StringView(std::nullptr_t) noexcept {}
@@ -53,24 +53,24 @@ class StringView: public detail::BaseStringView {
constexpr auto &operator=(StringView const&other) noexcept {
if (&other != this) {
set(other.data(), other.len());
set(other.data(), other.size());
}
return *this;
}
};
using StringViewCR = const StringView&;
using StringViewCR = StringView const&;
constexpr auto operator==(StringViewCR s1, StringViewCR s2) noexcept {
if (s2.len() != s1.len()) {
if (s2.size() != s1.size()) {
return false;
}
return ox::strncmp(s1.data(), s2.data(), s1.len()) == 0;
return ox::strncmp(s1.data(), s2.data(), s1.size()) == 0;
}
constexpr auto operator<=>(StringViewCR s1, StringViewCR s2) noexcept {
const auto maxLen = ox::min(s1.len(), s2.len());
const auto maxLen = ox::min(s1.size(), s2.size());
const auto a = &s1.front();
const auto b = &s2.front();
for (std::size_t i = 0; i < maxLen && (a[i] || b[i]); ++i) {
@@ -80,16 +80,16 @@ constexpr auto operator<=>(StringViewCR s1, StringViewCR s2) noexcept {
return 1;
}
}
if (s1.len() > s2.len()) {
if (s1.size() > s2.size()) {
return 1;
} else if (s1.len() < s2.len()) {
} else if (s1.size() < s2.size()) {
return -1;
} else {
return 0;
}
}
constexpr auto write(Writer_c auto &writer, ox::StringViewCR sv) noexcept {
constexpr auto write(Writer_c auto &writer, StringViewCR sv) noexcept {
return writer.write(sv.data(), sv.bytes());
}
@@ -100,17 +100,20 @@ constexpr auto toStdStringView(StringViewCR sv) noexcept {
#endif
constexpr ox::Result<int> strToInt(ox::StringViewCR str) noexcept {
constexpr ox::Result<int> strToInt(StringViewCR str) noexcept {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
int total = 0;
int multiplier = 1;
for (auto i = static_cast<int64_t>(str.len()) - 1; i != -1; --i) {
if (str.size() == 0) [[unlikely]] {
return Error{1, "Empty string passed to strToInt"};
}
for (auto i = static_cast<int64_t>(str.size()) - 1; i != -1; --i) {
auto s = static_cast<std::size_t>(i);
if (str[s] >= '0' && str[s] <= '9') {
total += (str[s] - '0') * multiplier;
multiplier *= 10;
} else {
return ox::Error(1);
return ox::Error{1};
}
}
return total;

View File

@@ -21,37 +21,47 @@ OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox {
[[nodiscard]]
constexpr ox::StringView substr(ox::StringView const&str, std::size_t pos) noexcept {
if (str.len() >= pos) {
return {&str[pos], str.len() - pos};
constexpr StringView substr(StringViewCR str, std::size_t const pos) noexcept {
if (str.size() >= pos) {
return {&str[pos], str.size() - pos};
}
return {};
}
[[nodiscard]]
constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std::size_t end) noexcept {
if (str.len() >= start && end >= start) {
constexpr StringView substr(StringViewCR str, std::size_t const start, std::size_t const end) noexcept {
if (str.size() >= start && end >= start) {
return {&str[start], end - start};
}
return {};
}
[[nodiscard]]
constexpr bool beginsWith(StringViewCR base, char const beginning) noexcept {
return base.size() && base[0] == beginning;
}
[[nodiscard]]
constexpr bool endsWith(StringViewCR base, char const ending) noexcept {
return base.size() && base[base.size() - 1] == ending;
}
[[nodiscard]]
constexpr bool beginsWith(StringViewCR base, StringViewCR beginning) noexcept {
const auto beginningLen = ox::min(beginning.len(), base.len());
return base.len() >= beginning.len() && ox::strncmp(base.data(), beginning, beginningLen) == 0;
const auto beginningLen = ox::min(beginning.size(), base.size());
return base.size() >= beginning.size() && ox::strncmp(base.data(), beginning, beginningLen) == 0;
}
[[nodiscard]]
constexpr bool endsWith(StringViewCR base, StringViewCR ending) noexcept {
const auto endingLen = ending.len();
return base.len() >= endingLen && ox::strcmp(base.data() + (base.len() - endingLen), ending) == 0;
const auto endingLen = ending.size();
return base.size() >= endingLen && ox::strcmp(base.data() + (base.size() - endingLen), ending) == 0;
}
[[nodiscard]]
constexpr std::size_t find(StringViewCR str, char search) noexcept {
constexpr std::size_t find(StringViewCR str, char const search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
for (; i < str.size(); ++i) {
if (str[i] == search) {
break;
}
@@ -62,7 +72,7 @@ constexpr std::size_t find(StringViewCR str, char search) noexcept {
[[nodiscard]]
constexpr std::size_t find(StringViewCR str, StringViewCR search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
for (; i < str.size(); ++i) {
if (beginsWith(substr(str, i), search)) {
break;
}
@@ -72,14 +82,14 @@ constexpr std::size_t find(StringViewCR str, StringViewCR search) noexcept {
template<std::size_t smallSz = 0>
[[nodiscard]]
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, char del) noexcept {
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, char const del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](StringViewCR current, char del) {
return substr(current, find(current, del) + 1);
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
for (auto current = str; current.size(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = substr(current, 0, next); s.len()) {
if (const auto s = substr(current, 0, next); s.size()) {
out.emplace_back(s);
}
current = substr(current, next);
@@ -92,11 +102,11 @@ template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringViewCR del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](StringViewCR current, StringViewCR del) {
return substr(current, find(current, del) + del.len());
return substr(current, find(current, del) + del.size());
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
for (auto current = str; current.size(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = substr(current, 0, next); s.len()) {
if (const auto s = substr(current, 0, next); s.size()) {
out.emplace_back(s);
}
current = substr(current, next);
@@ -105,7 +115,7 @@ constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringView
}
[[nodiscard]]
constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int character) noexcept {
constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int const character) noexcept {
ox::Result<std::size_t> retval = ox::Error(1, "Character not found");
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
if (str[static_cast<std::size_t>(i)] == character) {

View File

@@ -28,3 +28,4 @@ add_test("[ox/std] FromHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "FromHex")
add_test("[ox/std] ToHex" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ToHex")
add_test("[ox/std] UUID" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID")
add_test("[ox/std] UUID::generate" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "UUID::generate")
add_test("[ox/std] intToStr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "intToStr")

View File

@@ -183,7 +183,7 @@ OX_CLANG_NOWARN_END
s = "asdf";
oxAssert(s == "asdf", "String assign broken");
oxAssert(s != "aoeu", "String assign broken");
oxAssert(s.len() == 4, "String assign broken");
oxAssert(s.size() == 4, "String assign broken");
return ox::Error(0);
}
},
@@ -337,7 +337,6 @@ OX_CLANG_NOWARN_END
oxExpect(si["asdf"], 0);
oxAssert(si["aoeu"] == 100, "aoeu != 100");
auto si2 = si;
oxDebugf("{}", si2["asdf"]);
oxExpect(si2["asdf"], 0);
oxAssert(si2["aoeu"] == 100, "aoeu != 100");
ox::HashMap<int, int> ii;
@@ -537,6 +536,35 @@ OX_CLANG_NOWARN_END
return ox::Error(0);
}
},
{
"intToStr",
[] {
oxExpect(ox::intToStr<uint8_t>(255u), "255");
oxExpect(ox::intToStr<int8_t>(127), "127");
oxExpect(ox::intToStr<int8_t>(-128), "-128");
oxExpect(ox::intToStr<uint16_t>(65535u), "65535");
oxExpect(ox::intToStr<int16_t>(32767), "32767");
oxExpect(ox::intToStr<int16_t>(-32768), "-32768");
oxExpect(ox::intToStr<uint32_t>(4294967295u), "4294967295");
oxExpect(ox::intToStr<int32_t>(2147483647), "2147483647");
oxExpect(ox::intToStr<int32_t>(-2147483648), "-2147483648");
oxExpect(ox::intToStr<uint64_t>(18446744073709551615u), "18446744073709551615");
oxExpect(ox::intToStr<int64_t>(9223372036854775807), "9223372036854775807");
oxExpect(ox::intToStr<int64_t>(-9223372036854775807), "-9223372036854775807");
oxExpect(ox::intToStr<uint64_t>(0), "0");
oxExpect(ox::intToStr<uint64_t>(5), "5");
oxExpect(ox::intToStr(0), "0");
oxExpect(ox::intToStr(5), "5");
oxExpect(ox::intToStr(5000), "5000");
oxExpect(ox::intToStr(50000), "50000");
oxExpect(ox::intToStr(500000), "500000");
oxExpect(ox::intToStr(-5), "-5");
oxExpect(ox::intToStr(-5000), "-5000");
oxExpect(ox::intToStr(-50000), "-50000");
oxExpect(ox::intToStr(-500000), "-500000");
return ox::Error{};
}
},
};
int main(int argc, const char **argv) {

View File

@@ -166,7 +166,7 @@ class OutStream {
constexpr OutStream &operator<<(Integer_c auto v) noexcept;
constexpr OutStream &operator<<(char v) noexcept {
if (m_msg.msg.len()) {
if (m_msg.msg.size()) {
m_msg.msg += m_delimiter;
}
m_msg.msg += v;
@@ -174,7 +174,7 @@ class OutStream {
}
constexpr OutStream &operator<<(StringViewCR v) noexcept {
if (m_msg.msg.len()) {
if (m_msg.msg.size()) {
m_msg.msg += m_delimiter;
}
m_msg.msg += v;
@@ -209,7 +209,7 @@ class OutStream {
private:
constexpr OutStream &appendSignedInt(int64_t v) noexcept {
if (m_msg.msg.len()) {
if (m_msg.msg.size()) {
m_msg.msg += m_delimiter;
}
m_msg.msg += static_cast<int64_t>(v);
@@ -217,7 +217,7 @@ class OutStream {
}
constexpr OutStream &appendUnsignedInt(uint64_t v) noexcept {
if (m_msg.msg.len()) {
if (m_msg.msg.size()) {
m_msg.msg += m_delimiter;
}
m_msg.msg += static_cast<int64_t>(v);
@@ -227,7 +227,7 @@ class OutStream {
};
constexpr OutStream &OutStream::operator<<(Integer_c auto v) noexcept {
if (m_msg.msg.len()) {
if (m_msg.msg.size()) {
m_msg.msg += m_delimiter;
}
m_msg.msg += v;
@@ -268,7 +268,7 @@ using TraceStream = NullStream;
inline void logError(const char *file, int line, const char *fmt, const Error &err) noexcept {
if (err) {
TraceStream trc(file, line, "ox::error");
TraceStream trc(file, line, "ox.error");
if (err.src.file_name() != nullptr) {
trc << "Error: (" << err.src.file_name() << ":" << err.src.line() << "):";
} else {
@@ -280,7 +280,7 @@ inline void logError(const char *file, int line, const char *fmt, const Error &e
inline void logError(const char *file, int line, const Error &err) noexcept {
if (err) {
TraceStream trc(file, line, "ox::error");
TraceStream trc(file, line, "ox.error");
trc << "Error:" << err;
if (err.src.file_name() != nullptr) {
trc << "(" << err.src.file_name() << ":" << err.src.line() << ")";

View File

@@ -63,25 +63,6 @@ namespace ox {
using CString = char const*;
/**
* Aliases type T in size and alignment to allow allocating space for a T
* without running the constructor.
*/
template<typename T, std::size_t sz = sizeof(T)>
struct alignas(alignof(T)) AllocAlias {
char buff[sz];
constexpr AllocAlias() noexcept = default;
[[nodiscard]]
auto data() noexcept {
return reinterpret_cast<T*>(this);
}
[[nodiscard]]
auto data() const noexcept {
return reinterpret_cast<const T*>(this);
}
};
template<std::size_t sz>
struct SignedType {
};

View File

@@ -180,20 +180,6 @@ struct is_same<T, T>: true_type {};
template<typename T, typename U>
constexpr auto is_same_v = is_same<T, U>::value;
// enable_if ///////////////////////////////////////////////////////////////////
template<bool B, class T = void>
struct enable_if {
};
template<class T>
struct enable_if<true, T> {
using type = T;
};
template<bool B, typename T>
using enable_if_t = typename enable_if<B, T>::type;
template<typename T>
struct is_pointer {
static constexpr bool value = false;

View File

@@ -32,9 +32,9 @@ constexpr bool cmp_equal(T const t, U const u) noexcept {
if constexpr(ox::is_signed_v<T> == ox::is_signed_v<U>) {
return t == u;
} else if constexpr(ox::is_signed_v<T>) {
return ox::Signed<T>{t} == u;
return t >= 0 && static_cast<ox::Unsigned<T>>(t) == u;
} else {
return t == ox::Signed<U>{u};
return u >= 0 && t == static_cast<ox::Unsigned<U>>(u);
}
}
@@ -43,9 +43,9 @@ constexpr bool cmp_less(T const t, U const u) noexcept {
if constexpr(ox::is_signed_v<T> == ox::is_signed_v<U>) {
return t < u;
} else if constexpr(ox::is_signed_v<T>) {
return ox::Signed<T>{t} < u;
return t < 0 || static_cast<ox::Unsigned<T>>(t) < u;
} else {
return t < ox::Signed<U>{u};
return u >= 0 && t < static_cast<ox::Unsigned<U>>(u);
}
}
@@ -69,6 +69,13 @@ constexpr bool cmp_greater_equal(T const t, U const u) noexcept {
return !std::cmp_less(t, u);
}
static_assert(cmp_less(-1, 5u));
static_assert(!cmp_less(5u, -1));
static_assert(cmp_equal(5u, 5));
static_assert(cmp_equal(5, 5u));
static_assert(!cmp_equal(-5, 5u));
static_assert(!cmp_equal(4u, 5u));
}
#endif

View File

@@ -58,7 +58,7 @@ constexpr ox::Result<uint8_t> fromHex(ox::StringViewCR v) noexcept {
if (!detail::isHexChar(v[0]) || !detail::isHexChar(v[1])) {
return ox::Error(1, "Invalid UUID");
}
if (v.len() != 2) {
if (v.size() != 2) {
return ox::Error(2);
}
uint8_t out = 0;
@@ -133,18 +133,18 @@ class UUID {
}
static constexpr ox::Result<ox::UUID> fromString(ox::StringViewCR s) noexcept {
if (s.len() < 36) {
if (s.size() < 36) {
return ox::Error(1, "Insufficient data to contain a complete UUID");
}
UUID out;
auto valueI = 0u;
for (size_t i = 0; i < s.len();) {
for (size_t i = 0; i < s.size();) {
if (s[i] == '-') {
++i;
continue;
}
const auto seg = substr(s, i, i + 2);
if (seg.len() != 2) {
if (seg.size() != 2) {
return ox::Error(1, "Invalid UUID");
}
OX_REQUIRE(val, detail::fromHex(seg));
@@ -174,7 +174,7 @@ class UUID {
for (auto i = 0u; i < cnt; ++i) {
const auto v = value[valueI];
const auto h = detail::toHex(v);
std::ignore = writer.write(h.c_str(), h.len());
std::ignore = writer.write(h.c_str(), h.size());
++valueI;
}
};

View File

@@ -34,10 +34,10 @@ struct VectorAllocator {
ox::Array<AllocAlias<T>, Size> m_data = {};
protected:
constexpr VectorAllocator() noexcept = default;
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
constexpr VectorAllocator(VectorAllocator const&) noexcept = default;
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
constexpr void allocate(T **items, std::size_t cap) noexcept {
constexpr void allocate(T **items, std::size_t const cap) noexcept {
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
if (std::is_constant_evaluated() || cap > Size) {
*items = Allocator{}.allocate(cap);
@@ -49,45 +49,31 @@ struct VectorAllocator {
constexpr void moveConstructItemsFrom(
T **items,
VectorAllocator *src,
const std::size_t count,
const std::size_t cap) noexcept {
std::size_t const count,
std::size_t const cap) noexcept {
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
// try removing it later
if (!std::is_constant_evaluated()) {
if (cap <= m_data.size() && count <= m_data.size()) {
for (auto i = 0u; i < count; ++i) {
const auto dstItem = reinterpret_cast<T *>(&m_data[i]);
const auto srcItem = reinterpret_cast<T *>(&src->m_data[i]);
std::construct_at<T>(dstItem, std::move(*srcItem));
auto const srcItem = std::launder(reinterpret_cast<T*>(&src->m_data[i]));
new (&m_data[i]) T(std::move(*srcItem));
}
if (count) {
*items = std::launder(reinterpret_cast<T*>(m_data.data()));
} else {
*items = reinterpret_cast<T*>(m_data.data());
}
*items = reinterpret_cast<T*>(m_data.data());
}
}
}
constexpr void moveItemsFrom(
T **items,
VectorAllocator *src,
const std::size_t count,
const std::size_t cap) noexcept {
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
// try removing it later
if (!std::is_constant_evaluated()) {
if (cap <= m_data.size() && count <= m_data.size()) {
for (std::size_t i = 0; i < count; ++i) {
const auto dstItem = reinterpret_cast<T *>(&m_data[i]);
const auto srcItem = reinterpret_cast<T *>(&src->m_data[i]);
*dstItem = std::move(*srcItem);
}
*items = reinterpret_cast<T*>(m_data.data());
}
}
}
constexpr void deallocate(T *items, std::size_t cap) noexcept {
constexpr void deallocate(T *const items, std::size_t const cap) noexcept {
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
if (std::is_constant_evaluated()) {
Allocator{}.deallocate(items, cap);
if (items) {
Allocator{}.deallocate(items, cap);
}
} else {
if (items && static_cast<void*>(items) != static_cast<void*>(m_data.data())) {
Allocator{}.deallocate(items, cap);
@@ -101,10 +87,10 @@ template<typename T, typename Allocator>
struct VectorAllocator<T, Allocator, 0> {
protected:
constexpr VectorAllocator() noexcept = default;
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
constexpr VectorAllocator(VectorAllocator const&) noexcept = default;
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
constexpr void allocate(T **items, std::size_t cap) noexcept {
constexpr void allocate(T **items, std::size_t const cap) noexcept {
*items = Allocator{}.allocate(cap);
}
@@ -112,15 +98,15 @@ struct VectorAllocator<T, Allocator, 0> {
constexpr void moveConstructItemsFrom(
T**,
VectorAllocator*,
const std::size_t,
const std::size_t) noexcept {
std::size_t const,
std::size_t const) noexcept {
}
[[maybe_unused]]
constexpr void moveItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept {
constexpr void moveItemsFrom(T**, VectorAllocator*, std::size_t const, std::size_t const) noexcept {
}
constexpr void deallocate(T *items, std::size_t cap) noexcept {
constexpr void deallocate(T *const items, std::size_t const cap) noexcept {
if (items) {
Allocator{}.deallocate(items, cap);
}
@@ -261,6 +247,8 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr void resize(std::size_t size) noexcept(useNoexcept);
constexpr void reserveResize(std::size_t size) noexcept(useNoexcept);
[[nodiscard]]
constexpr T *data() noexcept {
return m_items;
@@ -275,7 +263,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr bool contains(MaybeView_t<T> const&) const noexcept;
constexpr iterator<T&, T*, false> insert(
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept);
std::size_t pos, std::size_t cnt, T const &val) noexcept(useNoexcept);
constexpr iterator<T&, T*, false> insert(std::size_t pos, T val) noexcept(useNoexcept);
@@ -285,7 +273,9 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
template<typename... Args>
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
constexpr void push_back(T item) noexcept(useNoexcept);
constexpr void push_back(T const &item) noexcept(useNoexcept);
constexpr void push_back(T &&item) noexcept(useNoexcept);
constexpr void pop_back() noexcept(useNoexcept);
@@ -311,7 +301,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
*/
constexpr Error unordered_erase(std::size_t pos) noexcept(useNoexcept);
constexpr Error remove(T const &val);
constexpr Error remove(MaybeView_t<T> const &val);
constexpr void reserve(std::size_t cap) noexcept(useNoexcept);
@@ -419,7 +409,7 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
m_size = other.m_size;
m_cap = other.m_cap;
m_items = other.m_items;
this->moveItemsFrom(&m_items, &other, m_size, m_cap);
this->moveConstructItemsFrom(&m_items, &other, m_size, m_cap);
other.m_size = 0;
other.m_cap = 0;
other.m_items = nullptr;
@@ -429,13 +419,13 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
boundsCheck(i, size(), "Vector access overflow");
return m_items[i];
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr const T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
boundsCheck(i, size(), "Vector access overflow");
return m_items[i];
}
@@ -530,7 +520,13 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) n
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const&v) const noexcept {
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveResize(std::size_t const size) noexcept(useNoexcept) {
reserve(size);
resize(size);
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> const &v) const noexcept {
for (std::size_t i = 0; i < m_size; ++i) {
if (m_items[i] == v) {
return true;
@@ -542,7 +538,7 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> co
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
Vector<T, SmallVectorSize, Allocator>::insert(
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept) {
std::size_t pos, std::size_t cnt, T const &val) noexcept(useNoexcept) {
if (m_size + cnt > m_cap) {
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
}
@@ -615,7 +611,16 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T item) noexcept(useNoexcept) {
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T const &item) noexcept(useNoexcept) {
if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialCap);
}
std::construct_at(&m_items[m_size], item);
++m_size;
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
if (m_size == m_cap) {
reserve(m_cap ? m_cap * 2 : initialCap);
}
@@ -658,11 +663,11 @@ constexpr Error Vector<T, SmallVectorSize, Allocator>::unordered_erase(std::size
--m_size;
m_items[pos] = std::move(m_items[m_size]);
m_items[m_size].~T();
return ox::Error(0);
return {};
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr ox::Error Vector<T, SmallVectorSize, Allocator>::remove(T const &val) {
constexpr ox::Error Vector<T, SmallVectorSize, Allocator>::remove(MaybeView_t<T> const &val) {
for (size_t i{}; auto const &v : *this) {
if (v == val) {
return erase(i).error;

View File

@@ -5,103 +5,117 @@
#pragma once
#include <ox/std/array.hpp>
#include <ox/std/types.hpp>
#include <ox/std/units.hpp>
/////////////////////////////////////////////////////////////////
// Interrupt Handler
using interrupt_handler = void (*)();
#define REG_ISR *reinterpret_cast<interrupt_handler*>(0x0300'7FFC)
#define REG_IE *reinterpret_cast<volatile uint16_t*>(0x0400'0200)
#define REG_IF *reinterpret_cast<volatile uint16_t*>(0x0400'0202)
#define REG_IME *reinterpret_cast<volatile uint16_t*>(0x0400'0208)
using InterruptHandler = void(*)();
#define REG_ISR (*reinterpret_cast<InterruptHandler*>(0x0300'7FFC))
#define REG_IE (*reinterpret_cast<volatile uint16_t*>(0x0400'0200))
#define REG_IF (*reinterpret_cast<volatile uint16_t*>(0x0400'0202))
#define REG_IME (*reinterpret_cast<volatile uint16_t*>(0x0400'0208))
/////////////////////////////////////////////////////////////////
// Display Registers
#define REG_DISPCTL *reinterpret_cast<volatile uint32_t*>(0x0400'0000)
#define REG_DISPSTAT *reinterpret_cast<volatile uint32_t*>(0x0400'0004)
#define REG_VCOUNT *reinterpret_cast<volatile uint32_t*>(0x0400'0006)
#define REG_DISPCTL (*reinterpret_cast<volatile uint32_t*>(0x0400'0000))
#define REG_DISPSTAT (*reinterpret_cast<volatile uint32_t*>(0x0400'0004))
#define REG_VCOUNT (*reinterpret_cast<volatile uint32_t*>(0x0400'0006))
/////////////////////////////////////////////////////////////////
// Timers
#define REG_TIMER0 *reinterpret_cast<volatile uint16_t*>(0x0400'0100)
#define REG_TIMER0CTL *reinterpret_cast<volatile uint16_t*>(0x0400'0102)
#define REG_TIMER0 (*reinterpret_cast<volatile uint16_t*>(0x0400'0100))
#define REG_TIMER0CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'0102))
#define REG_TIMER1 *reinterpret_cast<volatile uint16_t*>(0x0400'0104)
#define REG_TIMER1CTL *reinterpret_cast<volatile uint16_t*>(0x0400'0106)
#define REG_TIMER1 (*reinterpret_cast<volatile uint16_t*>(0x0400'0104))
#define REG_TIMER1CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'0106))
#define REG_TIMER2 *reinterpret_cast<volatile uint16_t*>(0x0400'0108)
#define REG_TIMER2CTL *reinterpret_cast<volatile uint16_t*>(0x0400'010a)
#define REG_TIMER2 (*reinterpret_cast<volatile uint16_t*>(0x0400'0108))
#define REG_TIMER2CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'010a))
#define REG_TIMER3 *reinterpret_cast<volatile uint16_t*>(0x0400'010c)
#define REG_TIMER3CTL *reinterpret_cast<volatile uint16_t*>(0x0400'010e)
#define REG_TIMER3 (*reinterpret_cast<volatile uint16_t*>(0x0400'010c))
#define REG_TIMER3CTL (*reinterpret_cast<volatile uint16_t*>(0x0400'010e))
/////////////////////////////////////////////////////////////////
// background registers
// background control registers
using BgCtl = uint16_t;
#define REG_BG0CTL *reinterpret_cast<volatile BgCtl*>(0x0400'0008)
#define REG_BG1CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000a)
#define REG_BG2CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000c)
#define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e)
#define REG_BG0CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'0008))
#define REG_BG1CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000a))
#define REG_BG2CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000c))
#define REG_BG3CTL (*reinterpret_cast<volatile BgCtl*>(0x0400'000e))
[[nodiscard]]
inline volatile BgCtl &regBgCtl(uintptr_t bgIdx) noexcept {
inline volatile BgCtl &regBgCtl(uintptr_t const bgIdx) noexcept {
return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx);
}
// background horizontal scrolling registers
#define REG_BG0HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0010)
#define REG_BG1HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0014)
#define REG_BG2HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0018)
#define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c)
#define REG_BG0HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0010))
#define REG_BG1HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0014))
#define REG_BG2HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0018))
#define REG_BG3HOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001c))
[[nodiscard]]
inline volatile uint32_t &regBgHofs(auto bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx);
volatile int16_t &regBgHofs(auto const bgIdx) noexcept {
return *reinterpret_cast<volatile int16_t*>(0x0400'0010 + 4 * bgIdx);
}
// background vertical scrolling registers
#define REG_BG0VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0012)
#define REG_BG1VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'0016)
#define REG_BG2VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001a)
#define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e)
#define REG_BG0VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0012))
#define REG_BG1VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'0016))
#define REG_BG2VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001a))
#define REG_BG3VOFS (*reinterpret_cast<volatile int16_t*>(0x0400'001e))
[[nodiscard]]
inline volatile uint32_t &regBgVofs(auto bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx);
volatile int16_t &regBgVofs(auto const bgIdx) noexcept {
return *reinterpret_cast<volatile int16_t*>(0x0400'0012 + 4 * bgIdx);
}
// background scrolling registers
struct OffsetPair {
int16_t x{}, y{};
};
#define REG_BG0OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0010))
#define REG_BG1OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0014))
#define REG_BG2OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'0018))
#define REG_BG3OFS (*reinterpret_cast<volatile OffsetPair*>(0x0400'001c))
[[nodiscard]]
volatile OffsetPair &regBgOfs(auto const bgIdx) noexcept {
return *reinterpret_cast<volatile OffsetPair*>(0x0400'0010 + sizeof(OffsetPair) * bgIdx);
}
/////////////////////////////////////////////////////////////////
// User Input
#define REG_GAMEPAD *reinterpret_cast<volatile uint16_t*>(0x0400'0130)
#define REG_GAMEPAD (*reinterpret_cast<volatile uint16_t*>(0x0400'0130))
/////////////////////////////////////////////////////////////////
// Memory Addresses
#define MEM_EWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0200'0000)
#define MEM_EWRAM_END reinterpret_cast<uint8_t*>(0x0203'FFFF)
#define MEM_EWRAM (*(reinterpret_cast<ox::Array<uint16_t, 0x0203'FFFF - 0x0200'0000>*>(0x0200'0000)))
#define MEM_IWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0300'0000)
#define MEM_IWRAM_END reinterpret_cast<uint8_t*>(0x0300'7FFF)
#define MEM_IWRAM (*(reinterpret_cast<ox::Array<uint8_t, 0x0300'7FFF - 0x0300'0000>*>(0x0300'0000)))
#define REG_BLNDCTL *reinterpret_cast<uint16_t*>(0x0400'0050)
#define REG_BLNDCTL (*reinterpret_cast<uint16_t*>(0x0400'0050))
#define MEM_BG_PALETTE reinterpret_cast<uint16_t*>(0x0500'0000)
#define MEM_SPRITE_PALETTE reinterpret_cast<uint16_t*>(0x0500'0200)
using Palette = ox::Array<uint16_t, 128>;
#define MEM_BG_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0000)))
#define MEM_SPRITE_PALETTE (*(reinterpret_cast<::Palette*>(0x0500'0200)))
using BgMapTile = ox::Array<uint16_t, 8192>;
#define MEM_BG_TILES reinterpret_cast<BgMapTile*>(0x0600'0000)
#define MEM_BG_MAP reinterpret_cast<BgMapTile*>(0x0600'e000)
#define MEM_BG_TILES (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'0000)))
#define MEM_BG_MAP (*(reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'e000)))
#define MEM_SPRITE_TILES reinterpret_cast<uint16_t*>(0x0601'0000)
#define MEM_OAM reinterpret_cast<uint64_t*>(0x0700'0000)
#define MEM_SPRITE_TILES (*(reinterpret_cast<ox::Array<uint16_t, 32 * ox::units::KB>*>(0x0601'0000)))
#define MEM_OAM (*(reinterpret_cast<ox::Array<uint64_t, 64>*>(0x0700'0000)))
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000)
#define MEM_ROM (*(reinterpret_cast<ox::Array<char, 32 * ox::units::MB>*>(0x0700'0000)))
#define MEM_SRAM reinterpret_cast<char*>(0x0e00'0000)
#define MEM_SRAM_SIZE 65535
#define MEM_SRAM (*(reinterpret_cast<ox::Array<char, 64 * ox::units::KB>*>(0x0e00'0000)))

View File

@@ -37,8 +37,10 @@ struct OX_ALIGN8 GbaSpriteAttrUpdate {
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept;
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept;
void applySpriteUpdates() noexcept;
void setBgOffset(uint16_t bg, int16_t x, int16_t y) noexcept;
}

View File

@@ -2,6 +2,8 @@
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#ifdef __GNUC__
#include <ox/std/heapmgr.hpp>
#include <teagba/bios.hpp>
@@ -24,7 +26,7 @@ extern void (*__preinit_array_end[]) (void);
extern void (*__init_array_start[]) (void);
extern void (*__init_array_end[]) (void);
int main(int argc, const char **argv);
int main(int argc, char const **argv);
extern "C" {
@@ -48,7 +50,7 @@ void __libc_init_array() {
}
int c_start() {
const char *args[2] = {"", "rom.oxfs"};
char const *args[2] = {"", "rom.oxfs"};
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
mgba::initConsole();
#pragma GCC diagnostic push
@@ -58,3 +60,5 @@ int c_start() {
}
}
#endif

View File

@@ -12,13 +12,13 @@ namespace teagba {
static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept {
GbaSpriteAttrUpdate &spriteAttr(size_t const i) noexcept {
return g_spriteBuffer[i];
}
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
void addSpriteUpdate(GbaSpriteAttrUpdate const &upd) noexcept {
const auto ie = REG_IE; // disable vblank interrupt handler
REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler
REG_IE = REG_IE & static_cast<uint16_t>(~Int_vblank); // disable vblank interrupt handler
g_spriteBuffer[upd.idx] = upd;
REG_IE = ie; // enable vblank interrupt handler
}
@@ -29,4 +29,10 @@ void applySpriteUpdates() noexcept {
}
}
void setBgOffset(uint16_t const bg, int16_t const x, int16_t const y) noexcept {
auto &o = regBgOfs(bg);
o.x = x;
o.y = y;
}
}

View File

@@ -27,9 +27,9 @@ All components have a platform indicator next to them:
* opengl - OpenGL implementation (P-)
* studio - studio plugin for core (P-)
* keel - keel plugin for core (PG)
* scene - defines & processes map data (PG)
* studio - studio plugin for scene (P-)
* keel - keel plugin for scene (PG)
* sound - sound system for Nostalgia (PG)
* studio - studio plugin for sound (P-)
* keel - keel plugin for sound (PG)
* player - plays the games (PG)
* studio - makes the games (P-)
* tools - command line tools (P-)
@@ -48,7 +48,7 @@ All components have a platform indicator next to them:
Not really that external... (PG)
* GlUtils - OpenGL helpers (P-)
* teagba - GBA assembly startup code (mostly pulled from devkitPro under MPL
2.0), and custom GBA hardware interop code (-G)
2.0), and custom GBA hardware interop code (-G)
Most GBA code is built on PC because it is small and helps to work on both
projects with the same CMake build dir, but GBA code is never linked with any
@@ -89,7 +89,8 @@ The GBA has two major resources for learning about its hardware:
On the surface, it seems like C++ changes the way we do things from C for no
reason, but there are reasons for many of these duplications of functionality.
The C++ language designers aren't stupid. Question them, but don't ignore them.
The C++ language designers aren't stupid.
Question them, but don't ignore them.
#### Casting
@@ -163,10 +164,11 @@ The Ox way of doing things is the Olympic way of doing things.
### Error Handling
Instead of throwing exceptions, generally try to use
[ox::Errors](deps/ox/ox-docs.md#error-handling) for error reporting,
but exceptions may be used where they make sense.
[ox::Error](deps/ox/ox-docs.md#error-handling) for error reporting.
Exceptions may be used where errors-as-values will not work, but catch them and
convert them to ```ox::Error``` as soon as possible.
Exceptions should generally just use ```OxException```, which is bascially an
Exceptions should generally just use ```ox::Exception```, which is basically an
exception form of ```ox::Error```.
### File I/O

View File

@@ -1,19 +1,49 @@
# d2025.07.0
* Add sub-command for exporting TileSheets as PNG files.
* Add 'Reload Project' menu item under File.
* Fix opening a project to mark an unopenable file as closed in the config file on startup.
# d2025.06.0
* Add ability to remember recent projects in config
* Add navigation support (back and forward)
* Fix file deletion to close file even if not active
* Fix file copy to work when creating a copy with the name of a previously
deleted file
* Fix crash that could occur after switching projects
* Make file picker popup accept on double click of a file
* TileSheetEditor: Fix copy/cut/paste enablement when there is no selection
* TileSheetEditor: Fix manual redo of draw actions, fix drawing to pixel 0, 0
as first action
* TileSheetEditor: Fix draw command to work on same pixel after switching
subsheets
* PaletteEditor: Add RGB key shortcuts for focusing color channels
* PaletteEditor: Add color preview to color editor
# d2025.05.1
* TileSheetEditor: Fix overrun errors when switching subsheets, clear selection
on switch (261e324acd)
* Fix new build error that occurs in MSVC (26d5048e6720c4c2d52508a6ee44c67dd9fe3ee5)
# d2025.05.0
* Add app icon for both window and file
* Change application font to Roboto Medium
* Closing application will now confirm with user if any files have unsaved
changes.
* UUID duplicates will now be reported when opening a project
* Deleting a directory now closes files in that directory
* Delete key now initiates deletion of selected directory
* UUID duplicates will now be reported when opening a project.
* Deleting a directory now closes files in that directory.
* Delete key now initiates deletion of selected directory.
* Remove ability to re-order tabs. There were bugs associated with that.
* TileSheetEditor: Fix selection clearing in to work when clicking outside
image.
* Mac: Menu bar shortcuts now say Cmd instead of Ctrl.
* TileSheetEditor: Fix selection clearing to work when clicking outside image.
* TileSheetEditor: Fix Delete Tile functionality, which was completely broken
* PaletteEditor: Fix color number key range in. Previously, pressing A caused
the editor to jump to the last color.
* PaletteEditor: page rename will now take effect upon pressing enter if the
* TileSheetEditor: Fix Insert Tile functionality, which was completely broken
* PaletteEditor: Fix color number key range. Previously, pressing A caused the
editor to jump to the last color.
* PaletteEditor: Page rename will now take effect upon pressing enter if the
text input has focus
# d2025.02.1

View File

@@ -19,10 +19,10 @@ using Color32 = uint32_t;
[[nodiscard]]
constexpr Color32 toColor32(Color16 nc) noexcept {
const auto r = static_cast<Color32>(((nc & 0b0000000000011111) >> 0) * 8);
const auto g = static_cast<Color32>(((nc & 0b0000001111100000) >> 5) * 8);
const auto b = static_cast<Color32>(((nc & 0b0111110000000000) >> 10) * 8);
const auto a = static_cast<Color32>(255);
auto const r = static_cast<Color32>(((nc & 0b0000000000011111) >> 0) * 8);
auto const g = static_cast<Color32>(((nc & 0b0000001111100000) >> 5) * 8);
auto const b = static_cast<Color32>(((nc & 0b0111110000000000) >> 10) * 8);
auto const a = static_cast<Color32>(255);
return r | (g << 8) | (b << 16) | (a << 24);
}
@@ -142,9 +142,9 @@ constexpr Color16 color16(int r, int g, int b, int a = 0) noexcept {
[[nodiscard]]
constexpr Color16 color16(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 0) noexcept {
return static_cast<Color16>(ox::min<uint8_t>(r, 31))
| static_cast<Color16>(ox::min<uint8_t>(g, 31) << 5)
| static_cast<Color16>(ox::min<uint8_t>(b, 31) << 10)
| static_cast<Color16>(a << 15);
| static_cast<Color16>(ox::min<uint8_t>(g, 31) << 5)
| static_cast<Color16>(ox::min<uint8_t>(b, 31) << 10)
| static_cast<Color16>(a << 15);
}
static_assert(color16(0, 31, 0) == 992);

View File

@@ -12,8 +12,37 @@ constexpr auto TileWidth = 8;
constexpr auto TileHeight = 8;
constexpr auto PixelsPerTile = TileWidth * TileHeight;
constexpr ox::StringLiteral FileExt_ng("ng");
constexpr ox::StringLiteral FileExt_nts("nts");
constexpr ox::StringLiteral FileExt_npal("npal");
constexpr ox::StringLiteral FileExt_ng{"ng"};
constexpr ox::StringLiteral FileExt_nts{"nts"};
constexpr ox::StringLiteral FileExt_npal{"npal"};
constexpr ox::Array<ox::StringLiteral, 2> FileExts_TileSheet{
FileExt_nts,
FileExt_ng,
};
constexpr ox::Array<ox::StringLiteral, 2> FileExts_Palette{
FileExt_npal,
};
[[nodiscard]]
constexpr bool isTileSheet(ox::StringViewCR path) noexcept {
return ox::any_of(
FileExts_TileSheet.begin(),
FileExts_TileSheet.end(),
[path](ox::StringLiteral const &ext) {
return endsWith(path, ext);
});
}
[[nodiscard]]
constexpr bool isPalette(ox::StringViewCR path) noexcept {
return ox::any_of(
FileExts_Palette.begin(),
FileExts_Palette.end(),
[path](ox::StringLiteral const &ext) {
return endsWith(path, ext);
});
}
}

View File

@@ -8,16 +8,12 @@
#include <turbine/context.hpp>
#include "initparams.hpp"
namespace nostalgia::gfx {
class Context;
void safeDelete(Context *ctx) noexcept;
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params = {}) noexcept;
keel::Context &keelCtx(Context &ctx) noexcept;
turbine::Context &turbineCtx(Context &ctx) noexcept;

View File

@@ -1,14 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include "color.hpp"
#include "context.hpp"
#include "gfx.hpp"
#include "initparams.hpp"
#include "keelmodule.hpp"
#include "palette.hpp"
#include "ptidxconv.hpp"
#include "tilesheet.hpp"

View File

@@ -9,8 +9,11 @@
#include <ox/std/types.hpp>
#include <ox/model/def.hpp>
#include "color.hpp"
#include "context.hpp"
#include "keelmodule.hpp"
#include "palette.hpp"
#include "ptidxconv.hpp"
#include "tilesheet.hpp"
namespace nostalgia::gfx {
@@ -102,21 +105,29 @@ OX_MODEL_BEGIN(TileSheetSet)
OX_MODEL_FIELD(entries)
OX_MODEL_END()
[[nodiscard]]
int tileColumns(Context&) noexcept;
struct InitParams {
bool glInstallDrawer = true;
uint_t glSpriteCount = 128;
uint_t glBlocksPerSprite = 64;
};
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const &params = {}) noexcept;
[[nodiscard]]
int tileRows(Context&) noexcept;
int tileColumns(Context const&) noexcept;
[[nodiscard]]
int tileRows(Context const&) noexcept;
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
CompactPalette const&palette,
CompactPalette const &palette,
size_t page = 0) noexcept;
ox::Error loadSpritePalette(
Context &ctx,
CompactPalette const&palette,
CompactPalette const &palette,
size_t page = 0) noexcept;
ox::Error loadBgPalette(
@@ -127,7 +138,7 @@ ox::Error loadBgPalette(
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept;
ox::FileAddress const &paletteAddr) noexcept;
ox::Error loadSpritePalette(
Context &ctx,
@@ -135,12 +146,12 @@ ox::Error loadSpritePalette(
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept;
ox::FileAddress const &paletteAddr) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
TileSheetSet const&set) noexcept;
TileSheetSet const &set) noexcept;
void clearCbb(Context &ctx, unsigned cbb) noexcept;
@@ -149,7 +160,7 @@ void clearCbbs(Context &ctx) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept;
@@ -165,7 +176,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tsAddr,
ox::FileAddress const &tsAddr,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept;
@@ -173,24 +184,24 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
CompactTileSheet const &ts,
ox::Optional<unsigned> const &paletteBank = {}) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tilesheetPath,
ox::Optional<unsigned> const&paletteBank) noexcept;
ox::Optional<unsigned> const &paletteBank) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
ox::FileAddress const &tilesheetAddr,
ox::Optional<unsigned> const &paletteBank = {}) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
CompactTileSheet const&ts,
CompactTileSheet const &ts,
bool loadDefaultPalette) noexcept;
ox::Error loadSpriteTileSheet(
@@ -200,16 +211,16 @@ ox::Error loadSpriteTileSheet(
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const &tilesheetAddr,
bool loadDefaultPalette = false) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept;
TileSheetSet const &set) noexcept;
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, unsigned tile, unsigned palBank = 0) noexcept;
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&tile) noexcept;
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const &tile) noexcept;
void clearBg(Context &ctx, uint_t bgIdx) noexcept;
@@ -223,18 +234,22 @@ bool bgStatus(Context &ctx, unsigned bg) noexcept;
void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept;
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept;
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbbIdx) noexcept;
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept;
void setBgOffset(Context &ctx, uint16_t bg, int16_t x, int16_t y) noexcept;
void scrollBgOffset(Context &ctx, uint16_t bg, int16_t x, int16_t y) noexcept;
void hideSprite(Context &ctx, unsigned) noexcept;
void showSprite(Context &ctx, unsigned) noexcept;
void setSprite(Context &c, uint_t idx, Sprite const&s) noexcept;
void setSprite(Context &ctx, uint_t idx, Sprite const &sprite) noexcept;
[[nodiscard]]
uint_t spriteCount(Context &ctx) noexcept;
uint_t spriteCount(Context const &ctx) noexcept;
ox::Error initConsole(Context &ctx) noexcept;
@@ -249,8 +264,8 @@ constexpr ox::CStringView GlslVersion = "#version 330";
[[nodiscard]]
ox::Size drawSize(int scale = 5) noexcept;
void draw(gfx::Context &ctx, ox::Size const&renderSz) noexcept;
void draw(Context &ctx, ox::Size const &renderSz) noexcept;
void draw(gfx::Context&, int scale = 5) noexcept;
void draw(Context&, int scale = 5) noexcept;
}

View File

@@ -1,17 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/std/types.hpp>
namespace nostalgia::gfx {
struct InitParams {
bool glInstallDrawer = true;
uint_t glSpriteCount = 128;
uint_t glBlocksPerSprite = 64;
};
}

View File

@@ -8,6 +8,6 @@
namespace nostalgia::gfx {
const keel::Module *keelModule() noexcept;
keel::Module const *keelModule() noexcept;
}

View File

@@ -168,9 +168,9 @@ OX_MODEL_BEGIN(PaletteV3)
OX_MODEL_END()
[[nodiscard]]
constexpr bool valid(PaletteV3 const&p) noexcept {
constexpr bool valid(PaletteV3 const &p) noexcept {
auto const colors = p.colorInfo.size();
return ox::all_of(p.pages.begin(), p.pages.end(), [colors](auto const&page) {
return ox::all_of(p.pages.begin(), p.pages.end(), [colors](auto const &page) {
return page.size() == colors;
});
}
@@ -198,9 +198,9 @@ OX_MODEL_BEGIN(PaletteV4)
OX_MODEL_END()
[[nodiscard]]
constexpr bool valid(PaletteV4 const&p) noexcept {
constexpr bool valid(PaletteV4 const &p) noexcept {
auto const colors = p.colorNames.size();
return ox::all_of(p.pages.begin(), p.pages.end(), [colors](PalettePageV1 const&page) {
return ox::all_of(p.pages.begin(), p.pages.end(), [colors](PalettePageV1 const &page) {
return page.colors.size() == colors;
});
}

View File

@@ -11,39 +11,39 @@
namespace nostalgia::gfx {
[[nodiscard]]
constexpr std::size_t ptToIdx(int x, int y, int c, int scale = 1) noexcept {
const auto tileWidth = TileWidth * scale;
const auto tileHeight = TileHeight * scale;
const auto pixelsPerTile = tileWidth * tileHeight;
const auto colLength = static_cast<std::size_t>(pixelsPerTile);
const auto rowLength = static_cast<std::size_t>(static_cast<std::size_t>(c / tileWidth) * colLength);
const auto colStart = static_cast<std::size_t>(colLength * static_cast<std::size_t>(x / tileWidth));
const auto rowStart = static_cast<std::size_t>(rowLength * static_cast<std::size_t>(y / tileHeight));
const auto colOffset = static_cast<std::size_t>(x % tileWidth);
const auto rowOffset = static_cast<std::size_t>((y % tileHeight) * tileHeight);
constexpr std::size_t ptToIdx(int const x, int const y, int const c, int const scale = 1) noexcept {
auto const tileWidth = TileWidth * scale;
auto const tileHeight = TileHeight * scale;
auto const pixelsPerTile = tileWidth * tileHeight;
auto const colLength = static_cast<std::size_t>(pixelsPerTile);
auto const rowLength = static_cast<std::size_t>(static_cast<std::size_t>(c / tileWidth) * colLength);
auto const colStart = static_cast<std::size_t>(colLength * static_cast<std::size_t>(x / tileWidth));
auto const rowStart = static_cast<std::size_t>(rowLength * static_cast<std::size_t>(y / tileHeight));
auto const colOffset = static_cast<std::size_t>(x % tileWidth);
auto const rowOffset = static_cast<std::size_t>((y % tileHeight) * tileHeight);
return static_cast<std::size_t>(colStart + colOffset + rowStart + rowOffset);
}
[[nodiscard]]
constexpr std::size_t ptToIdx(const ox::Point &pt, int c, int scale = 1) noexcept {
constexpr std::size_t ptToIdx(ox::Point const &pt, int const c, int const scale = 1) noexcept {
return ptToIdx(pt.x, pt.y, c * TileWidth, scale);
}
[[nodiscard]]
constexpr ox::Point idxToPt(int i, int c, int scale = 1) noexcept {
const auto tileWidth = TileWidth * scale;
const auto tileHeight = TileHeight * scale;
const auto pixelsPerTile = tileWidth * tileHeight;
constexpr ox::Point idxToPt(int const i, int c, int const scale = 1) noexcept {
auto const tileWidth = TileWidth * scale;
auto const tileHeight = TileHeight * scale;
auto const pixelsPerTile = tileWidth * tileHeight;
// prevent divide by zeros
if (!c) {
++c;
}
const auto t = i / pixelsPerTile; // tile number
const auto iti = i % pixelsPerTile; // in tile index
const auto tc = t % c; // tile column
const auto tr = t / c; // tile row
const auto itx = iti % tileWidth; // in tile x
const auto ity = iti / tileHeight; // in tile y
auto const t = i / pixelsPerTile; // tile number
auto const iti = i % pixelsPerTile; // in tile index
auto const tc = t % c; // tile column
auto const tr = t / c; // tile row
auto const itx = iti % tileWidth; // in tile x
auto const ity = iti / tileHeight; // in tile y
return {
itx + tc * tileWidth,
ity + tr * tileHeight,

View File

@@ -6,6 +6,28 @@
#include <studio/studio.hpp>
namespace nostalgia::core {
#include "tilesheet.hpp"
namespace nostalgia::gfx {
inline void navigateToTileSheet(
studio::Context &ctx, ox::StringParam path, SubSheetId const subsheetId) noexcept {
studio::navigateTo(ctx, std::move(path), ox::intToStr(subsheetId));
}
inline void navigateToPalette(studio::Context &ctx, ox::StringParam path) noexcept {
studio::navigateTo(ctx, std::move(path));
}
inline void navigateToPalette(
studio::Context &ctx,
ox::StringParam path,
size_t const colorIdx,
size_t const palPage) noexcept {
studio::navigateTo(
ctx,
std::move(path),
ox::sfmt("{};{}", colorIdx, palPage));
}
}

View File

@@ -8,6 +8,6 @@
namespace nostalgia::gfx {
const studio::Module *studioModule() noexcept;
studio::Module const *studioModule() noexcept;
}

View File

@@ -30,7 +30,7 @@ struct TileSheetV1 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV1 const&ts) noexcept {
constexpr bool valid(TileSheetV1 const &ts) noexcept {
auto const bytes = static_cast<size_t>(ts.columns * ts.rows * PixelsPerTile) / (ts.bpp == 4 ? 2 : 1);
return (ts.bpp == 4 || ts.bpp == 8) && ts.pixels.size() == bytes;
}
@@ -71,16 +71,16 @@ struct TileSheetV2 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV2::SubSheet const&ss, int bpp) noexcept {
constexpr bool valid(TileSheetV2::SubSheet const &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV2::SubSheet const&s) {
[bpp, bytes](TileSheetV2::SubSheet const &s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV2 const&ts) noexcept {
constexpr bool valid(TileSheetV2 const &ts) noexcept {
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
@@ -141,16 +141,16 @@ struct TileSheetV3 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV3::SubSheet const&ss, int bpp) noexcept {
constexpr bool valid(TileSheetV3::SubSheet const &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV3::SubSheet const&s) {
[bpp, bytes](TileSheetV3::SubSheet const &s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV3 const&ts) noexcept {
constexpr bool valid(TileSheetV3 const &ts) noexcept {
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
@@ -233,18 +233,18 @@ struct TileSheetV4 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV4::SubSheet const&ss, int bpp) noexcept {
constexpr bool valid(TileSheetV4::SubSheet const &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return
(ss.pixels.empty() || ss.subsheets.empty()) &&
ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV4::SubSheet const&s) {
[bpp, bytes](TileSheetV4::SubSheet const &s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV4 const&ts) noexcept {
constexpr bool valid(TileSheetV4 const &ts) noexcept {
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
@@ -334,19 +334,19 @@ struct TileSheetV5 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV5::SubSheet const&ss) noexcept {
constexpr bool valid(TileSheetV5::SubSheet const &ss) noexcept {
if (ss.subsheets.empty()) {
return static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) == ss.pixels.size();
return std::cmp_equal(ss.columns * ss.rows * PixelsPerTile, ss.pixels.size());
} else {
return ss.pixels.empty() && ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[](TileSheetV5::SubSheet const&s) {
[](TileSheetV5::SubSheet const &s) {
return valid(s);
});
}
}
[[nodiscard]]
constexpr bool valid(TileSheetV5 const&ts) noexcept {
constexpr bool valid(TileSheetV5 const &ts) noexcept {
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet);
}
@@ -376,24 +376,24 @@ constexpr ox::Error repair(TileSheetV5 &ts) noexcept {
using TileSheet = TileSheetV5;
[[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;
[[nodiscard]]
size_t getTileCnt(TileSheet const&ts) noexcept;
size_t getTileCnt(TileSheet const &ts) noexcept;
[[nodiscard]]
TileSheet::SubSheet const*getSubsheet(TileSheet const&ts, SubSheetId id) noexcept;
TileSheet::SubSheet const*getSubsheet(TileSheet const &ts, SubSheetId id) noexcept;
[[nodiscard]]
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId id) noexcept;
ox::Optional<size_t> getTileIdx(TileSheet const &ts, SubSheetId id) noexcept;
[[nodiscard]]
uint8_t getPixel(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
uint8_t getPixel(TileSheet::SubSheet const &ss, std::size_t idx) noexcept;
[[nodiscard]]
uint8_t getPixel(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
uint8_t getPixel(TileSheet::SubSheet const &ss, ox::Point const &pt) noexcept;
void setPixel(TileSheet::SubSheet &ss, ox::Point const&pt, uint8_t palIdx) noexcept;
void setPixel(TileSheet::SubSheet &ss, ox::Point const &pt, uint8_t palIdx) noexcept;
ox::Error setPixelCount(TileSheet::SubSheet &ss, std::size_t cnt) noexcept;
@@ -406,14 +406,14 @@ void flipY(TileSheet::SubSheet &ss, ox::Point const &a, ox::Point const &b) noex
* @return a count of the pixels in this sheet
*/
[[nodiscard]]
unsigned pixelCnt(TileSheet::SubSheet const&ss) noexcept;
unsigned pixelCnt(TileSheet::SubSheet const &ss) noexcept;
/**
*
* @param ss
* @param sz size of Subsheet in tiles (not pixels)
*/
ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept;
ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const &sz) noexcept;
/**
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the
@@ -424,11 +424,21 @@ ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept;
* @return a valid version of idx
*/
[[nodiscard]]
TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubSheetIdx idx) noexcept;
TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const &ts, TileSheet::SubSheetIdx idx) noexcept;
ox::Result<TileSheet::SubSheetIdx> getSubSheetIdx(TileSheet const &ts, SubSheetId pId) noexcept;
ox::Result<TileSheet::SubSheet*> getSubSheet(
ox::SpanView<ox::StringView> const &idx,
TileSheet &ts) noexcept;
ox::Result<TileSheet::SubSheet const*> getSubSheet(
ox::SpanView<ox::StringView> const &idx,
TileSheet const &ts) noexcept;
[[nodiscard]]
TileSheet::SubSheet &getSubSheet(
ox::SpanView<uint32_t> const&idx,
ox::SpanView<uint32_t> const &idx,
std::size_t idxIt,
TileSheet::SubSheet &pSubsheet) noexcept;
@@ -437,7 +447,7 @@ TileSheet::SubSheet &getSubSheet(
#pragma GCC diagnostic ignored "-Wdangling-reference"
#endif
[[nodiscard]]
TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, ox::SpanView<uint32_t> const &idx) noexcept;
TileSheet::SubSheet const &getSubSheet(TileSheet const &ts, ox::SpanView<uint32_t> const &idx) noexcept;
[[nodiscard]]
TileSheet::SubSheet &getSubSheet(TileSheet &ts, ox::SpanView<uint32_t> const &idx) noexcept;
@@ -451,27 +461,29 @@ ox::Error insertSubSheet(TileSheet &ts, ox::SpanView<uint32_t> const &idx, TileS
ox::Error rmSubSheet(
TileSheet &ts,
TileSheet::SubSheetIdx const&idx,
TileSheet::SubSheetIdx const &idx,
std::size_t idxIt,
TileSheet::SubSheet &pSubsheet) noexcept;
ox::Error rmSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept;
ox::Error rmSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const &idx) noexcept;
[[nodiscard]]
uint8_t getPixel(
TileSheet const&ts,
ox::Point const&pt,
TileSheet::SubSheetIdx const&subsheetIdx) noexcept;
TileSheet const &ts,
ox::Point const &pt,
TileSheet::SubSheetIdx const &subsheetIdx) noexcept;
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexcept;
ox::Result<SubSheetId> getIdFor(TileSheet const &ts, ox::StringViewCR path) noexcept;
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept;
ox::Result<unsigned> getTileOffset(TileSheet const &ts, ox::StringViewCR pNamePath) noexcept;
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, SubSheetId pId) noexcept;
ox::Result<uint32_t> getTileOffset(TileSheet const &ts, SubSheetId pId) noexcept;
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 &ts, SubSheetId pId) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet const &ts, SubSheetId pId) noexcept;
[[nodiscard]]
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept;
@@ -487,7 +499,7 @@ struct CompactTileSheetV1 {
};
[[nodiscard]]
constexpr bool valid(CompactTileSheetV1 const&ts) noexcept {
constexpr bool valid(CompactTileSheetV1 const &ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
@@ -496,22 +508,22 @@ using CompactTileSheet = CompactTileSheetV1;
[[nodiscard]]
uint8_t getPixel4Bpp(
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t idx) noexcept;
[[nodiscard]]
uint8_t getPixel8Bpp(
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t idx) noexcept;
[[nodiscard]]
ox::Pair<uint8_t> get2Pixels4Bpp(
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t idx) noexcept;
[[nodiscard]]
ox::Pair<uint8_t> get2Pixels8Bpp(
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t idx) noexcept;
OX_MODEL_BEGIN(TileSheetV1)
@@ -591,8 +603,8 @@ OX_MODEL_BEGIN(CompactTileSheetV1)
OX_MODEL_END()
ox::Vector<uint32_t> resizeTileSheetData(
ox::Vector<uint32_t> const&srcPixels,
ox::Size const&srcSize,
ox::Vector<uint32_t> const &srcPixels,
ox::Size const &srcSize,
int scale = 2) noexcept;
}

View File

@@ -4,11 +4,6 @@ add_library(
tilesheet.cpp
)
add_subdirectory(gba)
if(NOT BUILDCORE_TARGET STREQUAL "gba")
add_subdirectory(opengl)
endif()
target_include_directories(
NostalgiaGfx PUBLIC
../include
@@ -31,3 +26,38 @@ install(
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
# OpenGL
if(NOT BUILDCORE_TARGET STREQUAL "gba")
target_sources(
NostalgiaGfx PRIVATE
gfx-opengl.cpp
)
target_link_libraries(
NostalgiaGfx PUBLIC
GlUtils
)
endif()
# GBA
add_library(
NostalgiaGfx-GBA OBJECT
gfx-gba.cpp
)
target_include_directories(
NostalgiaGfx-GBA PUBLIC
../include
)
target_link_libraries(
NostalgiaGfx-GBA PUBLIC
TeaGBA
Keel
Turbine
)
if(BUILDCORE_TARGET STREQUAL "gba")
set_source_files_properties(gfx-gba.cpp PROPERTIES COMPILE_FLAGS -marm)
target_link_libraries(NostalgiaGfx PUBLIC NostalgiaGfx-GBA)
endif()

View File

@@ -1,21 +0,0 @@
add_library(
NostalgiaGfx-GBA OBJECT
context.cpp
gfx.cpp
panic.cpp
)
target_include_directories(
NostalgiaGfx-GBA PUBLIC
../../include
)
target_link_libraries(
NostalgiaGfx-GBA PUBLIC
TeaGBA
Keel
Turbine
)
if(BUILDCORE_TARGET STREQUAL "gba")
set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm)
target_link_libraries(NostalgiaGfx PUBLIC NostalgiaGfx-GBA)
endif()

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <turbine/turbine.hpp>
#include <nostalgia/gfx/gfx.hpp>
#include "context.hpp"
namespace nostalgia::gfx {
void safeDelete(Context *ctx) noexcept {
delete ctx;
}
Context::Context(turbine::Context &tctx) noexcept: turbineCtx(tctx) {
}
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept {
auto ctx = ox::make_unique<Context>(tctx);
OX_RETURN_ERROR(initGfx(*ctx, params));
return ox::UPtr<Context>(std::move(ctx));
}
keel::Context &keelCtx(Context &ctx) noexcept {
return turbine::keelCtx(ctx.turbineCtx);
}
turbine::Context &turbineCtx(Context &ctx) noexcept {
return ctx.turbineCtx;
}
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <nostalgia/gfx/context.hpp>
namespace nostalgia::gfx {
struct BgCbbData {
unsigned bpp = 4;
};
class Context {
public:
turbine::Context &turbineCtx;
ox::Array<BgCbbData, 4> cbbData;
explicit Context(turbine::Context &tctx) noexcept;
Context(Context &other) noexcept = delete;
Context(Context const&other) noexcept = delete;
Context(Context const&&other) noexcept = delete;
virtual ~Context() noexcept = default;
[[nodiscard]]
ox::MemFS const&rom() const noexcept {
return static_cast<ox::MemFS const&>(*turbine::rom(turbineCtx));
}
};
}

View File

@@ -1,11 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <nostalgia/gfx/context.hpp>
namespace nostalgia::gfx {
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <ox/std/def.hpp>
#include <ox/std/realstd.hpp>
#include <keel/media.hpp>
#include <turbine/turbine.hpp>
#include <teagba/addresses.hpp>
#include <teagba/bios.hpp>
#include <nostalgia/gfx/core.hpp>
#include "gfx.hpp"
#define HEAP_BEGIN (reinterpret_cast<char*>(MEM_EWRAM_BEGIN))
#define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2)
#define HEAP_END (reinterpret_cast<char*>(MEM_EWRAM_BEGIN + HEAP_SIZE))
namespace ox {
using namespace nostalgia::gfx;
void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept {
// reset heap to make sure we have enough memory to allocate context data
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
OX_ALLOW_UNSAFE_BUFFERS_END
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
auto ctx = init(*tctx).unwrap();
std::ignore = initGfx(*ctx, {});
std::ignore = initConsole(*ctx);
setBgStatus(*ctx, 0, true);
clearBg(*ctx, 0);
auto const serr = ox::sfmt<ox::IString<23>>("Error code: {}", static_cast<int64_t>(err));
consoleWrite(*ctx, 32 + 1, 1, "SADNESS...");
consoleWrite(*ctx, 32 + 1, 4, "UNEXPECTED STATE:");
consoleWrite(*ctx, 32 + 2, 6, panicMsg);
if (err) {
consoleWrite(*ctx, 32 + 2, 8, serr);
}
consoleWrite(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
// print to terminal if in mGBA
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
}
abort();
}
}

View File

@@ -15,15 +15,41 @@
#include <nostalgia/gfx/gfx.hpp>
#include <nostalgia/gfx/tilesheet.hpp>
#include "context.hpp"
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
namespace nostalgia::gfx {
struct BgCbbData {
unsigned bpp = 4;
};
class Context final {
public:
turbine::Context &turbineCtx;
ox::Array<BgCbbData, 4> cbbData;
ox::Array<OffsetPair, 4> bgOffsets;
explicit Context(turbine::Context &tctx) noexcept: turbineCtx{tctx} {}
Context(Context const &other) noexcept = delete;
};
void safeDelete(Context *ctx) noexcept {
delete ctx;
}
keel::Context &keelCtx(Context &ctx) noexcept {
return turbine::keelCtx(ctx.turbineCtx);
}
turbine::Context &turbineCtx(Context &ctx) noexcept {
return ctx.turbineCtx;
}
static constexpr auto SpriteCount = 128;
ox::Error initGfx(Context&, InitParams const&) noexcept {
static ox::Error initGfx() noexcept {
for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) {
teagba::bgSetSbb(*bgCtl, 28);
}
@@ -34,15 +60,21 @@ ox::Error initGfx(Context&, InitParams const&) noexcept {
return {};
}
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&) noexcept {
auto ctx = ox::make_unique<Context>(tctx);
OX_RETURN_ERROR(initGfx());
return ctx;
}
ox::Error loadBgPalette(
Context&,
size_t palBank,
CompactPalette const&palette,
size_t page) noexcept {
size_t const palBank,
CompactPalette const &palette,
size_t const page) noexcept {
if (palette.pages.empty()) {
return {};
}
auto const paletteMem = MEM_BG_PALETTE + palBank * 16;
auto const paletteMem = ox::Span{MEM_BG_PALETTE} + palBank * 16;
for (auto i = 0u; i < colorCnt(palette, page); ++i) {
paletteMem[i] = color(palette, page, i);
}
@@ -51,14 +83,13 @@ ox::Error loadBgPalette(
ox::Error loadSpritePalette(
Context&,
CompactPalette const&palette,
size_t page) noexcept {
CompactPalette const &palette,
size_t const page) noexcept {
if (palette.pages.empty()) {
return {};
}
auto const paletteMem = MEM_SPRITE_PALETTE;
for (auto i = 0u; i < colorCnt(palette, page); ++i) {
paletteMem[i] = color(palette, page, i);
MEM_SPRITE_PALETTE[i] = color(palette, page, i);
}
return {};
}
@@ -79,15 +110,15 @@ void clearCbbs(Context &ctx) noexcept {
static ox::Error loadTileSheetSet(
Context &ctx,
ox::Span<uint16_t> tileMapTargetMem,
TileSheetSet const&set) noexcept {
TileSheetSet const &set) noexcept {
size_t tileWriteIdx = 0;
size_t const bppMod = set.bpp == 4;
for (auto const&entry : set.entries) {
for (auto const &entry : set.entries) {
OX_REQUIRE(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), entry.tilesheet));
if (set.bpp != ts->bpp && ts->bpp == 8) {
return ox::Error(1, "cannot load an 8 BPP tilesheet into a 4 BPP CBB");
}
for (auto const&s : entry.sections) {
for (auto const &s : entry.sections) {
auto const cnt = (static_cast<size_t>(s.tiles) * PixelsPerTile) >> bppMod;
for (size_t i = 0; i < cnt; ++i) {
auto const begin = static_cast<size_t>(s.begin) * (PixelsPerTile >> bppMod);
@@ -106,7 +137,7 @@ static ox::Error loadTileSheetSet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
@@ -133,11 +164,11 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept {
auto const cnt = (ts.pixels.size() * PixelsPerTile) / (1 + (ts.bpp == 4));
for (size_t i = 0; i < cnt; ++i) {
unsigned const cbb,
CompactTileSheet const &ts,
ox::Optional<unsigned> const &paletteBank) noexcept {
auto const cnt = ts.pixels.size() >> (ts.bpp == 4);
for (size_t i{}; i < cnt; ++i) {
auto const srcIdx = i * 2;
auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]);
auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]);
@@ -159,7 +190,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
TileSheetSet const&set) noexcept {
TileSheetSet const &set) noexcept {
auto const bpp = static_cast<unsigned>(set.bpp);
OX_RETURN_ERROR(loadTileSheetSet(ctx, MEM_BG_TILES[cbb], set));
// update bpp of all bgs with the updated cbb
@@ -183,12 +214,13 @@ static void setSpritesBpp(unsigned const bpp) noexcept {
ox::Error loadSpriteTileSheet(
Context &ctx,
CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept {
for (size_t i = 0; i < ts.pixels.size(); i += 2) {
uint16_t v = ts.pixels[i];
v |= static_cast<uint16_t>(ts.pixels[i + 1] << 8);
MEM_SPRITE_TILES[i] = v;
CompactTileSheet const &ts,
bool const loadDefaultPalette) noexcept {
for (size_t i{}; i < ts.pixels.size(); i += 2) {
MEM_SPRITE_TILES[i >> 1] =
static_cast<uint16_t>(
ts.pixels[i] |
(static_cast<uint16_t>(ts.pixels[i + 1]) << 8));
}
if (loadDefaultPalette && ts.defaultPalette) {
OX_RETURN_ERROR(loadSpritePalette(ctx, ts.defaultPalette));
@@ -199,14 +231,19 @@ ox::Error loadSpriteTileSheet(
ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept {
TileSheetSet const &set) noexcept {
auto const bpp = static_cast<unsigned>(set.bpp);
OX_RETURN_ERROR(loadTileSheetSet(ctx, {MEM_SPRITE_TILES, 32 * ox::units::KB}, set));
OX_RETURN_ERROR(loadTileSheetSet(ctx, MEM_SPRITE_TILES, set));
setSpritesBpp(bpp);
return {};
}
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&tile) noexcept {
void setBgTile(
Context &ctx,
uint_t const bgIdx,
int const column,
int const row,
BgTile const &tile) noexcept {
auto const tileIdx = static_cast<std::size_t>(row * tileColumns(ctx) + column);
// see Tonc 9.3
MEM_BG_MAP[bgIdx][tileIdx] =
@@ -216,7 +253,7 @@ void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&til
static_cast<uint16_t>(tile.palBank << 0xc);
}
void clearBg(Context &ctx, uint_t bgIdx) noexcept {
void clearBg(Context &ctx, uint_t const bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, static_cast<size_t>(tileRows(ctx) * tileColumns(ctx)));
}
@@ -224,39 +261,51 @@ uint8_t bgStatus(Context&) noexcept {
return (REG_DISPCTL >> 8u) & 0b1111u;
}
void setBgStatus(Context&, uint32_t status) noexcept {
void setBgStatus(Context&, uint32_t const status) noexcept {
constexpr auto BgStatus = 8;
REG_DISPCTL = (REG_DISPCTL & ~0b111100000000u) | status << BgStatus;
}
bool bgStatus(Context&, unsigned bg) noexcept {
bool bgStatus(Context&, unsigned const bg) noexcept {
return (REG_DISPCTL >> (8 + bg)) & 1;
}
void setBgStatus(Context&, unsigned bg, bool status) noexcept {
void setBgStatus(Context&, unsigned const bg, bool const status) noexcept {
constexpr auto Bg0Status = 8;
const auto mask = static_cast<uint32_t>(status) << (Bg0Status + bg);
auto const mask = static_cast<uint32_t>(status) << (Bg0Status + bg);
REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask);
}
void setBgBpp(Context&, unsigned bgIdx, unsigned bpp) noexcept {
void setBgBpp(Context&, unsigned const bgIdx, unsigned const bpp) noexcept {
auto &bgCtl = regBgCtl(bgIdx);
teagba::bgSetBpp(bgCtl, bpp);
}
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept {
void setBgCbb(Context &ctx, unsigned const bgIdx, unsigned const cbbIdx) noexcept {
auto &bgCtl = regBgCtl(bgIdx);
const auto &cbbData = ctx.cbbData[cbb];
auto const &cbbData = ctx.cbbData[cbbIdx];
teagba::bgSetBpp(bgCtl, cbbData.bpp);
teagba::bgSetCbb(bgCtl, cbb);
teagba::bgSetCbb(bgCtl, cbbIdx);
}
void setBgPriority(Context&, uint_t bgIdx, uint_t priority) noexcept {
void setBgPriority(Context&, uint_t const bgIdx, uint_t const priority) noexcept {
auto &bgCtl = regBgCtl(bgIdx);
bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11);
}
void hideSprite(Context&, unsigned idx) noexcept {
void setBgOffset(Context &ctx, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
ctx.bgOffsets[bg] = {.x = x, .y = y};
teagba::setBgOffset(bg, x, y);
}
void scrollBgOffset(Context &ctx, uint16_t const bg, int16_t const x, int16_t const y) noexcept {
auto &o = ctx.bgOffsets[bg];
o.x += x;
o.y += y;
teagba::setBgOffset(bg, o.x, o.y);
}
void hideSprite(Context&, unsigned const idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({
.attr0 = uint16_t{0b11 << 8},
@@ -264,7 +313,7 @@ void hideSprite(Context&, unsigned idx) noexcept {
});
}
void showSprite(Context&, unsigned idx) noexcept {
void showSprite(Context&, unsigned const idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({
.attr0 = 0,
@@ -272,31 +321,70 @@ void showSprite(Context&, unsigned idx) noexcept {
});
}
void setSprite(Context&, uint_t idx, Sprite const&s) noexcept {
void setSprite(Context&, uint_t const idx, Sprite const &sprite) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
uint16_t const eightBpp = s.bpp == 8;
uint16_t const eightBpp = sprite.bpp == 8;
teagba::addSpriteUpdate({
.attr0 = static_cast<uint16_t>(
(static_cast<uint16_t>(s.y & ox::onMask<uint8_t>(0b111'1111)))
(static_cast<uint16_t>(sprite.y & ox::onMask<uint8_t>(0b111'1111)))
| (static_cast<uint16_t>(1) << 10) // enable alpha
| (static_cast<uint16_t>(eightBpp) << 13)
| (static_cast<uint16_t>(s.spriteShape) << 14)),
| (static_cast<uint16_t>(sprite.spriteShape) << 14)),
.attr1 = static_cast<uint16_t>(
(static_cast<uint16_t>(s.x) & ox::onMask<uint8_t>(8))
| (static_cast<uint16_t>(s.flipX) << 12)
| (static_cast<uint16_t>(s.spriteSize) << 14)),
(static_cast<uint16_t>(sprite.x) & ox::onMask<uint8_t>(8))
| (static_cast<uint16_t>(sprite.flipX) << 12)
| (static_cast<uint16_t>(sprite.spriteSize) << 14)),
.attr2 = static_cast<uint16_t>(
// double tileIdx if 8 bpp
(static_cast<uint16_t>((s.tileIdx * (1 + eightBpp)) & ox::onMask<uint16_t>(8)))
| (static_cast<uint16_t>(s.priority & 0b11) << 10)),
(static_cast<uint16_t>((sprite.tileIdx * (1 + eightBpp)) & ox::onMask<uint16_t>(8)))
| (static_cast<uint16_t>(sprite.priority & 0b11) << 10)),
.idx = static_cast<uint16_t>(idx),
});
}
uint_t spriteCount(Context&) noexcept {
uint_t spriteCount(Context const &) noexcept {
return SpriteCount;
}
}
namespace ox {
void panic(char const*panicMsg, Error const&err, std::source_location const &src) noexcept {
using namespace nostalgia::gfx;
// reset heap to make sure we have enough memory to allocate context data
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
auto const heapBegin = reinterpret_cast<char*>(MEM_EWRAM.data());
auto const heapSz = MEM_EWRAM.size() / 2;
auto const heapEnd = reinterpret_cast<char*>(MEM_EWRAM.data() + heapSz);
ox::heapmgr::initHeap(heapBegin, heapEnd);
OX_ALLOW_UNSAFE_BUFFERS_END
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
auto ctx = init(*tctx).unwrap();
std::ignore = initGfx();
std::ignore = initConsole(*ctx);
setBgStatus(*ctx, 0, true);
clearBg(*ctx, 0);
auto const serr = ox::sfmt<ox::IString<23>>("Error code: {}", static_cast<int64_t>(err));
consoleWrite(*ctx, 32 + 1, 1, "SADNESS...");
consoleWrite(*ctx, 32 + 1, 4, "UNEXPECTED STATE:");
consoleWrite(*ctx, 32 + 2, 6, panicMsg);
if (err) {
consoleWrite(*ctx, 32 + 2, 8, serr);
}
consoleWrite(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
// print to terminal if in mGBA
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", src.file_name(), src.line(), panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
}
abort();
}
}
OX_ALLOW_UNSAFE_BUFFERS_END

View File

@@ -4,7 +4,6 @@
#include <ox/std/array.hpp>
#include <ox/std/fmt.hpp>
#include <ox/std/vec.hpp>
#include <keel/media.hpp>
@@ -15,23 +14,104 @@
#include <nostalgia/gfx/palette.hpp>
#include <nostalgia/gfx/tilesheet.hpp>
#include "context.hpp"
#include "gfx.hpp"
namespace nostalgia::gfx {
namespace renderer {
constexpr uint64_t TileRows = 128;
constexpr uint64_t TileColumns = 128;
constexpr uint64_t TileCount = TileRows * TileColumns;
constexpr uint64_t BgVertexVboRows = 4;
constexpr uint64_t BgVertexVboRowLength = 7;
constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength;
constexpr uint64_t BgVertexEboLength = 6;
constexpr uint64_t SpriteVertexVboRows = 4;
constexpr uint64_t SpriteVertexVboRowLength = 6;
constexpr uint64_t SpriteVertexVboLength = SpriteVertexVboRows * SpriteVertexVboRowLength;
constexpr uint64_t SpriteVertexEboLength = 6;
struct CBB: glutils::BufferSet {
bool updated = false;
ox::Array<uint32_t, 32768> pixels;
constexpr CBB() noexcept {
vertices.resize(TileCount * BgVertexVboLength);
elements.resize(TileCount * BgVertexEboLength);
}
};
struct SpriteBlockset: glutils::BufferSet {
bool updated = false;
constexpr SpriteBlockset(uint64_t spriteCount, uint64_t blocksPerSprite) noexcept {
vertices.resize(spriteCount * SpriteVertexVboLength * blocksPerSprite);
elements.resize(spriteCount * SpriteVertexEboLength * blocksPerSprite);
}
};
struct Background {
float priority = 0;
bool enabled = false;
unsigned cbbIdx = 0;
};
}
class Context {
public:
class Drawer final: public turbine::gl::Drawer {
private:
Context &m_ctx;
public:
explicit Drawer(Context &ctx) noexcept: m_ctx{ctx} {}
void draw(turbine::Context &tctx) noexcept override {
gl::draw(m_ctx, turbine::getScreenSize(tctx));
}
};
turbine::Context &turbineCtx;
glutils::GLProgram bgShader;
glutils::GLProgram spriteShader;
ox::Array<renderer::CBB, 4> cbbs;
renderer::SpriteBlockset spriteBlocks;
ox::Array<Sprite, 128> spriteStates;
ox::Array<GLfloat, 1024> bgPalette;
ox::Array<renderer::Background, 4> backgrounds;
Drawer drawer;
uint_t spriteCount = 0;
uint_t blocksPerSprite = 0;
explicit Context(turbine::Context &tctx, InitParams const &params) noexcept:
turbineCtx{tctx},
spriteBlocks{params.glSpriteCount, params.glBlocksPerSprite},
drawer{*this},
spriteCount{params.glSpriteCount},
blocksPerSprite{params.glBlocksPerSprite} {
}
Context(Context const&) = delete;
Context &operator=(Context const&) = delete;
~Context() noexcept {
turbine::gl::removeDrawer(turbineCtx, &drawer);
}
};
void safeDelete(Context *ctx) noexcept {
delete ctx;
}
keel::Context &keelCtx(Context &ctx) noexcept {
return turbine::keelCtx(ctx.turbineCtx);
}
turbine::Context &turbineCtx(Context &ctx) noexcept {
return ctx.turbineCtx;
}
namespace renderer {
static constexpr auto Scale = 1;
static constexpr auto PriorityScale = 0.01f;
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
void Drawer::draw(turbine::Context &tctx) noexcept {
gfx::gl::draw(m_ctx, turbine::getScreenSize(tctx));
}
static constexpr ox::CStringView bgvshadTmpl = R"glsl(
static constexpr ox::StringLiteral bgvshadTmpl{R"glsl(
{}
in vec2 vTexCoord;
in vec3 vPosition;
@@ -53,9 +133,9 @@ static constexpr ox::CStringView bgvshadTmpl = R"glsl(
vTexCoord.x,
vTexCoord.y * vTileHeight + vTileIdx * vTileHeight);
fPalOffset = vPalOffset;
})glsl";
})glsl"};
static constexpr ox::CStringView bgfshadTmpl = R"glsl(
static constexpr ox::StringLiteral bgfshadTmpl{R"glsl(
{}
out vec4 outColor;
in float fPalOffset;
@@ -69,9 +149,9 @@ static constexpr ox::CStringView bgfshadTmpl = R"glsl(
if (outColor.a == 0) {
discard;
}
})glsl";
})glsl"};
static constexpr ox::CStringView spritevshadTmpl = R"glsl(
static constexpr ox::StringLiteral spritevshadTmpl{R"glsl(
{}
in float vEnabled;
in vec3 vPosition;
@@ -88,9 +168,9 @@ static constexpr ox::CStringView spritevshadTmpl = R"glsl(
vPosition.z - 0.004,
1.0) * vEnabled;
fTexCoord = vTexCoord * vec2(1, vTileHeight);
})glsl";
})glsl"};
static constexpr ox::CStringView spritefshadTmpl = R"glsl(
static constexpr ox::StringLiteral spritefshadTmpl{R"glsl(
{}
out vec4 outColor;
in vec2 fTexCoord;
@@ -103,10 +183,10 @@ static constexpr ox::CStringView spritefshadTmpl = R"glsl(
if (outColor.a == 0) {
discard;
}
})glsl";
})glsl"};
[[nodiscard]]
static constexpr auto bgVertexRow(uint_t x, uint_t y) noexcept {
static constexpr auto bgVertexRow(uint_t const x, uint_t const y) noexcept {
return y * TileRows + x;
}
@@ -183,7 +263,7 @@ static void setTileBufferObject(
ox::spancpy<GLuint>(ebo, elms);
}
static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexcept {
static void initSpriteBufferObjects(Context const &ctx, glutils::BufferSet &bs) noexcept {
for (auto i = 0u; i < ctx.spriteCount; ++i) {
auto const vbo = ox::Span{bs.vertices}
+ i * static_cast<std::size_t>(SpriteVertexVboLength);
@@ -205,7 +285,7 @@ static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexce
static void initBackgroundBufferObjects(glutils::BufferSet &bs) noexcept {
for (auto x = 0u; x < TileColumns; ++x) {
for (auto y = 0u; y < TileRows; ++y) {
const auto i = bgVertexRow(x, y);
auto const i = bgVertexRow(x, y);
auto const vbo = ox::Span{bs.vertices}
+ i * static_cast<std::size_t>(BgVertexVboLength);
auto const ebo = ox::Span{bs.elements}
@@ -241,7 +321,13 @@ static void initSpritesBufferset(Context &ctx) noexcept {
// in float vEnabled;
auto const enabledAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vEnabled"));
glEnableVertexAttribArray(enabledAttr);
glVertexAttribPointer(enabledAttr, 1, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float), nullptr);
glVertexAttribPointer(
enabledAttr,
1,
GL_FLOAT,
GL_FALSE,
SpriteVertexVboRowLength * sizeof(float),
nullptr);
// in vec3 vPosition;
auto const posAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vPosition"));
glEnableVertexAttribArray(posAttr);
@@ -250,13 +336,14 @@ static void initSpritesBufferset(Context &ctx) noexcept {
// in vec2 vTexCoord;
auto const texCoordAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTexCoord"));
glEnableVertexAttribArray(texCoordAttr);
glVertexAttribPointer(texCoordAttr, 2, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float),
std::bit_cast<void*>(uintptr_t{4 * sizeof(float)}));
glVertexAttribPointer(
texCoordAttr, 2, GL_FLOAT, GL_FALSE, SpriteVertexVboRowLength * sizeof(float),
std::bit_cast<void*>(uintptr_t{4 * sizeof(float)}));
glBindVertexArray(0);
}
static void initBackgroundBufferset(
GLuint shader,
GLuint const shader,
glutils::BufferSet &bs) noexcept {
// vao
bs.vao = glutils::generateVertexArrayObject();
@@ -270,7 +357,13 @@ static void initBackgroundBufferset(
// vbo layout
auto const posAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vPosition"));
glEnableVertexAttribArray(posAttr);
glVertexAttribPointer(posAttr, 3, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float), nullptr);
glVertexAttribPointer(
posAttr,
3,
GL_FLOAT,
GL_FALSE,
BgVertexVboRowLength * sizeof(float),
nullptr);
auto const texCoordAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTexCoord"));
glEnableVertexAttribArray(texCoordAttr);
glVertexAttribPointer(
@@ -290,9 +383,9 @@ static void initBackgroundBufferset(
}
static glutils::GLTexture createTexture(
GLsizei w,
GLsizei h,
void const*pixels) noexcept {
GLsizei const w,
GLsizei const h,
void const *pixels) noexcept {
GLuint texId = 0;
glGenTextures(1, &texId);
glutils::GLTexture tex(texId);
@@ -300,7 +393,16 @@ static glutils::GLTexture createTexture(
tex.height = h;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width, tex.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA,
tex.width,
tex.height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -321,22 +423,22 @@ static void drawBackground(CBB &cbb) noexcept {
static void drawBackgrounds(
Context &ctx,
ox::Size const&renderSz) noexcept {
ox::Size const &renderSz) noexcept {
// load background shader and its uniforms
glUseProgram(ctx.bgShader);
const auto uniformSrcImgSz = glGetUniformLocation(ctx.bgShader, "fSrcImgSz");
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vXScale"));
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vTileHeight"));
const auto uniformBgIdx = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vBgIdx"));
const auto [wi, hi] = renderSz;
const auto wf = static_cast<float>(wi);
const auto hf = static_cast<float>(hi);
auto const uniformSrcImgSz = glGetUniformLocation(ctx.bgShader, "fSrcImgSz");
auto const uniformXScale = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vXScale"));
auto const uniformTileHeight = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vTileHeight"));
auto const uniformBgIdx = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vBgIdx"));
auto const [wi, hi] = renderSz;
auto const wf = static_cast<float>(wi);
auto const hf = static_cast<float>(hi);
glUniform1f(uniformXScale, hf / wf);
auto bgIdx = 0.f;
for (const auto &bg : ctx.backgrounds) {
for (auto const &bg : ctx.backgrounds) {
if (bg.enabled) {
auto &cbb = ctx.cbbs[bg.cbbIdx];
const auto tileRows = cbb.tex.height / (TileHeight * Scale);
auto const tileRows = cbb.tex.height / (TileHeight * Scale);
glUniform1f(uniformTileHeight, 1.0f / static_cast<float>(tileRows));
glUniform2f(
uniformSrcImgSz,
@@ -349,14 +451,14 @@ static void drawBackgrounds(
}
}
static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
static void drawSprites(Context &ctx, ox::Size const &renderSz) noexcept {
glUseProgram(ctx.spriteShader);
auto &sb = ctx.spriteBlocks;
const auto uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale");
const auto uniformTileHeight = glGetUniformLocation(ctx.spriteShader, "vTileHeight");
const auto [wi, hi] = renderSz;
const auto wf = static_cast<float>(wi);
const auto hf = static_cast<float>(hi);
auto const uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale");
auto const uniformTileHeight = glGetUniformLocation(ctx.spriteShader, "vTileHeight");
auto const [wi, hi] = renderSz;
auto const wf = static_cast<float>(wi);
auto const hf = static_cast<float>(hi);
glUniform1f(uniformXScale, hf / wf);
// update vbo
glBindVertexArray(sb.vao);
@@ -365,7 +467,7 @@ static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
glutils::sendVbo(sb);
}
// set vTileHeight uniform
const auto tileRows = sb.tex.height / (TileHeight * Scale);
auto const tileRows = sb.tex.height / (TileHeight * Scale);
glUniform1f(uniformTileHeight, 1.0f / static_cast<float>(tileRows));
// draw
glBindTexture(GL_TEXTURE_2D, sb.tex);
@@ -375,10 +477,10 @@ static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
static void loadPalette(
ox::Array<GLfloat, 1024> &palette,
size_t palOffset,
GLuint shaderPgrm,
CompactPalette const&pal,
size_t page = 0) noexcept {
size_t const palOffset,
GLuint const shaderPgrm,
CompactPalette const &pal,
size_t const page = 0) noexcept {
static constexpr std::size_t ColorCnt = 256;
for (auto i = palOffset; auto const c : pal.pages[page]) {
palette[i++] = redf(c);
@@ -389,14 +491,14 @@ static void loadPalette(
// make first color transparent
palette[palOffset + 3] = 0;
glUseProgram(shaderPgrm);
const auto uniformPalette = static_cast<GLint>(glGetUniformLocation(shaderPgrm, "fPalette"));
auto const uniformPalette = static_cast<GLint>(glGetUniformLocation(shaderPgrm, "fPalette"));
glUniform4fv(uniformPalette, ColorCnt, palette.data());
}
static void setSprite(
Context &ctx,
uint_t const idx,
Sprite const&s) noexcept {
Sprite const &s) noexcept {
// Tonc Table 8.4
struct Sz { uint_t x{}, y{}; };
static constexpr ox::Array<Sz, 12> dimensions{
@@ -422,12 +524,12 @@ static void setSprite(
auto const uY = static_cast<int>(s.y + 8) % 255 - 8;
oxAssert(1 < ctx.spriteBlocks.vertices.size(), "vbo overflow");
oxAssert(1 < ctx.spriteBlocks.elements.size(), "ebo overflow");
const auto spriteVboSz = ctx.blocksPerSprite * renderer::SpriteVertexVboLength;
const auto spriteEboSz = ctx.blocksPerSprite * renderer::SpriteVertexEboLength;
auto const spriteVboSz = ctx.blocksPerSprite * renderer::SpriteVertexVboLength;
auto const spriteEboSz = ctx.blocksPerSprite * renderer::SpriteVertexEboLength;
auto const vboBase = spriteVboSz * idx;
auto const eboBase = spriteEboSz * idx;
auto i = 0u;
const auto set = [&](int xIt, int yIt, bool enabled) {
auto const set = [&](int xIt, int yIt, bool enabled) {
auto const fX = static_cast<float>(uX + xIt * 8) / 8;
auto const fY = static_cast<float>(uY + yIt * 8) / 8;
auto const vboIdx = vboBase + renderer::SpriteVertexVboLength * i;
@@ -470,28 +572,23 @@ static void setSprite(
}
ox::Error initGfx(
Context &ctx,
InitParams const&initParams) noexcept {
const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion);
const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion);
const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, gl::GlslVersion);
const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, gl::GlslVersion);
OX_RETURN_ERROR(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(ctx.bgShader));
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const &params) noexcept {
auto ctx = ox::make_unique<Context>(tctx, params);
auto const bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion);
auto const bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion);
auto const spriteVshad = ox::sfmt(renderer::spritevshadTmpl, gl::GlslVersion);
auto const spriteFshad = ox::sfmt(renderer::spritefshadTmpl, gl::GlslVersion);
OX_RETURN_ERROR(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(ctx->bgShader));
OX_RETURN_ERROR(
glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(ctx.spriteShader));
for (auto &cbb : ctx.cbbs) {
initBackgroundBufferset(ctx.bgShader, cbb);
glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(ctx->spriteShader));
for (auto &cbb : ctx->cbbs) {
initBackgroundBufferset(ctx->bgShader, cbb);
}
renderer::initSpritesBufferset(ctx);
if (initParams.glInstallDrawer) {
turbine::gl::addDrawer(ctx.turbineCtx, &ctx.drawer);
renderer::initSpritesBufferset(*ctx);
if (params.glInstallDrawer) {
turbine::gl::addDrawer(ctx->turbineCtx, &ctx->drawer);
}
return {};
}
void shutdownGfx(Context &ctx) noexcept {
turbine::gl::removeDrawer(ctx.turbineCtx, &ctx.drawer);
return ctx;
}
struct TileSheetData {
@@ -504,12 +601,12 @@ struct TileSheetData {
}
};
static ox::Result<TileSheetData> normalizeTileSheet(
CompactTileSheet const&ts) noexcept {
static ox::Result<TileSheetData> normalizeTileSheet
(CompactTileSheet const &ts) noexcept {
const uint_t bytesPerTile = ts.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
const auto tiles = ts.pixels.size() / bytesPerTile;
auto const tiles = ts.pixels.size() / bytesPerTile;
constexpr int width = 8;
const int height = 8 * static_cast<int>(tiles);
int const height = 8 * static_cast<int>(tiles);
ox::Vector<uint32_t> pixels;
if (bytesPerTile == 64) { // 8 BPP
pixels.resize(ts.pixels.size());
@@ -523,37 +620,41 @@ static ox::Result<TileSheetData> normalizeTileSheet(
pixels[i * 2 + 1] = ts.pixels[i] >> 4;
}
}
return TileSheetData{std::move(pixels), width, height};
return TileSheetData{
.pixels = std::move(pixels),
.width = width,
.height = height
};
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
CompactPalette const&palette,
size_t page) noexcept {
size_t const palBank,
CompactPalette const &palette,
size_t const page) noexcept {
renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page);
return {};
}
ox::Error loadSpritePalette(
Context &ctx,
CompactPalette const&palette,
size_t page) noexcept {
CompactPalette const &palette,
size_t const page) noexcept {
ox::Array<GLfloat, 1024> pal;
renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page);
return {};
}
static ox::Result<TileSheetData> buildSetTsd(
Context &ctx,
TileSheetSet const&set) noexcept {
Context const &ctx,
TileSheetSet const &set) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
TileSheetData setTsd;
setTsd.width = TileWidth;
for (auto const&entry : set.entries) {
for (auto const &entry : set.entries) {
OX_REQUIRE(tilesheet, readObj<CompactTileSheet>(kctx, entry.tilesheet));
OX_REQUIRE(tsd, normalizeTileSheet(*tilesheet));
for (auto const&s : entry.sections) {
for (auto const &s : entry.sections) {
auto const size = s.tiles * PixelsPerTile;
for (auto i = 0; i < size; ++i) {
auto const srcIdx = static_cast<size_t>(i) + static_cast<size_t>(s.begin * PixelsPerTile);
@@ -566,8 +667,8 @@ static ox::Result<TileSheetData> buildSetTsd(
}
static void copyPixels(
CompactTileSheet const&ts,
ox::Span<uint32_t> dst,
CompactTileSheet const &ts,
ox::Span<uint32_t> const dst,
size_t const srcPxIdx,
size_t const pxlCnt) noexcept {
size_t idx{};
@@ -601,7 +702,7 @@ void clearCbbs(Context &ctx) noexcept {
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
CompactTileSheet const&ts,
CompactTileSheet const &ts,
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
@@ -624,9 +725,9 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
uint_t cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept {
uint_t const cbb,
CompactTileSheet const &ts,
ox::Optional<unsigned> const &paletteBank) noexcept {
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
auto const tiles = ts.pixels.size() / bytesPerTile;
OX_RETURN_ERROR(loadBgTileSheet(ctx, cbb, ts, 0, 0, tiles));
@@ -638,8 +739,8 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
TileSheetSet const&set) noexcept {
unsigned const cbb,
TileSheetSet const &set) noexcept {
OX_REQUIRE(setTsd, buildSetTsd(ctx, set));
ctx.cbbs[cbb].tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data());
return {};
@@ -647,8 +748,8 @@ ox::Error loadBgTileSheet(
ox::Error loadSpriteTileSheet(
Context &ctx,
CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept {
CompactTileSheet const &ts,
bool const loadDefaultPalette) noexcept {
OX_REQUIRE(tsd, normalizeTileSheet(ts));
oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
@@ -660,7 +761,7 @@ ox::Error loadSpriteTileSheet(
ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept {
TileSheetSet const &set) noexcept {
OX_REQUIRE(setTsd, buildSetTsd(ctx, set));
ctx.spriteBlocks.tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data());
return {};
@@ -668,21 +769,21 @@ ox::Error loadSpriteTileSheet(
void setBgTile(
Context &ctx,
uint_t bgIdx,
int column,
int row,
BgTile const&tile) noexcept {
uint_t const bgIdx,
int const column,
int const row,
BgTile const &tile) noexcept {
oxTracef(
"nostalgia.gfx.setBgTile",
"bgIdx: {}, column: {}, row: {}, tile: {}, palBank: {}",
bgIdx, column, row, tile.tileIdx, tile.palBank);
const auto z = static_cast<uint_t>(bgIdx);
const auto y = static_cast<uint_t>(row);
const auto x = static_cast<uint_t>(column);
const auto i = renderer::bgVertexRow(x, y);
auto const z = static_cast<uint_t>(bgIdx);
auto const y = static_cast<uint_t>(row);
auto const x = static_cast<uint_t>(column);
auto const i = renderer::bgVertexRow(x, y);
auto &cbb = ctx.cbbs[z];
const auto vbo = ox::Span{cbb.vertices} + i * renderer::BgVertexVboLength;
const auto ebo = ox::Span{cbb.elements} + i * renderer::BgVertexEboLength;
auto const vbo = ox::Span{cbb.vertices} + i * renderer::BgVertexVboLength;
auto const ebo = ox::Span{cbb.elements} + i * renderer::BgVertexEboLength;
auto &bg = ctx.backgrounds[bgIdx];
renderer::setTileBufferObject(
static_cast<uint_t>(i * renderer::BgVertexVboRows),
@@ -698,7 +799,7 @@ void setBgTile(
cbb.updated = true;
}
void clearBg(Context &ctx, uint_t bgIdx) noexcept {
void clearBg(Context &ctx, uint_t const bgIdx) noexcept {
auto &cbb = ctx.cbbs[static_cast<std::size_t>(bgIdx)];
initBackgroundBufferObjects(cbb);
cbb.updated = true;
@@ -714,61 +815,65 @@ uint8_t bgStatus(Context &ctx) noexcept {
return out;
}
void setBgStatus(Context &ctx, uint32_t status) noexcept {
void setBgStatus(Context &ctx, uint32_t const status) noexcept {
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
ctx.backgrounds[i].enabled = (status >> i) & 1;
}
}
bool bgStatus(Context &ctx, uint_t bg) noexcept {
bool bgStatus(Context &ctx, uint_t const bg) noexcept {
return ctx.backgrounds[bg].enabled;
}
void setBgStatus(Context&ctx, uint_t bg, bool status) noexcept {
void setBgStatus(Context&ctx, uint_t const bg, bool const status) noexcept {
ctx.backgrounds[bg].enabled = status;
}
void setBgBpp(Context&, unsigned, unsigned) noexcept {}
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
void setBgCbb(Context &ctx, uint_t const bgIdx, uint_t const cbbIdx) noexcept {
auto &bg = ctx.backgrounds[bgIdx];
bg.cbbIdx = cbbIdx;
}
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept {
void setBgPriority(Context &ctx, uint_t const bgIdx, uint_t const priority) noexcept {
auto &bg = ctx.backgrounds[bgIdx];
bg.priority = static_cast<float>(priority & 0b11);
}
void hideSprite(Context &ctx, uint_t idx) noexcept {
void setBgOffset(Context&, uint16_t const, int16_t const, int16_t const) noexcept {
}
void scrollBgOffset(Context&, uint16_t const, int16_t const, int16_t const) noexcept {
}
void hideSprite(Context &ctx, uint_t const idx) noexcept {
auto &s = ctx.spriteStates[idx];
s.enabled = false;
renderer::setSprite(ctx, idx, s);
}
void showSprite(Context &ctx, uint_t idx) noexcept {
void showSprite(Context &ctx, uint_t const idx) noexcept {
auto &s = ctx.spriteStates[idx];
s.enabled = true;
renderer::setSprite(ctx, idx, s);
}
void setSprite(Context &ctx, uint_t idx, Sprite const&sprite) noexcept {
void setSprite(Context &ctx, uint_t const idx, Sprite const &sprite) noexcept {
auto &s = ctx.spriteStates[idx];
s = sprite;
renderer::setSprite(ctx, idx, s);
}
uint_t spriteCount(Context &ctx) noexcept {
uint_t spriteCount(Context const &ctx) noexcept {
return ctx.spriteCount;
}
namespace gl {
ox::Size drawSize(int scale) noexcept {
ox::Size drawSize(int const scale) noexcept {
return {240 * scale, 160 * scale};
}
void draw(gfx::Context &ctx, ox::Size const&renderSz) noexcept {
void draw(Context &ctx, ox::Size const &renderSz) noexcept {
glViewport(0, 0, renderSz.width, renderSz.height);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
@@ -783,7 +888,7 @@ void draw(gfx::Context &ctx, ox::Size const&renderSz) noexcept {
glDisable(GL_BLEND);
}
void draw(gfx::Context &ctx, int scale) noexcept {
void draw(Context &ctx, int const scale) noexcept {
draw(ctx, drawSize(scale));
}

View File

@@ -10,17 +10,17 @@ namespace nostalgia::gfx {
constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32;
int tileColumns(Context&) noexcept {
int tileColumns(Context const&) noexcept {
return GbaTileColumns;
}
int tileRows(Context&) noexcept {
int tileRows(Context const&) noexcept {
return GbaTileRows;
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
size_t const palBank,
ox::StringViewCR palettePath) noexcept {
OX_REQUIRE(pal, keel::readObj<CompactPalette>(keelCtx(ctx), palettePath));
return loadBgPalette(ctx, palBank, *pal, 0);
@@ -28,8 +28,8 @@ ox::Error loadBgPalette(
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept {
size_t const palBank,
ox::FileAddress const &paletteAddr) noexcept {
OX_REQUIRE(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadBgPalette(ctx, palBank, *pal, 0);
}
@@ -43,18 +43,18 @@ ox::Error loadSpritePalette(
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
ox::FileAddress const &paletteAddr) noexcept {
OX_REQUIRE(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr));
return loadSpritePalette(ctx, *pal, 0);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tsAddr,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept {
unsigned const cbb,
ox::FileAddress const &tsAddr,
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
OX_REQUIRE(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tsAddr));
return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt);
}
@@ -63,27 +63,27 @@ ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tsPath,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept {
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
OX_REQUIRE(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tsPath));
return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
unsigned const cbb,
ox::StringViewCR tilesheetPath,
ox::Optional<unsigned> const&paletteBank) noexcept {
ox::Optional<unsigned> const &paletteBank) noexcept {
OX_REQUIRE(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetPath));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::Optional<unsigned> const&paletteBank) noexcept {
unsigned const cbb,
ox::FileAddress const &tilesheetAddr,
ox::Optional<unsigned> const &paletteBank) noexcept {
OX_REQUIRE(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
@@ -91,15 +91,15 @@ ox::Error loadBgTileSheet(
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::StringViewCR tilesheetPath,
bool loadDefaultPalette) noexcept {
bool const loadDefaultPalette) noexcept {
OX_REQUIRE(ts, readObj<CompactTileSheet>(keelCtx(ctx), tilesheetPath));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
ox::FileAddress const &tilesheetAddr,
bool const loadDefaultPalette) noexcept {
OX_REQUIRE(ts, readObj<CompactTileSheet>(keelCtx(ctx), tilesheetAddr));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
@@ -235,7 +235,13 @@ constexpr ox::Array<char, 128> charMap = {
50, // ~
};
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, unsigned tile, unsigned palBank) noexcept {
void setBgTile(
Context &ctx,
uint_t const bgIdx,
int const column,
int const row,
unsigned const tile,
unsigned const palBank) noexcept {
setBgTile(ctx, bgIdx, column, row, {
.tileIdx = tile,
.palBank = palBank,
@@ -243,7 +249,7 @@ void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, unsigned tile, u
}
ox::Error initConsole(Context &ctx) noexcept {
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.nts");
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
setBgStatus(ctx, 0b0001);
setBgCbb(ctx, 0, 0);

View File

@@ -89,7 +89,7 @@ static class: public keel::Module {
} const mod;
keel::Module const*keelModule() noexcept {
keel::Module const *keelModule() noexcept {
return &mod;
}

View File

@@ -61,7 +61,7 @@ ox::Error convertPaletteV4ToPaletteV5(
for (auto &s : src.pages) {
ox::Vector<PaletteColorV2> colors;
colors.reserve(s.colors.size());
for (auto const&c : s.colors) {
for (auto const &c : s.colors) {
colors.emplace_back(c.r, c.g, c.b, c.a);
}
dst.pages.emplace_back(PalettePageV2{

Some files were not shown because too many files have changed in this diff Show More