When a computed jump cannot be resolved to a jump table, every instruction in
the function becomes an entry point, because the jump could land on any of
them. That fallback was also applied to JALR, which is not a jump but a call:
it transfers control to another function and returns to the instruction after
the delay slot. That return address is already queued as a resume target a few
lines above, so nothing else in the function needs to be reachable from
outside.
Indirect calls are ordinary code -- function pointers, virtual dispatch,
callbacks -- so the fallback fired constantly. On a 3 MB PS2 executable, 2,210
of the 2,422 unresolved sites were JALR, and 1,078 of the 1,282 affected
functions contained no unresolved jump at all.
Restrict the fallback to JR. Promoted entries drop from 189,876 to 1,688,
registered table entries from 156,783 to 75,386, the generated registration
file from 13 MB to 6 MB, and total output from 180 MB to 163 MB. Every
indirect call site in real code keeps its return-address resume entry (the
only sites that lose one are bogus functions carved out of rodata, where the
address is outside the function anyway).
* refactor: from guest threads to EE scheduler
* feat: bad wip mpeg fix for code veronica
* feat: cheap copy from host
feat: small perf o vsync tick
* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor
* fix: fix lotr tests
* fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides
* feat: revert wrong changes
* refactor: change GS architecture
* refactor: from guest threads to EE scheduler
* feat: bad wip mpeg fix for code veronica
* feat: cheap copy from host
feat: small perf o vsync tick
* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor
* fix: fix lotr tests
* fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides
* feat: revert wrong changes
* refactor: from guest threads to EE scheduler
* feat: bad wip mpeg fix for code veronica
* feat: cheap copy from host
feat: small perf o vsync tick
* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor
* fix: fix lotr tests
* feat: implement fix and changes based on dark cloud report
fix: fix GS AFAIL for RGB/alpha/Z, ZMSK
fix: fix VU1 flags mask and pipeline
fix: small VU1 cache fix
feat: __ct__, __sinit_ are not sillent stubs anymore
* feat: fix song JP pulling
* feat: sound update for lotR
* feat: prevent guest execution to be very slow
* fix: small gs size bug
* feat: refactor VU
fix: fix cliping and other issues on gs
fix: fix wrong vu0 register on recompiler
* fix fix ACC scheduler stall
feat: remove unused test
fix: .fix overflow e underflow on FMAC
* feat: small setting for windows test
Fill the remaining TODO_NAMED bodies in Kernel/Stubs/VU.cpp so the
out-of-line libvu0 macro-mode routines write their documented results to
the caller's output operand instead of leaving guest memory untouched (the
TODO_NAMED stub throws, or returns -1 once its per-name warning budget is
spent, and never writes the destination).
Implements the matrix/geometry/clip/lighting entry points:
CameraMatrix, InversMatrix, MulMatrix, TransMatrix, RotMatrix,
NormalLightMatrix, LightColorMatrix, DropShadowMatrix, ViewScreenMatrix,
RotTransPers/RotTransPersN, ClipScreen/ClipScreen3/ClipAll, MulVector,
ScaleVectorXYZ, DivVector/DivVectorXYZ, InterVector/InterVectorXYZ,
ClampVector, ecossin. Pure input->output arithmetic over guest memory
through the existing getMemPtr/getConstMemPtr and getRegU32/ctx->f[]
accessors already used by the implemented sceVu0 functions in the same
file. No new runtime state, no signature changes, no VU.h changes.
The clip and view/shadow routines provide the functional contract callers
rely on (nonzero => offscreen; projection by formula shape) rather than a
bit-exact reproduction of the COP2 sticky clip-flag register.
Adds ps2xTest/src/ps2_vu_tests.cpp covering each routine against its
documented formula.
* feat: implement memory card IOP
* feat: IOP trace
* feat: move IOP logic to ps2xIOP
refactor: small refactor on audio api on runtime
* feat: android support
feat: prevent race on GS
feat: a bit cleanup and reimplement on memory card
* feat: finish guest thread
feat: android build support
feat: vita build support with suspicious setup scripts
* feat: remove idea from track
The "Semaphore poll/signal remains stable under host-thread contention"
test created the semaphore full (init == max == 1), so SignalSema could
only succeed after PollSema had already freed a slot. With no start
barrier, under host-thread contention the signaler thread could run all
64 of its iterations before the poller's first timeslice, making every
SignalSema legitimately return KE_SEMA_OVF and leaving signalOkCount at
0 — a false failure of "contended SignalSema should observe successful
releases". An earlier investigation of the unfixed test observed this
twice in 24 contended (8-way-parallel) full-suite runs and never in 20
serial runs; CI has independently hit the same assertion on the
unrelated draft PR #174, confirming the trigger is host scheduling, not
the code under review.
Seed the semaphore with headroom (init=1, max=2) so the first PollSema
and the first SignalSema each succeed regardless of scheduling order,
and add a start barrier so both workers start together, maximizing the
opportunity to interleave. Widen the final-count range check to the new
max. The semaphore implementation is unchanged; both threads still
contend concurrently on the same per-semaphore mutex.
sceGifPkRefLoadImage seeded its A+D header GIFtag with nloop=4 via
makeGiftagAplusD(4u), then closePacketGifTag computed the appended
register-qword count (4) from the write-cursor delta and ADDED it to the
seed, finalizing nloop=8 for a tag with only 4 A+D register qwords
(BITBLTBUF/TRXPOS/TRXREG/TRXDIR). A GIF parser consuming that tag eats the
following IMAGE GIFtag and its first payload qwords as bogus A+D data,
starving the CLUT/texture upload that the setup packet precedes (e.g. DQ8
font-glyph CLUTs staying all-zero).
Seed an open A+D tag (nloop=0, nreg=1, EOP clear) instead and let
closePacketGifTag add the true count, finalizing 0x1000000000000004 -- the
value the regression test pins. The seed is written via a named
makeGiftagAplusDOpen(nloop) helper in Support.h (mirrors makeGiftagAplusD but
leaves EOP/bit 15 clear for a chained tag whose nloop is finalized at close),
rather than a bare (1ULL << 60) literal, to keep the file's
GIFtag-construction convention consistent. makeGiftagAplusD(0u) can't be used
because it always sets EOP.
Adds a byte-level regression test that drives sceGifPkRefLoadImage (setup
only, qwcRemaining=0) against a scratch packet-builder state and asserts the
finalized header tag lo/hi, the four A+D register descriptors (0x50..0x53),
and their four register payloads (BITBLTBUF dbp/dbw/psm, TRXPOS, TRXREG
width/height, TRXDIR) -- pinning the full setup packet.
Full build clean; ps2x_tests 297/297.
Real PS2 pads power up in DIGITAL mode (CURID 4, mode byte 0x41) and only
switch to analog (CURID 7, 0x73) when the game calls scePadSetMainMode. The
three open-time sites in Pad.cpp incorrectly set analogMode=true, so
scePadInfoMode(PAD_MODECURID) reported analog from frame 0. Games that gate
logic on the analog transition (e.g. DQ8 fn_165b20) saw an impossible state.
- PadPortState default, initializePadPortLocked, scePadPortOpen: analogMode=false
- scePadSetMainMode remains the only path into analog mode (unchanged)
- Updated the existing pad-info test's at-open CURID expectation (7 -> 4)
- Added a regression test: open reports digital (CURID 4, 0x41), then
scePadSetMainMode(mode=1) switches to analog (CURID 7, 0x73)
Add byte-level regression tests for the GS "high" indexed texture formats,
which store their index in the alpha byte of a shared PSMCT32 word -- T4HL in
bits 24-27, T4HH in bits 28-31, T8H in the full byte 24-31. The format-aware
VRAM path (the #140 refactor) already implements these at main; these tests
pin the plane-separation and over-transfer behavior so it can't silently
regress.
- Plane separation: uploading distinct T4HL then T4HH patterns to the same dbp
leaves both planes intact (RMW into the shared CT32 word), cross-checked
against GSMem::ReadP4HL/ReadP4HH.
- T8H coverage: uploads the full byte into bits 24-31 via a real BITBLTBUF+GIF
IMAGE transfer (one byte per texel through WriteP8H) and round-trips it via
GSMem::ReadP8H. T8H takes the plain byte-store branch of
PixelStorageTraits::Write and its own upload loop, distinct from the
T4HL/T4HH nibble RMW path, so it needs independent coverage.
- Clobber interaction: a T4HL nibble upload over a prior T8H byte overwrites
bits 24-27 with the nibble and preserves bits 28-31 (the T8H byte's high
nibble) -- the hardware-modeled RMW outcome.
- Sampled channels: each plane resolves through its own 16-entry CT32 CLUT to
the expected RGBA, with distractor CLUT entries so a cross-plane nibble read
produces a non-matching color.
- Over-transfer hard-stop: an ~8x oversized T4HL IMAGE payload writes only
rrw*rrh texels and deactivates the transfer (trxdir=3), and a subsequent
transfer to a different dbp is byte-correct.
Test-only; no product code change. ps2x_tests: 299/299.
* feat: added guestBranchKind enum to categorize branch types
feat: added missingFunctionPolicy enum to define behaviors for missing function scenarios
refactor: added handle guest branches and report missing functions
feat lookupFunction to utilize new dispatch logic and improve error handling for unregistered functions
* fix: fix test conflict
* feat: added debug sound driver logs
* feat: emmiter for return
* feat: added recompiler reporter
feat: added strict diagnostics flag for heavy debug calls
* feat: staticc table insted of hashmap for runtime
* feat: back file to ignore
* feat: explode code across helpers and classes
* feat: update codegen test
feat: better guest nop check
* feat: fix link problem on linux
* feat: fix Segmentation fault
* feat: added recompile replace for DMA and MMIO
feat: added a clean memory helpers
feat: use memory helpers across the project
feat: fix ucrt on msvc
* feat: undo messup merge
updateGsCsrFieldForVSync runs on the detached vsync worker and updated the
FIELD bit with a non-atomic read-modify-write of GSRegisters::csr while
guest threads concurrently read/write the same word (MMIO read32/read64 and
the W1C handling in write32/write64) and the GIF path sets SIGNAL/FINISH.
Even though the writers touch disjoint bits, a whole-word RMW loses the
other side's update: a clobbered SIGNAL/FINISH set hangs a game
synchronizing on GS completion, a clobbered W1C clear re-asserts a handled
interrupt, and a clobbered FIELD toggle stalls interlace field polling.
ThreadSanitizer flags the race on main (updateGsCsrFieldForVSync vs
PS2Memory::write64 and GS::writeRegister).
Make the field std::atomic<uint64_t> and perform every update as a single
atomic RMW:
- vsync FIELD toggle -> fetch_or / fetch_and
- MMIO W1C writes -> compare_exchange loop in shared helpers (a
load-then-store pair would still race); a 32-bit store to the CSR's upper
dword previously bypassed the W1C special case entirely and went through
the plain merge branch - both halves now share the same atomic helper
with unchanged guest-visible semantics
- GIF SIGNAL/FINISH -> fetch_or
- reads -> load()
std::atomic<uint64_t> is lock-free on all supported targets (static_assert
added), the struct's size/alignment asserts are unchanged, GSRegisters is
never copied by value, and default (seq_cst) ordering is used throughout -
these operations are rare (vblank ticks, GIF signals, CSR MMIO), so
reviewability wins over micro-optimization.
New regression test: two racer threads each own one status bit (SIGNAL /
FINISH) and loop 80k GIF-set + W1C-clear cycles verifying their own bit
after each half-op while the vsync worker toggles FIELD. Fails 20/20 runs
against the previous code, passes 50/50 with the fix, ~350ms runtime, no
sanitizer needed.
* feat: added guestBranchKind enum to categorize branch types
feat: added missingFunctionPolicy enum to define behaviors for missing function scenarios
refactor: added handle guest branches and report missing functions
feat lookupFunction to utilize new dispatch logic and improve error handling for unregistered functions
* fix: fix test conflict
* feat: added debug sound driver logs
* feat: emmiter for return
* feat: added recompiler reporter
feat: added strict diagnostics flag for heavy debug calls
* feat: staticc table insted of hashmap for runtime
* feat: back file to ignore
* feat: explode code across helpers and classes
* feat: update codegen test
feat: better guest nop check
* feat: fix link problem on linux
* feat: fix Segmentation fault
* feat: added ffmepg as dependency
* feat: wip decoder video
* feat: some perf and cleanup
* feat: added generic MPEG stream notification
* feat: CMakeLists.txt in ps2xStudio to configure SDL2 build options for static linking.
fix: fix ffmpeg setup for linux
fix: now MPEG decoder now identify that movie has ended and can play again anytime
feat: better audio stub to not block games
* feat: fix expansion test
* feat: foo
* a
* feat: finally added a helper to to prevent thread starvation
* feat: added basic vu0 code execution
* feat: added yield Guest Execution After Wake to prevent deadlock
* feat: added options on cmake for logs
feat: better input for keyboard pad
* feat: small corrections like top and itop vu branches etc
* feat: changes
* feat: working feature
* feat: fatal frame iop
* feat: test fix
feat: z buffer fix
* fix: gix GsPutIMR IMR
* feat: added rl imgui
* feat: added helper to get snapshot
* feat: added debug panel consuming snapshots
* feat: added pad snapshot
feat: added RCP debug events
* feat: final cleanup from old code
* feat: added EE timer counter
feat: applyed sound driver for Lotr
feat: better check for sound driver compat layout
feat: enquee and cosumed DMa cause
feat: added Pad execCMd
feat: update GS vsync signal flag
feat: custom IOPs for LotR
* feat: small cleanups
* fix: fix wrong import
* fix: semaphore syscalls return sid on success instead of KE_OK
The PS2 EE BIOS returns the semaphore ID on success for all semaphore
syscalls, not zero. PollSema, WaitSema, SignalSema, and DeleteSema were
all returning KE_OK (0) on success, which breaks games that compare the
return value against the semaphore ID.
DQ8's init code polls a mutex semaphore at 0x12A670 and checks the result
against the semaphore ID using bne. With KE_OK returned, the comparison
always fails and the game spins forever at PC 0x164978 and never starts.
Other games that follow the same EE BIOS convention would hit the same
problem. CreateSema already returned the ID correctly; this brings the
other four operations in line with the same convention.
The fix is five changes in Sync.cpp: the four return sites are updated to
return sid, and the count-decrement guard in WaitSema is changed from
ret == 0 to ret >= 0. The guard change is necessary because ret is now
seeded to sid (a positive value) on the success path, and the old equality
check would have silently stopped decrementing the semaphore count. Error
paths (KE_WAIT_DELETE, KE_RELEASE_WAIT) are negative and still correctly
bypass the decrement.
Tests are updated to expect sid instead of KE_OK on success paths, and new
test cases cover the blocked-wait-then-signal path (the actual DQ8 scenario),
force-release via ReleaseWaitThread, and the count-decrement guard directly.
* fix: update stale KE_OK assertions in expansion and SIF RPC tests
Two test files were not updated alongside the semaphore return-value change.
PollSema and SignalSema now return sid on success; update the four assertions
that expected KE_OK on those success paths.
* fix: tighten WaitSema count-decrement guard to ret == sid
ret is seeded to sid on success and only ever overwritten with negative
error codes, so ret == sid precisely expresses "this wait acquired this
semaphore" — more explicit than the looser ret >= 0.
Suggested by ran-j in PR review.
* [runtime] Memory swizzling rework
Reimplementation of memory swizzling supporting all valid GS texture
storage types.
An additional optimization was done to improve the speed of lookups.
Since page access is linear, we can precompute the non-linear bit
(blocks and columns) for an entire page for each format. This reduces
the runtime calculation to just calculating the correct page in 2d
memory space and then performing a lookup in the table to get the
location in memory inside a page. Since all page accesses are the same,
this works across all pages. Speed improvements should be compounded by
the number of accesses but there might be some reductions as a result of
actually implementing formats that were not implemented before.
I took care to do this with simple math. GS swizzling is complicated and
optimizing it for debug builds is outside the scope of my current work.
This is just the standalone code. It will be worked into the current
rasterizer in a follow up commit.
* [runtime] Reimplement GS host -> local transfers
Reimplement the host -> local transfers using new swizzling code
* [runtime] Reimplement sampling with new swizzling
Reimplements the rasterizer sampling code to use the new swizzling code
* [runtime] Replace fb writes with new swizzling
Replace the framebuffer write code with the new swizzling code
* [runtime] Reduce vram read/write to func lookup
Reduces the vram read write switches to a function lookup
* [tests] fix GS tests not handling depth test
* [runtime] z interpolation and write support
Add support for interpolating z from primitives and writing to the z
buffer after z testing and masking
* [runtime] local to local transfer rework
* [runtime] host readout uses new sizzling code
plus cleanup some dead code
* [runtime] rework local->host transfer
update to the new swizzling code
* [runtime] update clear function with new swizzling
* feat: invert codegen hight to low convertion
feat: added copy and GetEntryAddress
feat: handle truncated DMAC
* feat: always use address on analyzer now
* feat: correct pick syscalls ID
* feat: added deci2Call
* feat: added wip dbcmain IOP
* feat: added InitTLB
feat: added err logs on thread for debug sus crash
* fix: fix SetupHeap for strange cases
* feat: fix incorrect SetupHeap test(it use a wrong idea on how heap allocate memory)
* feat: added memalign and memalign_r
feat: added GetOsdConfigParam2 and SetOsdConfigParam2 but idk if was a good idea
* feat: added more memory stuff
* feat: back to library functions
* feat: modularize elf analyzer
feat: added experimental sce symbol scanner
feat: change analyzer order
feat: small optimizations on analyzer
* feat: remove example_config.toml because its causing confusion on some people
* feat: embed sce symbol but leave optional import path
feat: killed skip function on analyzer but leave it so you can skip manual if you want
* feat: pin elfio tag
* feat: manually create string view with size
* feat: update ghidra script
* feat(recomp): Reduce recompiler output memory usage
Stream output generation, add low-memory config controls, and avoid
pathological indirect-jump switch expansion in generated C++.
Low-memory mode now avoids retaining per-instruction disassembly strings
while still emitting asm comments during output generation. Output workers
are bounded/configurable, combined output is streamed, and decoded buffers
are released after generation.
Also document the new output memory settings.
* fix(recomp): added tests for unregistered JR/JALR, updated fallback logic to cover JR/JALR, moved Rabbitizer formatting into R5900Decoder
* feat: remove memory and pad from stub section
* feat: add support for resume entry targets in CodeGenerator (this allow jumps in address outside function)
feat: refactor entry point discovery one more try to reduce big generated file
* feat: optmizations for release build
* feat: remove unused file
* feat: added some test cases for code gen
* feat: added log macro and remove win specific code
* feat: refactor runtime folder structure
feat: added reset sound driver RPC state and compatibility layout
feat: rename and added new test
feat: update RPC calls to use defined constants
feat: added more PSMC(16, 32)
feat: change cd read to try find the asset ignoring case sensitive
fix: fix some render problems
feat: add logs on pad
feat: added more RPC handles
* feat: added game override for code veronica
* feat: apply vita patch
* feat: flags to disable build
* feat: fix merges
feat: break a lot of tests
* feat: better throw error on empty cd path
feat: remove recompiler unusde function
feat: apply missing patch
* feat: gamedp is now part of lib
feat: missing file
* feat: small cleanup
* feat: missing vita changes
* feat: fix more merge
* feat: fix tests
* feat: last missing feature
* feat: added missing import
* feat: rename test local functions
* feat: init syscall on ps2 list
* feat: added DMA helpers
* feat: faster builds
feat: more implement for darkcloud
* feat: back missing file
* feat: added missing includes
* feat: remove test
* feat: missing include
* feat: read register funtion
* feat: build fix
* feat: force exit on detach thread
* fix: CRITICAL fix on code gen on generating BEQ translation, I added a small yeld because goto could spin forever and monopolize guest execution
* feat: add scratchpad alias base and improve scratchpad address handling
* feat: added debug logging on GifArbiter for submit and drain operations
* feat: add interrupt and thread management syscall implementations
fix: change some IDs calls to match ps2sdk
* feat: added vif1 logs
* feat: added logs on gs gpu
feat: added performLocalToLocalTransfer to GS emulation path for TRXDIR = 2. (emulates the PS2 GS “copy this rectangle from one place in VRAM to another”)
* feat: added PSMT8 and refactor PSMT4
* feat: some identation on vu1
feat: added some logs on vu1
* feat: added GuestExecutionScope to temporarily stop owning guest execution, then restore it exactly as it was.
feat: added vsync wizardry
feat: added some regression test
* fix: fix gs logger
* feat: remove extra logs I think they will help no one
feat: move join all threads to prevent the app to get stuck on close, but now it random crash on closing
feat: one more small test on psmt4 to try fix ghosting on re code veronica
* feat: added a small case for exporter from ghidra for metal slug 3
* feat: added ugly code to pass on test
* docs: deprecate the local analyzer workflow in favor of Ghidra
feat: improve the Ghidra exporter for stripped games and internal entry points
fix: correct FindAddress behavior in the runtime
fix: emit missing delay-slot code in recompiler edge cases
feat: add SetSyscall support from @Whoneon
feat: add dispatchSyscallOverride support from @Whoneon
fix: fix Unmatched '{' due to missing newlines from issue #96
feat: delete python ghidra script I never updated it anyway
feat: added a lot more of regression test
feat: added a lot of logs to help debug on runtime
fix: fix wrong syscall ID on runtime
* pad: implement basic input mapping and stubs
Add a minimal libpad implementation backed by raylib input
Provide override hooks for deterministic tests
Add pad input tests and link runtime into test target
* FIX: moved pad override test hooks to ps2_call_list.h
* pad: move test hooks to X macro list + removing __cplusplus ifdef
* removed one last ifdef remaining
* refresh PR merge status
---------
Co-authored-by: Ranieri <ran-junior@hotmail.com>
* feat: small fixes on code gen
* feat: added code gen test
* feat: rename IOP
* fix: fix special case on JR
feat: added code generator test
* feat: ps2 logs now need special macros
* feat: a lot of regressions test
feat: use test to fix bugs on runtime
fix: fix incorrect instructions on code generator
feat: added missing decode on r5900 decoder
feat: added scissor on rasterizer
* feat: better ghidra plugin analyzer
fix: fix real bug on function finding on elf analyzer
* feat: some logs on GS
feat: added more syscalls stubs
feat: added more ps2 stubs
* feat: added missing stub
* feat: basic gs
feat: basic rasterizer
fix: a lot of fixes to runtime stubs
feat: basic vif intercepter
feat: return "ok" for some stubs
feat: disassembly code as comment
fix: fix code gen instructions set
fix: again jump
feat: remove unused macro
fix: fix some problematic macros
feat: track delayslots on runtime
and many more
* feat: added missing files
* fix: fix instruction test
* mc0: map memory card paths to mcRoot and related io tests
* Fix mc0 test setup to initialize temp paths
* fix: implementing WIN32 I/O support in syscalls
* fix: avoid fioWrite deadlock
Do not lock the fd map while calling getHostFile; use the syscall file mutex around fwrite instead
* feat: split runtime code in small files to be easy to develop
* feat: split stubs in inl files
* feat: function auto link function treat functions with underscore as same as without underscore
* feat: remove underscore prefix from stubs
* fix: added missing header include for gcc
* fix: small thread fix on syscalls
fix: fix incorrect VU translations (they was using wrong register)
* feat: added authoritative system for function extraction, this will prevent functions overlap when we have debug symbols
* Add missing VU0 Special1 macro translations
* Fix VU0 macro decode and field ops
Align Special2 decoding with fhi_flo, implement VCLIPw/VABS, and fix field variants (VADDx/VSUBx/VMULx). Keep C++17 compatibility by replacing unordered_set::contains and remove dead ADDIU return. Update Special2 metadata for VWAITQ.
* vu0: complete macro mappings and add coverage test
* review: clean up vu macro handling
* fix: restore C++20 contains in code generator
* fix: correct VU0 Special2 instruction encoding in decoder test
---------
Co-authored-by: Antonio Guastella <antonioguastella@energine.it>
Co-authored-by: Ranieri <ran-junior@hotmail.com>
fix: patching NOP things that code gen already know how to handle
feat: added a bug on JAL/J/JAR code gen
feat: enhanced tom file
fix: fix memory layout for ps2 macros
feat: added a lot of not working garbabe to runtime (fix later)
feat: some code organization
feat: added new tests
feat: update readme
* refactor: update function name checks to use contains method
* refactor: update code generation to use static_cast
* refactor: made member methods const
* refactor: made range-based loop
* refactor: make one variable constructor explicit
* refactor: remove redundant else
* refactor: turn includes to forward declarations
* refactor: brace placements turned into allman style