# Rewrite Stage 1

- Switch to CMake build system
- delete everything for a new structure
- Add SmartCtor class and saperate New func
- New Faster and Open Lithium Command API
- Rewritten Text Renderer to ghet rid of all that janky code
- New TimeTrace System and use of NanoTime using GetTimeNano
- Overall going to a more Object oriented way
- Updated vec api to support vec2 input on vec3
## Todo
- Support vec2 and vec3 in vec4 as inputs
- Continue UI7
- Fix SystemFont on 3ds freezing the system
- Fix TTF Font UV Mapping
## Warning
Creating Apps for the 3ds is not possible yet as the 3ds is Freezing and this is only stage 1 of ?   Emulator works perfect
This commit is contained in:
tobid7 2025-01-09 20:22:49 +01:00
parent d5c01b2988
commit d815bb5674
131 changed files with 21457 additions and 30844 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

View File

@ -7,12 +7,30 @@
"C:/devkitpro/libctru/include/**",
"C:/devkitpro/devkitARM/include/**",
"C:/devkitpro/devkitARM/arm-none-eabi/include/**",
"C:/devkitpro/portlibs/3ds/include/**",
"C:/devkitpro/portlibs/3ds/include/**"
],
"defines": [
"BUILD_CTR"
],
"compilerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-g++.exe",
"intelliSenseMode": "gcc-arm",
"cStandard": "c11",
"cppStandard": "c++20"
},
{
"name": "3DS | Linux",
"includePath": [
"${workspaceFolder}/**",
"/opt/devkitpro/libctru/include/**",
"/opt/devkitpro/portlibs/**"
]
"/opt/devkitpro/portlibs/3ds/include/**"
],
"defines": [
"BUILD_CTR"
],
"cStandard": "c17",
"cppStandard": "gnu++20",
"intelliSenseMode": "gcc-arm"
}
],
"version": 4
}
}

21
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"configurations": [
{
"name": "3DS GDB",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/test.elf",
"miDebuggerServerAddress": "localhost:4003",
"miDebuggerPath": "C:\\devkitPro\\devkitARM\\bin\\arm-none-eabi-gdb.exe",
"cwd": "${workspaceFolder}",
"externalConsole": true,
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

View File

@ -113,6 +113,8 @@
"__threading_support": "cpp",
"__tree": "cpp",
"__verbose_abort": "cpp",
"complex": "cpp"
"complex": "cpp",
"any": "cpp",
"text_encoding": "cpp"
}
}

View File

@ -1,127 +0,0 @@
# Palladium Changelog
## 1.0.0
- Rename Everyting to PD
- R7Vec -> NVec
- Switch from C2D to Lithium (LI7)
- For the Rest See RenderD7 Changelog below
- swr -> Rubidium
- LIFont (TTF Font Renderer)
- Implement shbin as c++ array
- Larger Mesaage Box
- Add Texture Loader
- Update Image/Error and other sytems to Lithium
- Remove Render2
- Add Deltatime to every moving object
- Restructure Project
# RenderD7 Changelog
## 0.9.5
- Remove Npi Intro and NVID Api
- Replace Toasts System with Message
- Added GetTime
- Move from Draw to Render2 Api
- Implement RD7Color and R7Vec2
- Add new Features to Color::RGBA
- Cleanup Code
- Added RenderD7 Keyboard (Overlay)
- Added Ftrace Overlay
- Moved MetrikOVL into an Overlay
- Removed Old Font/Text Handlers
- Added UI7 (New UI Api)
- Remove Old UI Api
- Rewrite of RenderD7::Image
- Internal Debugger/Database (IDB)
- Removed BitmapPrinter
- Added nimg and swr(render2nimg | SoftwareRender)
- Removed Old Error/Message Handler
- GetTextSize (extra buffer) + New TextShorter
- Require specific FLAG for MemTrack
- Replace all lodepng usage by stb_image
- Move Asset Generator into single python script
- Remove INI reader
- Python based clangformat script
- Move some Init code into functions to not use twice
- Added Font class
- Add LinearAllocator (for std)
- Fix Crash in FilsSystem
- Implement basic Theme System
- Remove 0.9.4 Security
- Tasks now based on std functional/thread
- Add Network Support (Download Files, APi Requests)
- Remove RD7TF
- Add Cia Installer
- Move from Init bool values to flags
## 0.9.4
- Implement new Security System To prevent from crashes
- Implement Functiontrace for better Timing Tests
- Implement MemAlloc Tracker (only size)
- Add some new Overlays (not functional yet)
- Complete Rewrite of Overlay System
- Fixed the FrameEnd Crash
- New System to get Hardware Info
- Removed RenderD7 Super Reselution (800px mode)
## 0.9.3
- Completly Documented Everything
- Fix typo in Sprite::getHeight
- Remove Deprecated/Useless Stuff
## 0.9.2
- Add Nvid Support(v0.0.1)
- Add Basic RenderD7 Splash
- Faster Graphics Init
- Fade Effects
- Fix Changelog Screen
## 0.9.1
- Fix Critical bug in Spritesheet animations
- Fix RenderD7::Color::Hex (Major performance tweak)
## 0.9.0
- Remove Stupid try of Console
- Add Services list
- Clean up Code
- Added Minimal Init for hax2.x
## 0.8.5
- Fix Deltatime
## 0.8.4
- A lot of Fixes
- New Features for BitmapPrinter
## 0.8.3
- Added Overlaycount to Info
- Addet ResultDecoder for errors
## 0.8.2
- Fix a lot of Stuff
- Use c++17 std::filesystem for RenderD7::Filesystem
## 0.8.1
- Add abillity to Get Stdout as string to render it to the screen.
## 0.8.0
- Implement BitmapPrinter
## 0.7.3
- Implement Over Render Overlay Framework
## 0.7.2
- Implement MT to csv file saving
- Add RGB2HEX
## 0.7.1
- Add the New Overlay Handler. Its Just in code and does nothing yet
## 0.7.0
- Made Big Progress In the MT Ovl but it still crashes On a 2nd C3D_FrameEnd \
- Implement 800px but doesn't work that good
## 0.6.2
- Fix Crash when exiting through Home Menu.
## 0.6.10
- Rewrite Threadsystem
- Improve framerate
## 0.6.02
- Fix Code in lang.hpp
- Add Draw Text Left Function (Right since 0.7.0)
- Add changelog
## 0.6.01
- Add Threading system
## 0.6.0
- Better Scene Management
## 0.5.0
- Fixed some Bugs!
## 0.4.0
- Trying to fix Filesystem and Bugs
## 0.3.0
- Recreate D7-Core into RenderD7
## 0.2.0
- Trying to create Animations of Images instead of Sheets
## 0.1.0
- Inital Release of D7-Core sprite animation plugin

82
CMakeLists.txt Normal file
View File

@ -0,0 +1,82 @@
cmake_minimum_required(VERSION 3.18)
# Setup Toolchain if not specified
# Could propably avoided by using arm-none-eabi-cmake
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{DEVKITPRO})
set(CMAKE_TOOLCHAIN_FILE "$ENV{DEVKITPRO}/cmake/3DS.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define DEVKITPRO to point to your SDK path!")
endif()
endif()
# Set Project
project(palladium LANGUAGES C CXX VERSION 1.0.0)
# Enable Compile Command Export
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Force C++ 20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Set Special C and CXX flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-psabi -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions")
set(SRC_FILES
# Core (common)
source/common/app.cpp
source/common/strings.cpp
source/common/timetrace.cpp
source/common/sys.cpp
source/common/lang.cpp
source/common/error.cpp
# Maths
source/maths/color.cpp
source/maths/bit_util.cpp
source/maths/img_convert.cpp
# Graphics
source/graphics/texture.cpp
source/graphics/li7_shader.cpp
source/graphics/lithium.cpp
# External
source/external/stb.cpp
)
set(TARGET_NAME palladium)
# Set Executable and its sources
add_library(${TARGET_NAME} STATIC ${SRC_FILES})
# Set dependencies, include dirs and definitions
target_include_directories(${TARGET_NAME} PUBLIC
include
${DEVKITPRO}/portlibs/3ds/include
)
target_compile_definitions(${TARGET_NAME} PUBLIC
-D_GNU_SOURCE=1
-DVERSION="${PROJECT_VERSION}"
-DBUILD_CTR=1
)
add_executable(test test/main.cpp)
target_include_directories(test PUBLIC include)
target_link_directories(test PUBLIC ${CMAKE_BINARY_DIR})
target_link_libraries(test PUBLIC palladium citro3d ctru m)
# Generate 3DSX
ctr_generate_smdh(
${CMAKE_BINARY_DIR}/test.smdh
NAME "${APP_NAME}"
DESCRIPTION "Palladium test app"
AUTHOR "tobid7"
ICON "test/romfs/icon.png"
)
ctr_create_3dsx(
test
OUTPUT "${CMAKE_BINARY_DIR}/test.3dsx"
SMDH "${CMAKE_BINARY_DIR}/test.smdh"
ROMFS "${CMAKE_SOURCE_DIR}/test/romfs"
)
install(TARGETS ${TARGET_NAME})
install(DIRECTORY include DESTINATION ".")

152
Makefile
View File

@ -1,152 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/3ds_rules
export PD_MAJOR := 1
export PD_MINOR := 0
export PD_PATCH := 0
VERSION := $(PD_MAJOR).$(PD_MINOR).$(PD_PATCH)
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := palladium
SOURCES := source source/base
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CFLAGS := -g -Wall -Wno-psabi -Werror -mword-relocations \
-ffunction-sections -fdata-sections \
-fomit-frame-pointer -ffast-math \
$(ARCH) $(BUILD_CFLAGS)
CFLAGS += $(INCLUDE) -D__3DS__ -D_GNU_SOURCE=1
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++20
ASFLAGS := -g $(ARCH) $(DEFINES)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
.PHONY: clean all doc
#---------------------------------------------------------------------------------
all: lib/libpalladium.a lib/libpalladiumd.a
dist-bin: all
@tar --exclude=*~ -cjf palladium-$(VERSION).tar.bz2 include lib
dist-src:
@tar --exclude=*~ -cjf palladium-src-$(VERSION).tar.bz2 include source Makefile
dist: dist-src dist-bin
install: dist-bin
mkdir -p $(DESTDIR)$(DEVKITPRO)/libctru
bzip2 -cd palladium-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/libctru
lib:
@[ -d $@ ] || mkdir -p $@
release:
@[ -d $@ ] || mkdir -p $@
debug:
@[ -d $@ ] || mkdir -p $@
lib/libpalladium.a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O3 -fomit-frame-pointer -fno-math-errno" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
lib/libpalladiumd.a : lib debug $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=debug OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DDEBUG=1 -Og" \
DEPSDIR=$(CURDIR)/debug \
--no-print-directory -C debug \
-f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release debug lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,62 +1,41 @@
# Palladium
Create README ?
# RenderD7 as Submodule (0.9.5+)
To use RenderD7 just use this command: `git submodule add https://github.com/NPI-D7/RenderD7` and add `-b v0.9.5` for example for a specific version.
## Build types
And in Your Project Makefile add this
```
# Make Sure to Change this paths if your Submodule
# is located somewhere else
RENDERD7_SRC := RenderD7/source RenderD7/external
RENDERD7_INC := RenderD7/include
# Libraries used for RenderD7
# if you already use -lm, -lctru etc place a # before -lm
RENDERD7_LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lz -lm -lcitro2dd -lcitro3d -lctru
```
Now you need to add it to your sources and includes
```
SOURCES := source $(RENDERD7_SRC)
INCLUDES := source $(RENDERD7_INC)
```bash
PD_EXTENDED_DEBUG=0 # Include things like ResultDecoder and Check for Memory usage
PD_DEBUG=0 # not yet
PD_NO_SAFE_CODE=0 # Remove All not important safetey checks
```
Example from rd7tf
### Installation (0.8.0-0.9.4) (OUTDATED)
Download a Package From Releses Page
`https://github.com/NPI-D7/RenderD7/releases/download/v0.9.4/renderd7.tar.bz2 -o renderd7.tar.bz2`
Then Extract it to your Libraries Path
`bzip2 -cd renderd7.tar.bz2 | tar -xf - -C path_to_your_libs`
Finally put `-lrenderd7` to the First Place and add the path_to_your_libs
```
LIBS := -lrenderd7 -lcurl -lstdc++ -lm -lcitro2d -lcitro3d -lctru
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(CTRULIB) ../path_to_your_libs
```
Make sure that `-lrenderd7` is before `-lcitro2d`, `-lcitro3d`, `-lctru`.
Here an example tree
```
Example-App
├── gfx
├── libs
│ ├── include
│ │ ├── rd7.hpp
│ │ └── renderd7
│ └── lib
│ ├── librenderd7.a
│ └── librenderd7d.a
├── Makefile
├── romfs
│ └── gfx
└── src
└── main.cpp
```
# Credits
- NPI-D7
- Tobi-D7 Main Dev
## Building
Some Icons are From
https://icons8.de/
See Subfolder Readmes
Install Dependencies:
```bash
# This Command will install everything
(dkp-)pacman -S --noconfirm 3ds-dev 3ds-portlibs
```
Building:
If you want to have the lib in a projects `libs` dir or so you can simply add `-DCMAKE_INSTALL_PREFIX=./res` to the cmake command and copy the dirs from res to you libs folder
For Debug build the Cmake Script generates a `libpalladiumd.a`
```bash
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release # Make sure to build in Release Mode (exept you want to debug some issues)
make
make install
```
## Credits
| Icon | Username | Description |
|---|---|---|
| <img src="https://github.com/tobid7.png" alt="https://github.com/tobid7" width="48"/> | [tobid7](https://github.com/tobid7) | main dev of RenderD7, Palladium |
| <img src="https://github.com/devkitpro.png" alt="https://github.com/devkitpro" width="48"/> | [devkitpro](https://github.com/devkitpro) | devkitarm, picasso, libctru and citro3d |
| <img src="https://github.com/Universal-Team.png" alt="https://github.com/Universal-Team" width="48"/> | [Universal-Team](https://github.com/Universal-Team) | Inspiration for Lang System, Cia Installer Code |
| <img src="https://github.com/nothings.png" alt="https://github.com/nothings" width="48"/> | [nothings](https://github.com/nothings) | stb_image(_write) and stb_truetype |
| <img src="https://github.com/nlohmann.png" alt="https://github.com/nlohmann" width="48"/> | [nlohmann](https://github.com/nlohmann) | for json.hpp |

View File

@ -1,18 +0,0 @@
<div class="md-copyright">
{% if config.copyright %}
<div class="md-copyright__highlight">
{{ config.copyright }}
</div>
{% endif %}
{% if not config.extra.generator == false %}
Made with
<a href="https://doxide.org" target="_blank" rel="noopener">
Doxide
</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
{% endif %}
</div>

View File

@ -1,18 +0,0 @@
<div class="md-copyright">
{% if config.copyright %}
<div class="md-copyright__highlight">
{{ config.copyright }}
</div>
{% endif %}
{% if not config.extra.generator == false %}
Made with
<a href="https://doxide.org" target="_blank" rel="noopener">
Doxide
</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
{% endif %}
</div>

View File

@ -1,49 +0,0 @@
:root {
--md-admonition-icon--variable: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.41 3c1.39 2.71 1.94 5.84 1.59 9-.2 3.16-1.3 6.29-3.17 9l-1.53-1c1.61-2.43 2.55-5.2 2.7-8 .34-2.8-.11-5.57-1.3-8l1.71-1M5.17 3 6.7 4C5.09 6.43 4.15 9.2 4 12c-.34 2.8.12 5.57 1.3 8l-1.69 1c-1.4-2.71-1.96-5.83-1.61-9 .2-3.16 1.3-6.29 3.17-9m6.91 7.68 2.32-3.23h2.53l-3.78 5 2.2 4.92h-2.26L11.71 14l-2.43 3.33H6.76l3.9-5.12-2.13-4.76h2.27l1.28 3.23Z"/></svg>');
--md-admonition-icon--function: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.6 5.29c-1.1-.1-2.07.71-2.17 1.82L13.18 10H16v2h-3l-.44 5.07a3.986 3.986 0 0 1-4.33 3.63 4.007 4.007 0 0 1-3.06-1.87l1.5-1.5c.24.74.9 1.31 1.73 1.38 1.1.1 2.07-.71 2.17-1.82L11 12H8v-2h3.17l.27-3.07c.19-2.2 2.13-3.83 4.33-3.63 1.31.11 2.41.84 3.06 1.87l-1.5 1.5c-.24-.74-.9-1.31-1.73-1.38Z"/></svg>');
--md-admonition-icon--concept: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.75 3.5a.25.25 0 0 0-.25.25v2.062a.75.75 0 1 1-1.5 0V3.75C2 2.783 2.783 2 3.75 2h2.062a.75.75 0 1 1 0 1.5Zm13.688-.75a.75.75 0 0 1 .75-.75h2.062c.966 0 1.75.783 1.75 1.75v2.062a.75.75 0 1 1-1.5 0V3.75a.25.25 0 0 0-.25-.25h-2.062a.75.75 0 0 1-.75-.75ZM2.75 17.438a.75.75 0 0 1 .75.75v2.062c0 .138.112.25.25.25h2.062a.75.75 0 1 1 0 1.5H3.75A1.75 1.75 0 0 1 2 20.25v-2.062a.75.75 0 0 1 .75-.75Zm18.5 0a.75.75 0 0 1 .75.75v2.062A1.75 1.75 0 0 1 20.25 22h-2.062a.75.75 0 1 1 0-1.5h2.062a.25.25 0 0 0 .25-.25v-2.062a.75.75 0 0 1 .75-.75Zm-18.5-8.25a.75.75 0 0 1 .75.75v4.124a.75.75 0 1 1-1.5 0V9.938a.75.75 0 0 1 .75-.75ZM9.188 2.75a.75.75 0 0 1 .75-.75h4.124a.75.75 0 1 1 0 1.5H9.938a.75.75 0 0 1-.75-.75Zm0 18.5a.75.75 0 0 1 .75-.75h4.124a.75.75 0 1 1 0 1.5H9.938a.75.75 0 0 1-.75-.75ZM21.25 9.188a.75.75 0 0 1 .75.75v4.124a.75.75 0 1 1-1.5 0V9.938a.75.75 0 0 1 .75-.75ZM3.75 8.25a.75.75 0 0 1 .75-.75h2a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1-.75-.75Zm5.5 0A.75.75 0 0 1 10 7.5h2A.75.75 0 0 1 12 9h-2a.75.75 0 0 1-.75-.75Zm-1-4.5A.75.75 0 0 1 9 4.5v2a.75.75 0 0 1-1.5 0v-2a.75.75 0 0 1 .75-.75Zm0 5.5A.75.75 0 0 1 9 10v2a.75.75 0 0 1-1.5 0v-2a.75.75 0 0 1 .75-.75Zm0 4.75a.75.75 0 0 1 .75.75v4a.75.75 0 0 1-1.5 0v-4a.75.75 0 0 1 .75-.75ZM14 8.25a.75.75 0 0 1 .75-.75h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1-.75-.75Z"/></svg>');
--md-admonition-icon--macro: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m5.41 21 .71-4h-4l.35-2h4l1.06-6h-4l.35-2h4l.71-4h2l-.71 4h6l.71-4h2l-.71 4h4l-.35 2h-4l-1.06 6h4l-.35 2h-4l-.71 4h-2l.71-4h-6l-.71 4h-2M9.53 9l-1.06 6h6l1.06-6h-6Z"/></svg>');
}
.md-typeset .admonition.variable, .md-typeset details.variable,
.md-typeset .admonition.function, .md-typeset details.function,
.md-typeset .admonition.concept, .md-typeset details.concept,
.md-typeset .admonition.macro, .md-typeset details.macro {
border-color: var(--md-default-fg-color--lighter);
}
.md-typeset .variable > .admonition-title, .md-typeset .variable > summary,
.md-typeset .function > .admonition-title, .md-typeset .function > summary,
.md-typeset .concept > .admonition-title, .md-typeset .concept > summary,
.md-typeset .macro > .admonition-title, .md-typeset .macro > summary {
background-color: var(--md-default-bg-color);
}
.md-typeset .variable > .admonition-title::before,
.md-typeset .variable > summary::before {
background-color: var(--md-default-fg-color--light);
-webkit-mask-image: var(--md-admonition-icon--variable);
mask-image: var(--md-admonition-icon--variable);
}
.md-typeset .function > .admonition-title::before,
.md-typeset .function > summary::before {
background-color: var(--md-default-fg-color--light);
-webkit-mask-image: var(--md-admonition-icon--function);
mask-image: var(--md-admonition-icon--function);
}
.md-typeset .concept > .admonition-title::before,
.md-typeset .concept > summary::before {
background-color: var(--md-default-fg-color--light);
-webkit-mask-image: var(--md-admonition-icon--concept);
mask-image: var(--md-admonition-icon--concept);
}
.md-typeset .macro > .admonition-title::before,
.md-typeset .macro > summary::before {
background-color: var(--md-default-fg-color--light);
-webkit-mask-image: var(--md-admonition-icon--macro);
mask-image: var(--md-admonition-icon--macro);
}

View File

@ -1,9 +0,0 @@
title: Palladium
description:
files:
- "include/*.hpp"
- "include/pd/*.hpp"
- "include/pd/base/*.hpp"
- "include/*.h"
- "include/pd/*.h"
- "include/pd/base/*.h"

View File

@ -1,27 +1,42 @@
#pragma once
#include <pd/Error.hpp>
#include <pd/Hid.hpp>
#include <pd/Image.hpp>
#include <pd/Installer.hpp>
#include <pd/Lithium.hpp>
#include <pd/Message.hpp>
#include <pd/Net.hpp>
#include <pd/Overlays.hpp>
#include <pd/Rubidium.hpp>
#include <pd/Sheet.hpp>
#include <pd/Sound.hpp>
#include <pd/Texture.hpp>
#include <pd/Timer.hpp>
#include <pd/UI7.hpp>
#include <pd/base/Allocator.hpp>
#include <pd/base/FileSystem.hpp>
#include <pd/global_db.hpp>
#include <pd/palladium.hpp>
/*
MIT License
namespace Palladium {
using Lithium = LI;
using RB = Rubidium;
} // namespace Palladium
Copyright (c) 2024 tobid7
namespace PD = Palladium;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Common
#include <pd/common/app.hpp>
#include <pd/common/lang.hpp>
#include <pd/common/strings.hpp>
#include <pd/common/sys.hpp>
#include <pd/common/timetrace.hpp>
// Graphics
#include <pd/graphics/lithium.hpp>
#include <pd/graphics/texture.hpp>
// Maths
#include <pd/maths/bit_util.hpp>
#include <pd/maths/color.hpp>
#include <pd/maths/img_convert.hpp>
#include <pd/maths/vec.hpp>
// namespace Palladium = PD;

View File

@ -1,18 +0,0 @@
#pragma once
#include <string>
namespace Palladium {
void Error(const std::string& msg);
inline void InlineError(const std::string& msg) {
std::string location = __FILE__ + std::string(":") + std::to_string(__LINE__);
Error("Error: \n" + location + "\n" + msg);
}
inline void InlineAssert(bool v, const std::string& msg = "") {
if (v == false) {
std::string location =
__FILE__ + std::string(":") + std::to_string(__LINE__);
Error("Assert Failed:\n" + location + "\n" + msg);
}
}
} // namespace Palladium

View File

@ -1,26 +0,0 @@
#pragma once
namespace Palladium {
namespace Hardware {
/// @brief Initialisize required Services
void Initialisize();
/// @brief Check if Headphones are Plugged in
/// @return true if headphones plugged in
bool IsHeadphones();
/// @brief Check if the 3ds Is Charging
/// @return true if System gets Charged
bool IsCharging();
/// @brief Check the Battery Percentage
/// @return Persentage as int
int GetBatteryPercentage();
/// @brief Get current State of 3d Slider
/// @return current 3dslider poition
float Get3dSliderLevel();
/// @brief Get Current state of Sound Slider
/// @return current SoundSlider state
float GetSoundSliderLevel();
/// @brief Get Current Wifi Level
/// @return current wifi level
int GetWifiLevel();
} // namespace Hardware
} // namespace Palladium

View File

@ -1,42 +0,0 @@
// WARNING
// THIS IS BETA STUFF
// ITS MAKE LIKE EXTERNAL BUT
// FOR Palladium ITS INTEGRATED
#pragma once
#include <pd/maths/NVec.hpp>
#include <string>
namespace Palladium {
namespace Hid {
enum Actions {
Down = 0,
Held = 1,
Up = 2,
DownRepeat = 3,
};
// Register Functions
// Register Current state values
void RegKeyDown(uint32_t &key_down);
void RegKeyHeld(uint32_t &key_held);
void RegKeyUp(uint32_t &key_up);
void RegKeyRepeat(uint32_t &repeat);
void RegTouchCoords(NVec2 &touch_pos);
// Not Corectly Implemented Yet
void RegAnalog1Movement(NVec2 &movement);
void RegAnalog2Movement(NVec2 &movement);
// Register Keys
void RegKeyEvent(const std::string &event, uint32_t key);
// KeyEvents
bool IsEvent(const std::string &event, Actions action);
NVec2 GetTouchPosition();
NVec2 GetLastTouchPosition();
NVec2 GetTouchDownPosition();
void Update();
// Lock/Unlock Input api for example for Keyboard
void Lock();
void Unlock();
void Clear();
} // namespace Hid
} // namespace Palladium

View File

@ -1,33 +0,0 @@
#pragma once
#include <3ds.h>
#include <pd/Texture.hpp>
#include <pd/maths/NVec.hpp>
#include <pd/nimg.hpp>
#include <pd/smart_ctor.hpp>
#include <string>
namespace Palladium {
class Image {
public:
Image() = default;
Image(const std::string& path) { this->Load(path); }
~Image() = default;
PD_SMART_CTOR(Image)
void Load(const std::string& path);
void From_NIMG(const nimg& image);
void Delete();
Texture::Ref Get();
void Set(Texture::Ref i, NVec4 uvs = NVec4(-1, -1, -1, -1));
NVec2 GetSize();
NVec4 GetUV() { return (custom_uvs.x() != -1) ? custom_uvs : img->GetUV(); }
bool Loadet();
private:
bool ext = false;
Texture::Ref img;
NVec4 custom_uvs = NVec4(-1, -1, -1, -1);
};
} // namespace Palladium

View File

@ -1,17 +0,0 @@
#pragma once
#include <3ds.h> // Result
#include <string>
namespace Palladium {
struct InstallerInfo {
unsigned long long total;
unsigned long long current;
unsigned int mem_size = 0x80000;
bool active = false;
};
Result InstallCia(const std::string& path, bool self);
void InstallSetBuffersSize(unsigned int bytes);
InstallerInfo InstallGetInfo();
} // namespace Palladium

View File

@ -1,238 +0,0 @@
#pragma once
#include <citro3d.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <pd/Texture.hpp>
#include <pd/base/Allocator.hpp>
#include <pd/maths/NVec.hpp>
#include <vector>
#define MAKEFLAG(x) (1 << x)
using PDTextFlags = unsigned int;
enum PDTextFlags_ {
PDTextFlags_None = 0, //< Align is Left and Other things are disabled
PDTextFlags_AlignRight = MAKEFLAG(0),
PDTextFlags_AlignMid = MAKEFLAG(1),
PDTextFlags_Shaddow = MAKEFLAG(2), // TextBuf Killer lol (doubled Text)
PDTextFlags_Wrap = MAKEFLAG(3),
PDTextFlags_Short = MAKEFLAG(4),
PDTextFlags_Scroll = MAKEFLAG(5),
};
using PDLithiumFlags = unsigned int;
enum PDLithiumFlags_ {
PDLithiumFlags_None = 0,
PDLithiumFlags_TMS = MAKEFLAG(0), // Text Map System
PDLithiumFlags_LRS = MAKEFLAG(1), // Layer Render System
PDLithiumFlags_FCS = MAKEFLAG(2), // Floor Coords System
PDLithiumFlags_Default = PDLithiumFlags_TMS,
};
namespace Palladium {
class LIFont {
public:
struct CPI {
CPI()
: codepoint(0),
uv(NVec4()),
tex(nullptr),
szs(NVec2()),
off(0.f),
invalid(false) {}
CPI(bool iv)
: codepoint(0),
uv(NVec4()),
tex(nullptr),
szs(NVec2()),
off(0.f),
invalid(iv) {}
unsigned int codepoint;
NVec4 uv;
Texture::Ref tex;
NVec2 szs;
float off;
bool invalid;
};
LIFont() = default;
~LIFont() = default;
PD_SMART_CTOR(LIFont)
void LoadTFF(const std::string path, int px_size = 32);
void LoadBitmapFont(const std::string& path);
void LoadSystemFont();
int GetPixelHeight();
CPI GetCodepoint(unsigned int c);
std::string GetName() { return name; };
bool IsSystemFont() { return sysfnt; }
void Dump();
private:
bool sysfnt = false;
std::string name;
int pixel_height;
std::map<unsigned int, CPI> cpmap;
std::vector<Texture::Ref> tex;
};
class LI {
public:
struct Vtx {
Vtx() {}
Vtx(NVec2 xy, float u, float v, unsigned int clr) {
// Coords
pos[0] = xy[0];
pos[1] = xy[1];
pos[2] = 0.f;
// UV
uv[0] = u;
uv[1] = v;
col = clr;
}
NVec3 pos;
NVec2 uv;
unsigned int col;
};
/// CMD TYPES ///
/// 0 = SKIP
/// 2 = TRIANGLE
/// 1 = RECT
/// 3 = Circle
/////////////////
struct Cmd {
NVec4 top;
NVec4 bot;
NVec4 uv;
int layer = 0;
int cmd_type = 0;
bool fcs = false; // Floor Coords System
unsigned int clr = 0;
bool sfr = false; // SysFontRender
Texture::Ref tex = nullptr;
int index = 0;
};
/// Text Box ///
/// System to Make GetTextDiemnsions
/// and Short/Wrap faster
struct TextBox {
NVec2 size;
float time_created;
// Optional
bool optinal = false;
std::string text;
};
LI() = default;
~LI() = default;
static void Init();
static void Exit();
// Settings
static void EnableFeature(PDLithiumFlags flag) { flags |= flag; }
static void DisableFeature(PDLithiumFlags flag) { flags &= ~flag; }
static PDLithiumFlags& GetFeatures() { return flags; }
static void OnScreen(bool bottom);
static void Render(C3D_RenderTarget* top, C3D_RenderTarget* bot);
static NVec2 GetScreenSize() { return screen_size; }
static LIFont::Ref GetFont() { return font; }
static void SetFont(LIFont::Ref i) {
font_update = true;
font = i;
}
static void UseTexture(Texture::Ref tex = nullptr) {
active_texture = tex ? tex : single_color;
}
static bool IsBottomScreen() { return bottom_screen; }
static float GetTextScale() { return text_scale; }
static void SetTextScale(float scale) {
font_update = true;
text_scale = scale;
}
static void DefaultTextScale() {
font_update = true;
text_scale = default_text_size;
}
static void Layer(int v) { layer = v; }
static int Layer() { return layer; }
static void NewLayer() { layer++; }
static NVec2 GetTextDimensions(const std::string& text);
static std::string ShortText(const std::string& in, int maxlen, NVec2& dim);
static std::string WrapText(const std::string& in, int maxlen, NVec2& dim);
// Drawing Functions
static void DrawRect(NVec2 pos, NVec2 size, unsigned int color, NVec4 uvs);
static void DrawLine(NVec2 a, NVec2 b, unsigned int clr, int t = 1);
static void DrawCircle(NVec2 pos, float r, unsigned int color, int segments);
static void DrawRect(NVec2 pos, NVec2 size, unsigned int color) {
UseTexture();
DrawRect(pos, size, color, NVec4(0, 1, 1, 0));
}
static void DrawTriangle(NVec2 a, NVec2 b, NVec2 c, unsigned int color);
static void DrawImage(NVec2 pos, Texture::Ref tex, NVec2 size, NVec4 uvs) {
UseTexture(tex);
DrawRect(pos, size, 0xffffffff, uvs);
}
static void DrawText(NVec2 pos, unsigned int color, const std::string& text,
PDTextFlags flags = 0, NVec2 ap = NVec2());
static int Vertices() { return num_vertices; }
static int Indices() { return num_indices; }
static int Drawcalls() { return num_drawcalls; }
static int DarwCommands() { return num_commands; }
static size_t GetMaxVerticesNum() { return vertex_buffer.size(); }
private:
static void RotateCorner(NVec2& v, float s, float c);
static void MakeRect(NVec4& top, NVec4& bot, NVec2 pos, NVec2 szs,
float angle = 0.f);
static bool CompareCommands(const Cmd& a, const Cmd& b);
static void RenderFrame(bool bottom);
/// CTX ///
static PDLithiumFlags flags;
// Font Stuff
// Default Font Size in (px)
static const float default_font_size;
static const float default_text_size;
static float text_scale;
// Renderer Stuff
static NVec2 screen_size;
static bool bottom_screen;
static int layer;
static std::vector<Cmd> draw_lists[2];
static Texture::Ref active_texture;
static Texture::Ref single_color;
static std::vector<Vtx, LinearAllocator<Vtx>> vertex_buffer;
static std::vector<unsigned short, LinearAllocator<unsigned short>>
idx_buffer;
static size_t vertex_index;
static size_t idx_index;
static LIFont::Ref font;
static bool font_update;
static bool sysfont_render;
static std::map<std::string, TextBox> text_sizes;
static int cmd_index;
// Debug
static int num_vertices;
static int num_drawcalls;
static int num_commands;
static int num_indices;
// Shader
static DVLB_s* li7_dvlb;
static shaderProgram_s li7_prog;
static C3D_AttrInfo li7_attr;
static int uLoc_proj;
};
} // namespace Palladium

View File

@ -1,27 +0,0 @@
#pragma once
#include <string>
namespace Palladium {
struct Message {
Message(std::string t, std::string m) {
title = t;
message = m;
animtime = 0.f;
}
std::string title;
std::string message;
float animtime;
};
void ProcessMessages();
void PushMessage(const Message& msg);
inline void PushMessage(const std::string& head, const std::string& msg) {
PushMessage(Message(head, msg));
}
// Config
void SetMessageIdleStartFrame(int frame);
void SetMessageTotalAnimationFrames(int total_frames);
void SetMessageFadeOutStartFrame(int frame);
} // namespace Palladium

View File

@ -1,42 +0,0 @@
#pragma once
#include <pd/external/json.hpp>
#include <string>
namespace Palladium {
namespace Net {
// Define List of Errors
enum Error_ {
Error_None, // Function Executed Successfully
Error_Memory, // Memory Allocation Error
Error_Write, // Unable to Write File
Error_StatusCode, // Error with Status Code
Error_Git, // Git Error
Error_CtrStatus, // 3ds Result Code
Error_Curl, // Curl Error
Error_Busy, // Another Download Taskl is already running
Error_Invalid, // Invalid Json struct
Error_NoWifi, // Console not connected to wifi
};
// Set an typedefine for Error code
using Error = unsigned long long;
// Extract Error_ from Error code
inline Error_ ErrorCode(Error err) {
return static_cast<Error_>(static_cast<unsigned int>(err & 0xffffffff));
}
// Extract Http Status code, Curl Error Code or Ctr Result Code
inline int StatusCode(Error err) {
Error_ c = ErrorCode(err);
if (c != Error_StatusCode && c != Error_CtrStatus && c != Error_Curl)
return 0;
return static_cast<unsigned int>(err >> 32);
}
Error Download(const std::string& url, std::string& data);
Error Download2File(const std::string& url, const std::string& path);
Error GitDownloadRelease(const std::string& url, const std::string& asset_name,
const std::string& path, bool prerelease = false);
Error JsonApiRequest(const std::string& api_url, nlohmann::json& res);
unsigned long long GetProgressCurrent();
unsigned long long GetProgressTotal();
} // namespace Net
} // namespace Palladium

View File

@ -1,107 +0,0 @@
#pragma once
#include <pd/Ovl.hpp>
#include <pd/Timer.hpp>
#include <pd/base/FunctionTrace.hpp>
#include <pd/maths/NVec.hpp>
#include <string>
typedef int PDKeyboard;
enum PDKeyboard_ {
PDKeyboard_Default,
PDKeyboard_Numpad,
PDKeyboard_Password,
};
enum PDKeyboardState {
PDKeyboardState_None = 0,
PDKeyboardState_Cancel = 1,
PDKeyboardState_Confirm = 2,
};
using PDKeyboardFlags = unsigned int;
enum PDKeyboardFlags_ {
PDKeyboardFlags_None = 0,
PDKeyboardFlags_BlendTop = 1 << 0,
PDKeyboardFlags_BlendBottom = 1 << 1,
PDKeyboardFlags_LockControls = 1 << 2,
PDKeyboardFlags_Default = PDKeyboardFlags_BlendTop |
PDKeyboardFlags_BlendBottom |
PDKeyboardFlags_LockControls,
};
namespace Palladium {
class Ovl_Ftrace : public Palladium::Ovl {
public:
/// @brief Constructor
Ovl_Ftrace(bool* is_enabled);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
bool* i_is_enabled;
};
class Ovl_Metrik : public Palladium::Ovl {
public:
/// @brief Constructor
Ovl_Metrik(bool* is_enabled, bool* screen, unsigned int* mt_color,
unsigned int* txt_color, float* txt_size);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
// Mutable internal values
mutable std::string mt_fps;
mutable std::string mt_cpu;
mutable std::string mt_gpu;
mutable std::string mt_cmd;
mutable std::string mt_lfr;
mutable std::string mt_vtx;
mutable std::string mt_idx;
mutable std::string mt_drc;
mutable std::string mt_dmc;
mutable std::string mt_mem;
// Importand Adresses
bool* i_is_enabled;
bool* i_screen;
unsigned int* i_mt_color;
unsigned int* i_txt_color;
float* i_txt_size;
mutable Ftrace::TimeStats cpu_stats;
mutable Ftrace::TimeStats gpu_stats;
mutable Timer v_update;
};
class Ovl_Keyboard : public Palladium::Ovl {
public:
/// @brief Constructor
/// Keyboard Type not Supported for now
Ovl_Keyboard(std::string& ref, PDKeyboardState& state,
const std::string& hint = "", PDKeyboard type = 0,
PDKeyboardFlags flags = PDKeyboardFlags_Default);
/// @brief Deconstructor
~Ovl_Keyboard();
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
mutable std::map<unsigned char, char> shared_data;
// Pointer to useres String
std::string* typed_text = nullptr;
std::string str_bak;
PDKeyboardState* state;
PDKeyboard type;
int mode = 0;
int ft3 = 0;
PDKeyboardFlags flags;
};
} // namespace Palladium

View File

@ -1,28 +0,0 @@
#pragma once
#include <map>
#include <memory>
namespace Palladium {
/// @brief The Overlay Class (Used for Toasts for example)
class Ovl {
public:
/// @brief Deconstructor
virtual ~Ovl() {}
/// @brief Function Called to Draw this
virtual void Draw() const = 0;
/// @brief Logic of the Overlay
virtual void Logic() = 0;
/// @brief Should the overlay be killed
/// @return Killed or Not
inline bool IsKilled() { return this->iskilled; }
/// @brief Kill The Overlay
inline void Kill() { iskilled = true; }
private:
/// @param iskilled For IsKilled();
bool iskilled = false;
};
/// @brief Add an Overlay to the Screen
/// @param scene Overlay to push to Screen
void AddOvl(std::unique_ptr<Palladium::Ovl> scene);
} // namespace Palladium

View File

@ -1,54 +0,0 @@
#pragma once
#include <3ds.h>
#include <string>
namespace Palladium {
/// @brief Decoder for 3ds Result Codes
class ResultDecoder {
public:
/// @brief Constructor
ResultDecoder() {}
/// @brief Deconstructor
~ResultDecoder() {}
/// @brief Load a Result into Decoder
/// @param rescode Result Code
void Load(Result rescode);
/// @brief Load A Hex Converted Code into Decoder
/// @param rescode Result-Hex Code
void Load(std::string rescode);
/// @brief Get Hex Code
/// @return Hex-Code
std::string GetCode();
/// @brief Get Level Name
/// @return Level Name
std::string GetLevel();
/// @brief Get Level Value
/// @return Level Value
int GetLevelInt();
/// @brief Get The Mosule Name
/// @return Module Name
std::string GetModule();
/// @brief Get The Module Value
/// @return Module Value
int GetModuleInt();
/// @brief Get The Description
/// @return Description
std::string GetDescription();
/// @brief Get The Description Valur
/// @return Description Value
int GetDescriptionInt();
/// @brief Get the Summary
/// @return Summary
std::string GetSummary();
/// @brief Get the Summary Value
/// @return Summary Value
int GetSummaryInt();
/// @brief Write a Result log file to sd
void WriteLog(void);
private:
/// @param m_rescode Result code
Result m_rescode;
};
} // namespace Palladium

View File

@ -1,30 +0,0 @@
#pragma once
#include <pd/nimg.hpp>
#include <pd/smart_ctor.hpp>
namespace Palladium {
class Rubidium {
public:
Rubidium(int w, int h);
Rubidium();
~Rubidium();
PD_SMART_CTOR(Rubidium)
nimg& GetNimg() { return image; }
void LoadFile(const std::string& path);
void LoadNimg(const std::string& path);
// Rendering
void DrawPixel(int x, int y, unsigned int color);
void DrawRect(int x, int y, int w, int h, unsigned int color, int t = 1);
void DrawRectSolid(int x, int y, int w, int h, unsigned int color);
void DrawLine(int x1, int y1, int x2, int y2, unsigned int color, int t = 1);
void Flip(bool h, bool v);
void EnableAA(bool enable) { enable_aa = enable; }
private:
// Leinwand (dont know english word for that)
nimg image;
bool enable_aa = true;
};
} // namespace Palladium

View File

@ -1,23 +0,0 @@
#pragma once
#include <tex3ds.h>
#include <pd/Image.hpp>
#include <pd/Texture.hpp>
#include <pd/smart_ctor.hpp>
namespace Palladium {
class Sheet {
public:
Sheet() = default;
~Sheet() = default;
PD_SMART_CTOR(Sheet)
void LoadT3X(const std::string& path);
Texture::Ref Get(int idx);
Image::Ref GetImage(int idx);
private:
std::vector<Texture::Ref> sprites;
Tex3DS_Texture sheet;
C3D_Tex* sheet_tex = nullptr;
};
} // namespace Palladium

View File

@ -1,35 +0,0 @@
#pragma once
#include <3ds.h>
#include <pd/smart_ctor.hpp>
#include <string>
namespace Palladium {
/** Sound Class */
class Sound {
public:
/// \brief Construct new Soundeffect
/// \param path Path to the .wav file
/// \param channel the channel 1-23
/// \param toloop true:loop the sound, false: don't loop
Sound(const std::string &path, int channel = 1, bool toloop = false);
/// @brief Deconstructor
~Sound();
PD_SMART_CTOR(Sound)
/// @brief Play the sound
void Play();
/// @brief Stop the sound
void Stop();
private:
/// \param dataSize Size of the filedata
u32 dataSize;
/// \param waveBuf For ndsp
ndspWaveBuf waveBuf;
/// \param data Memmory data of the sound
uint8_t *data = NULL;
/// \param chnl Channel of the sound
int chnl;
};
} // namespace Palladium

View File

@ -1,63 +0,0 @@
#pragma once
#include <citro3d.h>
#include <pd/Image.hpp>
#include <pd/smart_ctor.hpp>
namespace Palladium {
/// @brief Sprite Class
class Sprite {
public:
/// \brief Construct Sprite
Sprite() = default;
/// \brief Deconstruct Sprite
~Sprite() = default;
PD_SMART_CTOR(Sprite)
/// \brief Load a Sprite From SpriteSheet
/// \param img the Image to load from.(Palladium::Image)
void FromImage(Palladium::Image::Ref img);
/// @brief Draw the Sprite
/// @return success ?
bool Draw();
/// @brief Set the Center Position
/// @param x X Pos
/// @param y Y Pos
void SetCenter(float x, float y);
/// @brief Set the Sprite's Position
/// @param x X Pos
/// @param y Y Pos
void SetPos(float x, float y);
/// @brief Set The Sprite's Scale
/// @param x Scale on X-Axis
/// @param y Scale on Y-Axis
void SetScale(float x, float y);
/// @brief Set the Sprite's Rotation
/// @param rotation ratation
void SetRotation(float rotation);
/// @brief Rotate the Sprite
/// @param speed Speed to Rotate
void Rotate(float speed);
/// @brief Get Tje Sprite's Width
/// @return Width
float GetWidth();
/// @brief Get the Sprite's Height
/// @return Height
float GetHeight();
/// @brief Get The Sprite's X Position
/// @return X Position
float GetPosX();
/// @brief Get the Sprite's Y Position
/// @return Y Position
float GetPosY();
NVec2 GetSize();
NVec2 GetPos();
void SetPos(NVec2 pos);
void SetScale(NVec2 scale);
void SetRotCenter(NVec2 percentage);
private:
///// @param sprite The Sprite
// C2D_Sprite sprite;
};
} // namespace Palladium

View File

@ -1,13 +0,0 @@
#pragma once
#include <functional>
namespace Palladium {
namespace Tasks {
/// @brief Push A Task
/// @param fun Function of Your Task
/// @return index
int Create(std::function<void()> fun);
/// @brief Destroy all Tasks
void DestroyAll();
} // namespace Tasks
} // namespace Palladium

View File

@ -1,77 +0,0 @@
#pragma once
#include <citro3d.h>
#include <pd/maths/NVec.hpp>
#include <pd/smart_ctor.hpp>
#include <string>
#include <vector>
namespace Palladium {
class Texture {
public:
// Define Types supported by the texture loader
// For example usefull to waste not as much space
// in linear mem
enum Type {
RGBA32,
RGB24,
A8,
};
enum Filter {
NEAREST,
LINEAR,
};
Texture() {
// Set Default UV
this->uvs[0] = 0.0f;
this->uvs[1] = 1.0f;
this->uvs[2] = 1.0f;
this->uvs[3] = 0.0f;
};
~Texture() { Delete(); }
PD_SMART_CTOR(Texture)
void Delete();
/// @brief Loads an Image [png, jpg, bmp] as texture
/// by default it sets up the texture as RGBA32 and
/// only supports RGB24 and RGBA32 images
/// @param path Path to file
void LoadFile(const std::string& path);
/// @brief Loads an Image [png, jpg, bmp] as texture
/// by default it sets up the texture as RGBA32 and
/// only supports RGB24 and RGBA32 images
/// @param data Data of file
void LoadFromMemory(const std::vector<unsigned char>& data);
/// @brief Create Texture by pixel Data. This function supports
/// [RGBA32, RGB24, A8]
/// @param data Pixel Data
/// @param w Width of data
/// @param h Height of Data
/// @param type Type of Data (default is RGBA32)
void LoadPixels(const std::vector<unsigned char>& data, int w, int h,
Type type = RGBA32, Filter filter = NEAREST);
/// @brief This function sets up a texture Object based on the input
/// Data and a self setup C3D_Tex. You dont need to delete it as
/// This class does this automatically
void ExternalLoad(C3D_Tex* tex, NVec2 rszs, NVec4 uvs);
C3D_Tex* Get() { return this->tex; }
NVec2 GetTexSize();
NVec2 GetSize() { return img_size; }
// As the texture is a pow of 2 we need a uv
NVec4 GetUV() { return uvs; }
void AutoDelete(bool enable) { ad = enable; }
private:
void MakeTex(std::vector<unsigned char>& buf, int w, int h,
Type type = RGBA32, Filter filter = NEAREST);
C3D_Tex* tex = nullptr;
NVec2 img_size;
NVec4 uvs;
bool ad = true;
};
} // namespace Palladium

View File

@ -1,28 +0,0 @@
#pragma once
#include <pd/palladium.hpp>
namespace Palladium {
class ThemeEditor : public Palladium::Scene {
public:
ThemeEditor();
~ThemeEditor();
void Update() override;
private:
Theme::Ref edit_theme;
// Placeholder to save active one to
Theme::Ref temp_theme;
// temp vars for samples
bool cm;
std::string inpt;
int menu = 0;
// Keyboard
PDKeyboardState kbd_state;
std::string kbd_text;
std::vector<std::string> theme_list;
};
} // namespace Palladium

View File

@ -1,13 +0,0 @@
#pragma once
#include <string>
namespace Palladium {
/// @brief Format a String
/// @param fmt_str Format To
/// @param ... Additional Args
/// @return Formatted String
std::string FormatString(std::string fmt_str, ...);
/// @brief Get Current Time as String
/// @return Time-String
std::string GetTimeStr(void);
} // namespace Palladium

View File

@ -1,26 +0,0 @@
#pragma once
#include <3ds.h>
#include <pd/smart_ctor.hpp>
namespace Palladium {
class Timer {
public:
Timer(bool autostart = true);
~Timer() {}
PD_SMART_CTOR(Timer)
void Reset();
void Tick();
void Pause();
void Resume();
float Get();
float GetLive();
bool Running();
private:
uint64_t last = 0;
uint64_t current = 0;
bool is_running = false;
};
} // namespace Palladium

View File

@ -1,134 +0,0 @@
#pragma once
#include <pd/Image.hpp>
#include <pd/Lithium.hpp>
#include <pd/base/Color.hpp>
#include <pd/maths/NVec.hpp>
#include <pd/smart_ctor.hpp>
#define UI7MAKEFLAG(x) (1 << x)
using UI7MenuFlags = unsigned int;
enum UI7MenuFlags_ {
UI7MenuFlags_None = 0,
UI7MenuFlags_NoTitlebar = UI7MAKEFLAG(0),
UI7MenuFlags_TitleMid = UI7MAKEFLAG(1),
UI7MenuFlags_HzScrolling = MAKEFLAG(2),
UI7MenuFlags_VtScrolling = MAKEFLAG(3),
UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling,
};
enum UI7Horizontal {
UI7Horizontal_Left = 0,
UI7Horizontal_Center = 1,
UI7Horizontal_Right = 2,
};
enum UI7Vertical {
UI7Vertical_Top = 0,
UI7Vertical_Center = 1,
UI7Vertical_Bot = 2,
};
class DrawCmd;
class UI7DrawList {
public:
UI7DrawList() = default;
~UI7DrawList() = default;
void AddRectangle(NVec2 pos, NVec2 szs, PDColor clr);
void AddRectangle(NVec2 pos, NVec2 szs, unsigned int clr);
void AddTriangle(NVec2 pos0, NVec2 pos1, NVec2 pos2, PDColor clr);
void AddTriangle(NVec2 pos0, NVec2 pos1, NVec2 pos2, unsigned int clr);
void AddText(NVec2 pos, const std::string &text, PDColor clr,
PDTextFlags flags = 0, NVec2 box = NVec2());
void AddText(NVec2 pos, const std::string &text, unsigned int clr,
PDTextFlags flags = 0, NVec2 box = NVec2());
void AddImage(NVec2 pos, Palladium::Image::Ref img);
void AddCall(std::shared_ptr<DrawCmd> cmd);
void Process(bool auto_clear = true);
void Clear();
int Layer() { return layer; }
void Layer(int v) { layer = v; }
int BaseLayer() { return bl; }
void BaseLayer(int v) { bl = v; }
PD_SMART_CTOR(UI7DrawList)
private:
int layer = 0;
int bl = 0;
void AddDebugCall(std::shared_ptr<DrawCmd> cmd);
std::vector<std::shared_ptr<DrawCmd>> list;
};
namespace UI7 {
// Key functions
void Init();
void Deinit();
void Update();
float GetTime();
float GetDeltaTime();
bool &IsDebugging();
// Internal Function
// Should not be used
void Debug();
bool &DebugMenu();
bool Button(const std::string &label, NVec2 size = NVec2(0, 0));
void Checkbox(const std::string &label, bool &c);
void Label(const std::string &label, PDTextFlags flags = 0);
void Progressbar(float value);
/// @brief Draw Image in Menu
/// @param img Pointer f.e to Palladium::Image2
void Image(Palladium::Image::Ref img);
void BrowserList(const std::vector<std::string> &entrys, int &selection,
PDTextFlags txtflags = 0, NVec2 size = NVec2(0, 0),
int max_entrys = 13);
void InputText(const std::string &label, std::string &text,
const std::string &hint = "");
bool BeginMenu(const std::string &title, NVec2 size = NVec2(0, 0),
UI7MenuFlags flags = 0);
void EndMenu();
void Grid(const std::string &name, const NVec2 &size, const NVec2 &entry_size,
void (*display_func)(void *, NVec2), void **data_array,
size_t num_entrys);
void ColorSelector(const std::string &label, unsigned int &color);
bool BeginTree(const std::string &text);
void EndTree();
void Prompt(const std::string &label, int &res,
// For Translations
const std::string &lcf = "Confirm",
const std::string &lcc = "Cancel");
void ClosePromts();
NVec2 GetCursorPos();
void SetCursorPos(NVec2 cp);
void RestoreCursor();
void SameLine();
void Separator();
// Internal API (For Creating Custom Objects)
bool InBox(NVec2 inpos, NVec2 boxpos, NVec2 boxsize);
void MoveCursor(NVec2 size);
bool HandleScrolling(NVec2 &pos, NVec2 size);
bool InMenu();
namespace Menu {
// All of them return the Main BG DrawList if Menu is null
UI7DrawList::Ref GetBackgroundList();
UI7DrawList::Ref GetList();
UI7DrawList::Ref GetForegroundList();
// Other Menu Specific Functions
float GetScrollingOffset();
void SetScrollingOffset(float off);
bool IsScrolling();
} // namespace Menu
namespace Next {
// Alignment in ScreenSpace
void Align(UI7Horizontal hz = UI7Horizontal_Left,
UI7Vertical vt = UI7Vertical_Top);
} // namespace Next
// DrawLists
UI7DrawList::Ref GetForegroundList();
UI7DrawList::Ref GetBackgroundList();
} // namespace UI7

View File

@ -1,40 +0,0 @@
#pragma once
#include <3ds.h>
#include <memory>
#include <pd/Error.hpp>
// Write own LinearAllocator for learning
namespace Palladium {
template <typename T>
class LinearAllocator : public std::allocator<T> {
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template <typename T1>
struct rebind {
typedef LinearAllocator<T1> other;
};
pointer allocate(size_type n, const void* hint = nullptr) {
if (n > this->max_size()) {
Palladium::Error(
"Linear Allocator: \nBad Alloc -> size is larger than free space!");
return nullptr;
}
return (pointer)linearAlloc(n * sizeof(T));
}
void deallocate(pointer p, size_type) { linearFree((void*)p); }
size_type max_size() { return linearSpaceFree(); }
LinearAllocator() throw() {}
LinearAllocator(const LinearAllocator<T>& a) throw() : std::allocator<T>(a) {}
~LinearAllocator() throw() {}
};
} // namespace Palladium

View File

@ -1,204 +0,0 @@
#pragma once
#include <unistd.h>
#include <cstring>
#include <memory>
#include <pd/smart_ctor.hpp>
#include <string>
#include <vector>
#define UNPACK_RGBA(col) \
(unsigned char)(col >> 24), (col >> 16), (col >> 8), (col)
#define UNPACK_BGRA(col) \
(unsigned char)(col >> 8), (col >> 16), (col >> 24), (col)
inline unsigned int RGBA8(unsigned char r, unsigned char g, unsigned char b,
unsigned char a = 255) {
return (r | g << 8 | b << 16 | a << 24);
}
typedef int PDColor;
// MultiColor (Less FunctionNameLen)
struct Color2 {
unsigned int color0;
unsigned int color1;
};
struct Color3 {
unsigned int color0;
unsigned int color1;
unsigned int color2;
};
struct Color4 {
unsigned int color0;
unsigned int color1;
unsigned int color2;
unsigned int color3;
};
enum PDColor_ {
PDColor_Text, ///< This Color Should always be used for Light Backgrounds
PDColor_TextDisabled, /// Text Disabled Color
PDColor_Text2, ///< And This want for Texts on Dark Backgrounds
PDColor_Background, ///< Your Bg Color
PDColor_Header, ///< Header Color (if the header is dark text2 is used)
PDColor_Selector, ///< Selector Color
PDColor_SelectorFade, ///< Selector FadingTo Color
PDColor_List0, ///< List Color1
PDColor_List1, ///< List Color2
PDColor_MessageBackground, ///< Message Background
PDColor_Button, ///< Button Color
PDColor_ButtonHovered, ///< Button Color if Hovered
PDColor_ButtonDisabled, ///< Button Color if disabled
PDColor_ButtonActive, ///< Button Colkor if Clicked
PDColor_Checkmark, ///< Checkbox Checkmark Color
PDColor_FrameBg, ///< Frame Background Color
PDColor_FrameBgHovered, ///< Frame Background Color if hovered
PDColor_Progressbar, ///< Progressbar Color
/// NON COLOR ///
PDColor_Len, ///< Used to define the lengh of this list
};
namespace Palladium {
class Theme {
public:
Theme() = default;
~Theme() = default;
void Load(const std::string &path);
void Default();
void Save(const std::string &path);
unsigned int Get(PDColor clr);
void Set(PDColor clr, unsigned int v);
void Swap(PDColor a, PDColor b);
bool Undo();
void UndoAll();
void TextBy(PDColor bg);
PDColor AutoText(PDColor bg);
void ClearHistory() { changes.clear(); }
std::vector<unsigned int> &GetTableRef() { return clr_tab; }
// For Smart Pointer
PD_SMART_CTOR(Theme);
// Loader method
void CopyOther(Theme::Ref theme);
private:
struct change {
change(PDColor a, unsigned int f, unsigned int t)
: clr(a), from(f), to(t) {}
change(PDColor a, PDColor b, unsigned int f, unsigned int t)
: clr(a), clr2(b), from(f), to(t) {}
PDColor clr;
PDColor clr2 = 0; // Used if Swap
unsigned int from;
unsigned int to;
};
// Use a vector for faster access
std::vector<unsigned int> clr_tab;
std::vector<change> changes;
};
Theme::Ref ThemeActive();
/// @brief Change Theme Adress
/// @param theme your adress
void ThemeSet(Theme::Ref theme);
namespace Color {
/// @brief RGBA Class
class RGBA {
public:
/// @brief Construct
/// @param r
/// @param g
/// @param b
/// @param a
RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255)
: m_r(r), m_g(g), m_b(b), m_a(a) {}
/// @brief Construct
/// @param r
/// @param g
/// @param b
/// @param a
RGBA(float r, float g, float b, float a = 1.f)
: m_r(r * 255.f), m_g(g * 255.f), m_b(b * 255.f), m_a(a * 255.f) {}
RGBA(unsigned int in) {
#define ISIMPLEUNPAK(x, y) (((x) >> y) & 0xFF)
m_r = ISIMPLEUNPAK(in, 0);
m_g = ISIMPLEUNPAK(in, 8);
m_b = ISIMPLEUNPAK(in, 16);
m_a = ISIMPLEUNPAK(in, 24);
}
RGBA(PDColor in) {
if (!Palladium::ThemeActive()) return;
unsigned int col = Palladium::ThemeActive()->Get(in);
m_r = ISIMPLEUNPAK(col, 0);
m_g = ISIMPLEUNPAK(col, 8);
m_b = ISIMPLEUNPAK(col, 16);
m_a = ISIMPLEUNPAK(col, 24);
}
RGBA &changeR(unsigned char r) {
m_r = r;
return *this;
}
RGBA &changeG(unsigned char g) {
m_g = g;
return *this;
}
RGBA &changeB(unsigned char b) {
m_b = b;
return *this;
}
RGBA &changeA(unsigned char a) {
m_a = a;
return *this;
}
RGBA &fade_to(const RGBA &color, float p) {
m_a =
m_a + static_cast<unsigned char>((color.m_a - m_a) * ((p + 1.0f) / 2));
m_b =
m_b + static_cast<unsigned char>((color.m_b - m_b) * ((p + 1.0f) / 2));
m_g =
m_g + static_cast<unsigned char>((color.m_g - m_g) * ((p + 1.0f) / 2));
m_r =
m_r + static_cast<unsigned char>((color.m_r - m_r) * ((p + 1.0f) / 2));
return *this;
}
/// @brief Get as Uint32
/// @return color
unsigned int toRGBA() const { return RGBA8(m_r, m_g, m_b, m_a); }
// Just calculate the "lightness" f.e. to use Text or Text2
float luminance() const {
// For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
return (0.3 * (m_r / 255.f) + 0.59 * (m_g / 255.f) + 0.11 * (m_b / 255.f));
}
bool is_light() {
// Gives us the light or dark to not
// always use the below "if" statement
return (luminance() >= 0.5);
}
unsigned char m_r = 0, m_g = 0, m_b = 0, m_a = 0;
};
std::string RGBA2Hex(unsigned int c32);
/// @brief Convert RGB to Hex
/// @param r
/// @param g
/// @param b
/// @return Hex-String
std::string RGB2Hex(int r, int g, int b);
/// @brief Hex to U32
/// @param color
/// @param a
/// @return Color32
unsigned int Hex(const std::string &color, unsigned char a = 255);
} // namespace Color
} // namespace Palladium

View File

@ -1,24 +0,0 @@
#pragma once
#include <string>
#include <vector>
namespace Palladium {
namespace FileSystem {
/// @brief A Directory Entry
struct Entry {
/// @brief Patf of The Entry
std::string path;
/// @brief Name of The Entry
std::string name;
/// @brief Directory or File
bool dir = false;
};
/// @brief Gets All Entrys of A Directory into a Vector
/// @param path The Path of the Directory
/// @return The Vector of found Entrys
std::vector<Palladium::FileSystem::Entry> GetDirContent(std::string path);
std::string GetParentPath(std::string path, std::string mount_point);
std::vector<Entry> GetDirContentsExt(
std::string &path, const std::vector<std::string> &extensions);
} // namespace FileSystem
} // namespace Palladium

View File

@ -1,137 +0,0 @@
#pragma once
// Base includes
#include <functional>
#include <map>
#include <string>
// 3ds does not support std::chrono
#include <3ds.h>
/// @brief 3ds System Ticks per milli second
#define TICKS_PER_MSEC 268111.856
#define f2s(x_) #x_
#define scomb(x1, x2) std::string(x1 + x2)
namespace Palladium {
namespace Ftrace {
class TimeStats {
public:
TimeStats(int len) : len(len), values(len, 0) {}
void Add(float v) {
values[idx] = v;
idx = next_index(idx);
num_values = std::min(num_values + 1, len);
}
float GetAverage() {
float res = 0.f;
if (!num_values) {
return res;
}
for (int i = 0; i < num_values; ++i) {
res += values[index(i)];
}
return res / num_values;
}
float GetMax() {
float res = 0.f;
if (!num_values) {
return res;
}
for (int i = 0; i < num_values; i++) {
res = std::max(res, values[index(i)]);
}
return res;
}
float GetMin() {
float res = 0.f;
if (!num_values) {
return res;
}
res = values[0];
for (int i = 0; i < num_values; i++) {
res = std::min(res, values[index(i)]);
}
return res;
}
const std::vector<float>& GetData() { return values; }
const float& operator[](int i) { return values[index(i)]; }
const size_t GetLen() { return len; }
const size_t GetNumValues() { return num_values; }
private:
// Indexing Functions for better overview
size_t next_index(size_t current) const { return (current + 1) % len; }
size_t index(size_t v) const { return (idx + len - num_values + v) % len; }
// Data
int len = 0;
std::vector<float> values;
int idx = 0;
int num_values = 0;
};
/// @brief Result of FTrace
struct FTRes {
FTRes() : time_start(0), time_end(0), time_of(0.f), is_ovl(false), ts(60) {}
std::string group; ///< Group of the Trace
std::string func_name; ///< Function Name
uint64_t time_start; ///< when started
uint64_t time_end; ///< when stopped
float time_of; ///< stop - start (how long)
bool is_ovl; ///< is displayed in overlay?
TimeStats ts; ///< Time Stats
};
/// @brief Map of Traces
extern std::map<std::string, Palladium::Ftrace::FTRes> pd_traces;
/// @brief Set a Start TracePoint
/// @param group Set a Group Name
/// @param func_name Set a Function Name
inline void Beg(const std::string& group, const std::string& func_name) {
std::string trace_id = scomb(group, func_name);
auto& trace = pd_traces[trace_id];
trace.group = group;
trace.func_name = func_name;
trace.time_start = svcGetSystemTick();
}
/// @brief Set an End TracePoint
/// @param group Set a Group Name
/// @param func_name Set a Function Name
inline void End(const std::string& group, const std::string& func_name) {
std::string trace_id = scomb(group, func_name);
auto& trace = pd_traces[trace_id];
trace.time_end = svcGetSystemTick();
trace.time_of =
static_cast<float>(trace.time_end - trace.time_start) / TICKS_PER_MSEC;
trace.ts.Add(trace.time_of);
}
/// @brief Trace a function execution
/// @param group Set a Group Name
/// @param name Set a Function Name
inline void Func(const std::string& group, const std::string& name,
std::function<void()> fun) {
if (!fun) return;
Beg(group, name);
fun();
End(group, name);
}
/// @brief This Starts an Ftrace and
/// end ist when going out of scope
struct ScopedTrace {
ScopedTrace(std::string g, std::string n) : group(g), name(n) {
Ftrace::Beg(g, n);
}
~ScopedTrace() { Ftrace::End(group, name); }
std::string group;
std::string name;
};
} // namespace Ftrace
} // namespace Palladium

View File

@ -1,24 +0,0 @@
#pragma once
// clang-format off
#include <string>
#include <pd/external/json.hpp>
// clang-format on
namespace Palladium {
namespace Lang {
/// @brief Get 3ds System lang! [en] by default
/// @return Sytemlang as string
std::string GetSys();
/// @brief Get The Translation String
/// @param key Key of Translation
/// @return The Translated String
std::string Get(const std::string &key);
/// @brief Load A Language json
/// @param lang The Language Key [en], [de], etc, or getSys()
void Load(const std::string &lang);
// New funcs
std::string GetName();
std::string GetAuthor();
std::string GetShortcut();
} // namespace Lang
} // namespace Palladium

View File

@ -1,26 +0,0 @@
#pragma once
#include <cstddef>
namespace Palladium {
namespace Memory {
/// @brief Metriks struct For the Internal Tracker
struct memory_metrics {
unsigned int t_TotalAllocated = 0; ///< Total Allocated Memory
unsigned int t_TotalFreed = 0; ///< Total Deleted Memory
/// @brief Gets the Currently Allocated Memory
unsigned int t_CurrentlyAllocated() {
return t_TotalAllocated - t_TotalFreed;
}
};
/// @brief Get Total Allocated Memory
/// @return Total Allocated Memory
size_t GetTotalAllocated();
/// @brief Get Total Deleted Memory
/// @return Total Deleted Memory
size_t GetTotalFreed();
/// @brief Get Current Allocated Memory
/// @return Current Allocated Memory
size_t GetCurrent();
} // namespace Memory
} // namespace Palladium

View File

@ -1,98 +0,0 @@
#pragma once
#include <format>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
namespace Palladium {
/// @brief Check if A String ends with
/// @param name Input String
/// @param extensions Extensions to Check for
/// @return Ends with or not
inline bool NameIsEndingWith(const std::string &name,
const std::vector<std::string> &extensions) {
if (name.substr(0, 2) == "._") return false;
if (name.size() == 0) return false;
if (extensions.size() == 0) return true;
for (int i = 0; i < (int)extensions.size(); i++) {
const std::string ext = extensions.at(i);
if (strcasecmp(name.c_str() + name.size() - ext.size(), ext.c_str()) == 0)
return true;
}
return false;
}
/// @brief Format Milliseconds to clean string (Stolen from one of my Mc
/// Plugins)
/// @param t_time Time in ms
/// @return String
inline std::string MsTimeFmt(float t_time, bool dems = false) {
std::string res;
if (t_time < 0.000001f) {
res = std::format("{:.2f}ns", t_time * 1000000.f);
} else if (t_time < 0.001f) {
res = std::format("{:.2f}µs", t_time * 1000.f);
} else if (t_time < 1.0f) {
res = std::format("{:.2f}ms", t_time);
} else if (t_time < 60000.0f) {
int seconds = static_cast<int>(t_time / 1000.0f);
float milliseconds = t_time - (seconds * 1000.0f);
if (seconds) {
res = std::format("{}s {:.2f}ms", seconds, milliseconds);
}
res = std::format("{:.2f}ms", milliseconds);
} else {
int minutes = static_cast<int>(t_time / 60000.0f);
int seconds = static_cast<int>((t_time - (minutes * 60000.0f)) / 1000.0f);
float milliseconds = t_time - (minutes * 60000.0f) - (seconds * 1000.0f);
res = std::format("{}m {}s {:.2f}ms", minutes, seconds, milliseconds);
}
return res;
}
inline std::string FormatBytes(int bytes) {
char out[32];
if (bytes == 1)
snprintf(out, sizeof(out), "%d Byte", bytes);
else if (bytes < 1024)
snprintf(out, sizeof(out), "%d Bytes", bytes);
else if (bytes < 1024 * 1024)
snprintf(out, sizeof(out), "%.1f KB", (float)bytes / 1024);
else if (bytes < 1024 * 1024 * 1024)
snprintf(out, sizeof(out), "%.1f MB", (float)bytes / 1024 / 1024);
else
snprintf(out, sizeof(out), "%.1f GB", (float)bytes / 1024 / 1024 / 1024);
return out;
}
} // namespace Palladium
template <class T>
T GetFileName(T const &path, T const &delims = "/\\") {
return path.substr(path.find_last_of(delims) + 1);
}
template <class T>
T remove_ext(T const &filename) {
typename T::size_type const p(filename.find_last_of('.'));
return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}
template <typename T>
std::string Int_To_Hex(T i) {
std::stringstream stream;
stream << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex
<< i;
return stream.str();
}

68
include/pd/common/app.hpp Normal file
View File

@ -0,0 +1,68 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
#include <pd/common/timetrace.hpp>
#include <pd/graphics/lithium.hpp>
namespace PD {
/// @brief Template Class for User Application
class App : public SmartCtor<App> {
public:
App() = default;
~App() = default;
/// @brief Templete function where the user can Init his stuff
virtual void Init() {}
/// @brief Templeta funciton to deinit stuff
/// (most of that is done automatically)
virtual void Deinit() {}
/// @brief App Mainloop
/// @param delta Deltatime
/// @param time App RunTime
/// @return false to exit the app
virtual bool MainLoop(u64 delta, float time) { return false; }
/// @brief Function to run the App
/// (int main() {
/// auto app = PD::New<UserApp>();
/// app->Run();
/// return 0;
/// })
void Run();
LI::Renderer::Ref Renderer() { return renderer; }
float GetFps() const { return fps; }
private:
void PreInit();
void PostDeinit();
LI::Renderer::Ref renderer;
u64 last_time;
float app_time;
float fps;
};
} // namespace PD

View File

@ -0,0 +1,71 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <chrono>
#include <cinttypes>
#include <cmath>
#include <filesystem> // Requires C++ 17 or later
#include <format> // Requires C++ 20 or later
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
namespace PD {
// New Version of Smart CTOR
// Using as Template class
template <typename T>
class SmartCtor {
public:
/// @brief Type Reference
using Ref = std::shared_ptr<T>;
/// @brief Creates a New Shared Pointer
/// @param ...args Arguments to forward
/// @return Shared Pointer (Reference)
template <typename... Args>
static Ref New(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
};
/// @brief Wrapper for SmartCtor<Type>::New
/// @tparam T class type
/// @param ...args Arguments
/// @return SmartCtor<T>::Ref type reference
/// @note Not sure if this is solving the problem or
/// if I schould switch back to the macro
template <typename T, typename... Args>
SmartCtor<T>::Ref New(Args&&... args) {
return SmartCtor<T>::New(std::forward<Args>(args)...);
}
// Defines
using u64 = unsigned long long;
using u32 = unsigned int;
using u16 = unsigned short;
using u8 = unsigned char;
} // namespace PD

View File

@ -0,0 +1,31 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
void Error(const std::string& error);
void Assert(bool v, const std::string& msg);
} // namespace PD

View File

@ -0,0 +1,57 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
/// @brief Lang System
///< Translations are saved into json files
///< Path should point to a directory the fils
///< for example the files ar named [en.json, de.json, fr.json]
class Lang : public SmartCtor<Lang> {
public:
Lang() = default;
~Lang() = default;
void SetBasePath(const std::string &path) { langs_path = path; }
void Load(const std::string &lang_key) {
LoadFile(langs_path + "/" + lang_key + ".json");
}
void LoadFile(const std::string &path);
const std::string &Get(const std::string &k);
const std::string &GetName() { return lang_name; }
const std::string &GetID() { return lang_id; }
const std::string &GetAuthor() { return lang_author; }
const std::string &GetPath() { return langs_path; }
private:
const int ver = 0;
std::string langs_path = "romfs:/lang";
std::string lang_name;
std::string lang_id;
std::string lang_author;
std::map<std::string, std::string> ltable;
};
} // namespace PD

View File

@ -0,0 +1,60 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <3ds.h>
#include <pd/common/common.hpp>
#include <pd/common/error.hpp>
namespace PD {
template <typename T>
class LinearAllocator : public std::allocator<T> {
public:
using size_type = size_t;
using pointer = T*;
using const_pointer = const T*;
template <typename T1>
struct rebind {
using other = LinearAllocator<T1>;
};
pointer allocate(size_type n, const void* hint = nullptr) {
if (n > this->max_size()) {
Error("Linear Alloc failed (no space left)");
return nullptr;
}
return (pointer)linearAlloc(n * sizeof(T));
}
void deallocate(pointer p, size_type) { linearFree((void*)p); }
size_type max_size() { return linearSpaceFree(); }
LinearAllocator() noexcept {}
LinearAllocator(const LinearAllocator<T>& a) noexcept
: std::allocator<T>(a) {}
~LinearAllocator() noexcept {}
};
} // namespace PD

View File

@ -0,0 +1,42 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
namespace Strings {
bool StringEndsWith(const std::string& str,
const std::vector<std::string>& exts);
std::wstring MakeWstring(const std::string& s);
const std::string FormatNanos(unsigned long long nanos);
const std::string FormatMillis(unsigned long long millis);
const std::string FormatBytes(unsigned long long bytes);
const std::string GetFileName(const std::string& path,
const std::string& saperators = "/\\");
const std::string PathRemoveExtension(const std::string& path);
template <typename T>
const std::string ToHex(const T& v);
} // namespace Strings
} // namespace PD

37
include/pd/common/sys.hpp Normal file
View File

@ -0,0 +1,37 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
#include <pd/common/timetrace.hpp>
namespace PD {
namespace Sys {
using TraceMap = std::map<std::string, TT::Res::Ref>;
u64 GetTime();
u64 GetNanoTime();
TT::Res::Ref& GetTraceRef(const std::string& id);
TraceMap& GetTraceMap();
} // namespace Sys
} // namespace PD

View File

@ -0,0 +1,44 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
#include <pd/common/sys.hpp>
namespace PD {
class Timer {
public:
Timer() {}
~Timer() {}
void Start() {}
void Pause() {}
void Update() {}
void Reset() { start_ = Sys::GetTime(); }
u64 Get() {}
private:
u64 start_;
u64 now_;
};
} // namespace PD

View File

@ -0,0 +1,102 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
class TimeStats : public SmartCtor<TimeStats> {
public:
TimeStats(int l) : len(l), val(l, 0) {}
~TimeStats() = default;
void Add(unsigned long long v) {
val[idx] = v;
idx = next(idx);
num_val = std::min(num_val + 1, len);
}
unsigned long long GetAverage() {
if (!num_val) return 0.f;
unsigned long long res = 0;
for (int i = 0; i < num_val; i++) {
res += val[smart_idx(i)];
}
return res / num_val;
}
const std::vector<unsigned long long> &GetData() { return val; }
const unsigned long long &operator[](int i) { return val[smart_idx(i)]; }
const size_t GetLen() { return len; }
const size_t GetNumValues() { return num_val; }
private:
size_t next(size_t c) const { return (c + 1) % len; }
size_t smart_idx(size_t v) const { return (idx + len - num_val + v) % len; }
int len = 0;
std::vector<unsigned long long> val;
int idx = 0;
int num_val = 0;
};
namespace TT {
class Res : public SmartCtor<Res> {
public:
Res() { protocol = TimeStats::New(60); }
~Res() = default;
void SetID(const std::string &v) { id = v; }
const std::string GetID() { return id; }
void SetStart(unsigned long long v) { start = v; }
unsigned long long GetStart() { return start; }
void SetEnd(unsigned long long v) {
end = v;
protocol->Add(GetLastDiff());
}
unsigned long long GetEnd() { return end; }
unsigned long long GetLastDiff() { return end - start; }
TimeStats::Ref GetProtocol() { return protocol; }
private:
std::string id;
unsigned long long start;
unsigned long long end;
TimeStats::Ref protocol;
};
void Beg(const std::string &id);
void End(const std::string &id);
class Scope {
public:
Scope(const std::string &id) {
this->id = id;
Beg(id);
}
~Scope() { End(id); }
private:
std::string id;
};
} // namespace TT
} // namespace PD

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
#pragma once
#include <pd/external/json.hpp>
#include <pd/palladium.hpp>
namespace Palladium {
namespace IDB {
void Start();
void Stop();
void Restart();
} // namespace IDB
} // namespace Palladium
using PDFlags = unsigned int;
enum PDFlags_ {
PDFlags_None = 0,
PDFlags_MemTrack = 1 << 0,
PDFlags_SceneSystem = 1 << 1,
PDFlags_Default = PDFlags_SceneSystem,
};
using PDMetrikOverlayFlags = unsigned int;
enum PDMetrikOverlayFlags_ {
PDMetrikOverlayFlags_None = 0, // Displays Nothing
PDMetrikOverlayFlags_FPS = 1 << 0, // Display FPS
PDMetrikOverlayFlags_CPU = 1 << 1, // Display CPU Usage
PDMetrikOverlayFlags_GPU = 1 << 2, // Display GPU Usage
PDMetrikOverlayFlags_CMD = 1 << 3, // Display GPU CMD Usage
PDMetrikOverlayFlags_LMM = 1 << 4, // Display Linear Space Free
PDMetrikOverlayFlags_LVT = 1 << 5, // Display Lithium Vertex Usage
PDMetrikOverlayFlags_LID = 1 << 6, // Display Lithium Indices Usage
PDMetrikOverlayFlags_LDM = 1 << 7, // Display Lithium Draw Command Num
PDMetrikOverlayFlags_LDC = 1 << 8, // Display Lithium Drawcalls Count
PDMetrikOverlayFlags_PDO = 1 << 9, // Display Overlay Info String
PDMetrikOverlayFlags_MTD = 1 << 10, // Display Memory Usage (if enabled)
PDMetrikOverlayFlags_CGR = 1 << 11, // Display CPU Graph
PDMetrikOverlayFlags_GGR = 1 << 12, // Display GPU Graph
PDMetrikOverlayFlags_Default =
PDMetrikOverlayFlags_FPS | PDMetrikOverlayFlags_CPU |
PDMetrikOverlayFlags_GPU | PDMetrikOverlayFlags_CMD |
PDMetrikOverlayFlags_LMM | PDMetrikOverlayFlags_LVT |
PDMetrikOverlayFlags_LID | PDMetrikOverlayFlags_LDM |
PDMetrikOverlayFlags_LDC | PDMetrikOverlayFlags_PDO |
PDMetrikOverlayFlags_MTD, // Enable All of Them exept Graphs
};
using PDFTraceOverlayFlags = unsigned int;
enum PDFTraceOverlayFlags_ {
PDFTraceOverlayFlags_None = 0, // Displays Nothing
PDFTraceOverlayFlags_DisplayName = 1 << 0, // Display Tracename
PDFTraceOverlayFlags_DisplayAverage = 1 << 1, // Display Average Time
PDFTraceOverlayFlags_DisplayMin = 1 << 2, // Display Minimum Time
PDFTraceOverlayFlags_DisplayMax = 1 << 3, // Display Maximum Time
PDFTraceOverlayFlags_FillBg = 1 << 4, // Make Background Darker
PDFTraceOverlayFlags_DisplayHelp = 1 << 5, // Display Info for values
PDFTraceOverlayFlags_Default =
PDFTraceOverlayFlags_DisplayName | PDFTraceOverlayFlags_DisplayAverage |
PDFTraceOverlayFlags_DisplayMin | PDFTraceOverlayFlags_DisplayMax |
PDFTraceOverlayFlags_FillBg |
PDFTraceOverlayFlags_DisplayHelp, // Enable All of Them
};
// Outdated HidApi (HidV2Patched)
extern u32 d7_hDown;
extern u32 d7_hHeld;
extern u32 d7_hUp;
extern u32 d7_hRepeat; // Inofficial lol
extern touchPosition d7_touch;
// Modern Global Api
extern C3D_RenderTarget *pd_top;
extern C3D_RenderTarget *pd_top_right;
extern C3D_RenderTarget *pd_bottom;
extern PDFlags pd_flags;
extern PDMetrikOverlayFlags pd_ovl_flags;
extern PDFTraceOverlayFlags pd_ftrace_ovl_flags;
// Draw2
extern float pd_draw2_tsm;

View File

@ -0,0 +1,31 @@
// THIS FILE WAS GENERATED BY build_shaders.py!!!
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <cstddef>
extern unsigned char li7_shader[];
extern size_t li7_shader_size;

View File

@ -0,0 +1,433 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
#include <pd/common/memory.hpp>
#include <pd/graphics/screen.hpp>
#include <pd/graphics/texture.hpp>
#include <pd/maths/vec.hpp>
#include <pd/tools/markdown.hpp>
using LITextFlags = u32;
enum LITextFlags_ {
LITextFlags_None = 0,
LITextFlags_AlignRight = 1 << 0,
LITextFlags_AlignMid = 1 << 1,
LITextFlags_Shaddow = 1 << 2, // Draws the text twice
LITextFlags_Wrap = 1 << 3, // May be runs better with TMS
LITextFlags_Short = 1 << 4, // May be runs better with TMS
LITextFlags_Scroll = 1 << 5, // Not implemented
};
namespace PD {
namespace LI {
/// @brief Container that holds top and bottom corners of a quad
class Rect {
public:
Rect() = default;
Rect(vec4 t, vec4 b) {
top = t;
bot = b;
}
Rect(vec2 tl, vec2 tr, vec2 bl, vec2 br) {
top = vec4(tl, tr);
bot = vec4(bl, br);
}
~Rect() = default;
vec4 Top() const { return top; }
vec4 Bot() const { return bot; }
vec2 TopLeft() const { return vec2(top[0], top[1]); }
vec2 TopRight() const { return vec2(top[2], top[3]); }
vec2 BotLeft() const { return vec2(bot[0], bot[1]); }
vec2 BotRight() const { return vec2(bot[2], bot[3]); }
private:
vec4 top;
vec4 bot;
};
class Font : public SmartCtor<Font> {
public:
class Codepoint {
public:
Codepoint() {}
~Codepoint() {}
u32 cp() const { return m_cp; }
Codepoint& cp(u32 v) {
m_cp = v;
return *this;
}
vec4 uv() const { return m_uv; }
Codepoint& uv(vec4 v) {
m_uv = v;
return *this;
}
Texture::Ref tex() const { return m_tex; }
Codepoint& tex(Texture::Ref v) {
m_tex = v;
return *this;
}
vec2 size() const { return m_size; }
Codepoint& size(vec2 v) {
m_size = v;
return *this;
}
float off() const { return m_off; }
Codepoint& off(float v) {
m_off = v;
return *this;
}
bool invalid() const { return m_invalid; }
Codepoint& invalid(bool v) {
m_invalid = v;
return *this;
}
private:
u32 m_cp = 0;
vec4 m_uv;
Texture::Ref m_tex = nullptr;
vec2 m_size;
float m_off = 0;
bool m_invalid = false;
};
Font() {}
~Font() {}
void LoadTTF(const std::string& path, int px_height = 32);
void LoadSystemFont();
int PixelHeight() const { return pixel_height; }
Codepoint& GetCodepoint(u32 c);
bool SystemFont() const { return sysfont; }
private:
bool sysfont;
int pixel_height;
std::vector<Texture::Ref> textures;
std::map<u32, Codepoint> cpmap;
};
class Vertex {
public:
Vertex() {}
Vertex(vec2 p, vec2 u, u32 c) {
pos[0] = p[0];
pos[1] = p[1];
pos[2] = 0.f;
uv = u;
color = c;
}
~Vertex() {}
Vertex& Pos(vec3 v) {
pos = v;
return *this;
}
// Lets support that as well
Vertex& Pos(vec2 v) {
pos[0] = v[0];
pos[1] = v[1];
pos[2] = 0.f;
return *this;
}
Vertex& Uv(vec2 v) {
uv = v;
return *this;
}
Vertex& Color(u32 v) {
color = v;
return *this;
}
// private:
vec3 pos;
vec2 uv;
u32 color;
};
/// @brief Required to Set the TexENV
enum RenderMode {
RenderMode_RGBA,
RenderMode_SysFont,
};
/// @brief Reform the Drawcommand by generating the Vertexbuffer into it
class Command : public SmartCtor<Command> {
public:
Command() {}
~Command() {}
Command& Layer(int v) {
layer = v;
return *this;
}
int Layer() const { return layer; }
Command& Index(int v) {
index = v;
return *this;
}
int Index() const { return index; }
Command& Tex(Texture::Ref v) {
tex = v;
return *this;
}
Texture::Ref Tex() const { return tex; }
Command& PushVertex(Vertex v) {
vertex_buf.push_back(v);
return *this;
}
const std::vector<u16>& IndexList() const { return index_buf; }
const std::vector<Vertex>& VertexList() const { return vertex_buf; }
Command& PushIndex(u16 v) {
index_buf.push_back(vertex_buf.size() + v);
return *this;
}
Command& Rendermode(const RenderMode& v) {
mode = v;
return *this;
}
RenderMode Rendermode() const { return mode; }
private:
/// Using Default std::vector here
std::vector<Vertex> vertex_buf;
std::vector<u16> index_buf;
int layer;
Texture::Ref tex;
int index;
RenderMode mode = RenderMode_RGBA;
};
class TextBox {
public:
TextBox() {}
TextBox(const vec2& s, float time) {
size = s;
time_created = time;
optional = false;
}
~TextBox() {}
void TimeCreated(float v) { time_created = v; }
void Size(const vec2& v) { size = v; }
void Optional(bool v) { optional = v; }
void Text(const std::string& v) { text = v; }
vec2 Size() const { return size; }
float TimeCreated() const { return time_created; }
bool Optional() const { return optional; }
std::string Text() const { return text; }
private:
vec2 size;
float time_created;
bool optional;
std::string text; // TextWrap
};
using RenderFlags = u32;
enum RenderFlags_ {
RenderFlags_None = 0,
RenderFlags_TMS = 1 << 0, ///< Text Map System
RenderFlags_LRS = 1 << 1, ///< Layer Render System
RenderFlags_Default = RenderFlags_TMS,
};
class Renderer : public SmartCtor<Renderer> {
public:
Renderer(RenderFlags flags = RenderFlags_Default);
~Renderer();
void Render();
void OnScreen(Screen::Screen_ screen) {
if (screen == Screen::Top) {
bottom = false;
area_size = top->GetSize();
} else if (screen == Screen::Bottom) {
bottom = true;
area_size = bot->GetSize();
} else {
return;
}
}
void OnScreen(bool bottom) {
bottom = bottom;
area_size = bottom ? bot->GetSize() : top->GetSize();
}
void Rotation(float v) { rot = v; }
float Rotation() const { return rot; }
void TextScale(float v) { text_size = v; }
void DefaultTextScale() { text_size = default_text_size; }
float TextScale() const { return text_size; }
void UseTex(Texture::Ref v = nullptr) {
if (v == nullptr) {
current_tex = white;
return;
}
current_tex = v;
}
/// @brief Draws a Rect based on current Texture
/// @param pos Pos
/// @param size Size
/// @param color Color
/// @param uv UV Map
void DrawRect(vec2 pos, vec2 size, u32 color,
vec4 uv = vec4(0.f, 1.f, 1.f, 0.f));
/// @brief Draw a Solid Rect (uses white tex)
/// @note acts as a simplified Draw rect Wrapper
/// @param pos Position
/// @param size Size
/// @param color Color
void DrawRectSolid(vec2 pos, vec2 size, u32 color);
/// @brief Render a Triangle
/// @param a Position Alpha
/// @param b Position Bravo
/// @param c Position Delta
/// @param color Color
/// @note Defaults to Solif Color
void DrawTriangle(vec2 a, vec2 b, vec2 c, u32 color);
/// @brief Draw a Circle (Supports Textures)
/// @param center_pos Center Position
/// @param r Radius
/// @param color Color
/// @param segments Segments to use
/// @note Textures could look a bit janky due to uv mapping
void DrawCircle(vec2 center_pos, float r, u32 color, int segments);
/// @brief Draw a Line between to Positions
/// @param a Position Alpha
/// @param b Position Bravo
/// @param color Color
/// @param t Thickness
void DrawLine(vec2 a, vec2 b, u32 color, int t);
void DrawText(vec2 pos, u32 color, const std::string& text, u32 flags = 0,
vec2 ap = vec2());
/// @brief Draw a Texture as 2D Image
/// @param pos Position
/// @param tex Texture reference
/// @param scale Scale (cause maybe wants to be resized)
/// @note Acts as a Simplified wrapper to DrawRect
void DrawImage(vec2 pos, Texture::Ref tex, vec2 scale = vec2(1.f));
/// Debug STUFF
u32 Vertices() const { return vertices; }
u32 Indices() const { return indices; }
u32 Commands() const { return commands; }
u32 DrawCalls() const { return drawcalls; }
/// TOOLS ///
void RotateCorner(vec2& v, float s, float c);
Rect CreateRect(vec2 pos, vec2 size, float angle);
Rect CreateLine(vec2 a, vec2 b, int t);
bool InBox(vec2 pos, vec2 size, vec4 rect);
bool InBox(vec2 alpha, vec2 bravo, vec2 charlie, vec4 rect);
void OptiCommandList(std::vector<Command::Ref>& list);
/// @brief Returns Viewport with xy
vec4 GetViewport();
/// @brief Push a Self Created command
void PushCommand(Command::Ref cmd) { draw_list[bottom].push_back(cmd); }
/// @brief Automatically sets up a command
void SetupCommand(Command::Ref cmd);
/// @brief Creates a default Quad Render Command
void QuadCommand(Command::Ref cmd, const Rect& quad, vec4 uv, u32 col);
/// @brief Create a Default Triangle
void TriangleCommand(Command::Ref cmd, vec2 a, vec2 b, vec2 c, u32 col);
/// @brief Create List of a Text Commands
/// @param cmds Link to a command List
/// @param pos Position
/// @param color Color
/// @param text Text
/// @param flags Flags
/// @param box (Size for wrapping / Offset for Centered Text)
/// @note Funktion macht noch faxxen (Text nicht sichtbar)
void TextCommand(std::vector<Command::Ref>& cmds, vec2 pos, u32 color,
const std::string& text, LITextFlags flags, vec2 box);
vec2 GetTextDimensions(const std::string& text);
private:
/// Helper Funcitons ///
void RenderOn(bool bottom);
void UpdateRenderMode(const RenderMode& mode);
/// @brief Screens ///
Screen::Ref top;
Screen::Ref bot;
/// Context Related ///
RenderFlags flags = RenderFlags_Default;
vec2 area_size;
bool bottom = false;
int current_layer = 0;
Texture::Ref current_tex = nullptr;
Texture::Ref white = nullptr; // Single color
Font::Ref font = nullptr;
bool font_update;
RenderMode mode = RenderMode_RGBA;
// Text Map System
std::map<std::string, TextBox> tms;
/// Text Rendering ///
const float default_font_h = 24.f;
const float default_text_size = 0.7f;
float text_size = 0.7f;
/// Special ///
float rot = 0.f;
/// Rendering ///
// Use dual drawlist
std::vector<Command::Ref> draw_list[2];
std::vector<Vertex, LinearAllocator<Vertex>> vertex_buf;
std::vector<u16, LinearAllocator<u16>> index_buf;
u32 vertex_idx = 0;
u32 index_idx = 0;
u32 cmd_idx = 0;
/// Debug ///
u32 vertices = 0;
u32 indices = 0;
u32 commands = 0;
u32 drawcalls = 0;
/// Shader
DVLB_s* dvlb = nullptr;
shaderProgram_s shader;
C3D_AttrInfo attr;
int uLoc_projection = 0;
/// Matrix
C3D_Mtx top_proj;
C3D_Mtx bot_proj;
};
} // namespace LI
} // namespace PD

View File

@ -0,0 +1,74 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <3ds.h>
#include <citro3d.h>
#include <pd/common/common.hpp>
#include <pd/maths/vec.hpp>
namespace PD {
class Screen : public SmartCtor<Screen> {
public:
enum Screen_ { Top, Bottom, TopRight };
Screen(Screen_ screen) {
if (screen == Top) {
target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8,
GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT,
DisplayTransferFlags);
} else if (screen == Bottom) {
target = C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8,
GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetOutput(target, GFX_BOTTOM, GFX_LEFT,
DisplayTransferFlags);
} else if (screen == TopRight) {
target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8,
GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_RIGHT,
DisplayTransferFlags);
}
}
~Screen() {}
void Clear() { C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0x00000000, 0); }
void Use() { C3D_FrameDrawOn(target); }
vec2 GetSize() const {
return vec2(target->frameBuf.height, target->frameBuf.width);
}
C3D_RenderTarget* Get() const { return target; }
operator C3D_RenderTarget*() const { return target; }
private:
const u32 DisplayTransferFlags =
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) |
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) |
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) |
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO));
C3D_RenderTarget* target;
};
} // namespace PD

View File

@ -0,0 +1,123 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <citro3d.h>
#include <pd/common/common.hpp>
#include <pd/maths/vec.hpp>
namespace PD {
class Texture : public SmartCtor<Texture> {
public:
enum Type {
RGBA32,
RGB24,
A8,
};
enum Filter {
NEAREST,
LINEAR,
};
/// @brief Default constructor
Texture() : uv(0.f, 1.f, 1.f, 0.f) {}
/// @brief Load file Constructor
/// @param path path to file
Texture(const std::string& path) : uv(0.f, 1.f, 1.f, 0.f) {
this->LoadFile(path);
}
/// @brief Load Memory constructor
/// @param data File Data reference
Texture(const std::vector<u8>& data) : uv(0.f, 1.f, 1.f, 0.f) {
this->LoadMemory(data);
}
/// @brief Load Pixels constructor
/// @param data Pixel Buffer reference
/// @param w width
/// @param h height
/// @param type Buffer Type
/// @param filter Filter
Texture(const std::vector<u8>& data, int w, int h, Type type = RGBA32,
Filter filter = NEAREST)
: uv(0.f, 1.f, 1.f, 0.f) {
this->LoadPixels(data, w, h, type, filter);
}
/// @brief Deconstructor (aka auto delete)
~Texture() { Delete(); }
/// @brief Deletes image (if not already unloaded)
void Delete();
/// @brief Load a png/jpg/bmp from fs into a gpu tex
/// @param path path to image file
void LoadFile(const std::string& path);
/// @brief Load a png/jpg/bmp from memory
/// @param data reference to data buffer of the file
void LoadMemory(const std::vector<u8>& data);
/// @brief Create Texture out of Pixel Data
/// @param data Data reference
/// @param w width
/// @param h heigt
/// @param type Type of the databuffer
/// @param filter Filter (NEAREST OR LINEAR)
void LoadPixels(const std::vector<u8>& data, int w, int h, Type type = RGBA32,
Filter filter = NEAREST);
/// @brief Input a Texture that you had set up on your own
/// @param tex Texture reference (deletes itself)
/// @param rszs The size of the source image
/// @param uvs Your uv Setup
void LoadExternal(C3D_Tex* tex, vec2 rszs, vec4 uvs) {
this->Delete();
this->tex = tex;
this->size = rszs;
this->uv = uvs;
}
vec2 GetRealSize() {
if (!tex) {
return vec2();
}
return vec2(tex->width, tex->height);
}
vec2 GetSize() const { return size; }
C3D_Tex* GetTex() const { return tex; };
vec4 GetUV() const { return uv; }
bool IsValid() const { return tex != 0; }
operator C3D_Tex*() const { return tex; }
operator vec2() const { return size; }
operator vec4() const { return uv; }
operator bool() const { return tex != 0; }
private:
void MakeTex(std::vector<u8>& buf, int w, int h, Type type = RGBA32,
Filter filter = NEAREST);
vec2 size;
vec4 uv;
C3D_Tex* tex = nullptr;
};
} // namespace PD

View File

@ -1,64 +0,0 @@
#pragma once
#include <pd/Net.hpp>
#include <pd/external/json.hpp>
#include <pd/global_db.hpp>
#include <pd/palladium.hpp>
#define CFGVER "2"
#define THEMEVER "0"
#ifndef V_PDBTIME
#define V_PDBTIME "SUBMODULE"
#endif
#ifndef V_PDCSTRING
#define V_PDCSTRING "SUBMODULE"
#endif
// Base
extern bool pdi_enable_scene_system;
extern bool pdi_debugging;
extern bool pdi_enable_memtrack;
extern std::string pdi_app_name;
extern std::string pdi_config_path;
extern nlohmann::json pdi_config;
extern u8 pdi_console_model;
extern u8 pdi_system_region;
extern bool pdi_is_citra;
extern bool pdi_settings;
extern NVec2 pdi_hid_touch_pos;
extern bool pdi_is_ndsp;
extern bool pdi_running;
extern std::unique_ptr<Palladium::Scene> pdi_fade_scene;
extern std::vector<std::unique_ptr<Palladium::Ovl>> pdi_overlays;
extern unsigned int pdi_frames;
extern u64 pdi_last_time;
extern float pdi_framerate;
extern unsigned int pdi_mt_color;
extern unsigned int pdi_mt_txtcolor;
extern bool pdi_mt_screen;
extern float pdi_mt_txtSize;
extern bool pdi_metrikd;
extern bool pdi_ftraced;
extern u64 pdi_delta_time;
extern u64 pdi_last_tm;
extern float pdi_dtm;
extern float pdi_time;
extern bool pdi_fadeout;
extern bool pdi_fadein;
extern bool pdi_fadeout2;
extern bool pdi_fadein2;
extern int pdi_fadealpha;
extern int pdi_fadecolor;
extern bool pdi_wait_fade;
extern bool pdi_fade_exit;
extern bool pdi_fade_scene_wait;
extern bool pdi_idb_running;
extern bool pdi_graphics_on;
extern bool pdi_amdt;
extern void* pdi_soc_buf;
extern bool pdi_is_am_init;
extern Palladium::Theme::Ref pdi_active_theme;
extern bool pdi_lggrf;
Palladium::Net::Error pdi_soc_init();
void pdi_soc_deinit();

View File

@ -1,8 +0,0 @@
// THIS FILE WAS GENERATED BY build_shaders.py!!!
#pragma once
#include <cstddef>
extern unsigned char li7_shader[];
extern size_t li7_shader_size;

View File

@ -1,45 +0,0 @@
#pragma once
#include <pd/maths/NVec.hpp>
class NMat4 {
public:
NMat4() { Zeros(); }
~NMat4() {}
void Zeros() { memset(this, 0, sizeof(*this)); }
void Identity() { Diagonal(NVec4(1.f, 1.f, 1.f, 1.f)); }
void Diagonal(NVec4 xyzw) {
Zeros();
r[0][0] = xyzw[0];
r[1][1] = xyzw[1];
r[2][2] = xyzw[2];
r[3][3] = xyzw[3];
}
NMat4& Get() { return *this; }
void Add(const NMat4& in) {
for (int i = 0; i < 0x10; i++) {
m[i] += in[i];
}
}
void Sub(const NMat4& in) {
for (int i = 0; i < 0x10; i++) {
m[i] -= in[i];
}
}
void Mul(const NMat4& in) {
}
void Transpose();
float Inverse();
// Operators
float operator[](int i) const { return m[i]; }
float& operator[](int i) { return m[i]; }
union {
NVec4 r[4];
float m[0x10];
};
};

View File

@ -1,366 +0,0 @@
#pragma once
#include <cmath>
struct NVec2 {
// Init Funcs
NVec2() {
v[0] = 0;
v[1] = 0;
}
NVec2(float x, float y) {
v[0] = x;
v[1] = y;
}
NVec2(const NVec2 &i) {
v[0] = i[0];
v[1] = i[1];
}
NVec2(float i) {
v[0] = i;
v[1] = i;
}
// Operations
// Add
NVec2 &operator+=(const NVec2 &i) {
v[0] += i[0];
v[1] += i[1];
return *this;
}
NVec2 &operator+=(const float &i) {
v[0] += i;
v[1] += i;
return *this;
}
NVec2 operator+(const NVec2 &i) const {
return NVec2(v[0] + i[0], v[1] + i[1]);
}
NVec2 operator+(const float &i) const { return NVec2(v[0] + i, v[1] + i); }
// Sub
NVec2 &operator-=(const NVec2 &i) {
v[0] -= i[0];
v[1] -= i[1];
return *this;
}
NVec2 &operator-=(const float &i) {
v[0] -= i;
v[1] -= i;
return *this;
}
NVec2 operator-(const NVec2 &i) const {
return NVec2(v[0] - i[0], v[1] - i[1]);
}
NVec2 operator-(const float &i) const { return NVec2(v[0] - i, v[1] - i); }
// Mul
NVec2 &operator*=(const NVec2 &i) {
v[0] *= i[0];
v[1] *= i[1];
return *this;
}
NVec2 &operator*=(const float &i) {
v[0] *= i;
v[1] *= i;
return *this;
}
NVec2 operator*(const NVec2 &i) const {
return NVec2(v[0] * i[0], v[1] * i[1]);
}
NVec2 operator*(const float &i) const { return NVec2(v[0] * i, v[1] * i); }
// Div
NVec2 &operator/=(const NVec2 &i) {
v[0] /= i[0];
v[1] /= i[1];
return *this;
}
NVec2 &operator/=(const float &i) {
v[0] /= i;
v[1] /= i;
return *this;
}
NVec2 operator/(const NVec2 &i) const {
return NVec2(v[0] / i[0], v[1] / i[1]);
}
NVec2 operator/(const float &i) const { return NVec2(v[0] / i, v[1] / i); }
// Compare
bool operator==(const NVec2 &in) const {
return v[0] == in[0] && v[1] == in[1];
}
bool operator!=(const NVec2 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
NVec2 operator-() const { return NVec2(-v[0], -v[1]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const { return v[0] * v[0] + v[1] * v[1]; }
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
// Internal Values
float v[2];
};
struct NVec3 {
// Init Funcs
NVec3() {
v[0] = 0.f;
v[1] = 0.f;
v[2] = 0.f;
}
NVec3(float x, float y, float z) {
v[0] = x;
v[1] = y;
v[2] = z;
}
NVec3(const NVec3 &i) {
v[0] = i[0];
v[1] = i[1];
v[2] = i[2];
}
NVec3(float i) {
v[0] = i;
v[1] = i;
v[2] = i;
}
// Operations
// Add
NVec3 &operator+=(const NVec3 &i) {
v[0] += i[0];
v[1] += i[1];
v[2] += i[2];
return *this;
}
NVec3 &operator+=(const float &i) {
v[0] += i;
v[1] += i;
v[2] += i;
return *this;
}
NVec3 operator+(const NVec3 &i) const {
return NVec3(v[0] + i[0], v[1] + i[1], v[2] + i[2]);
}
NVec3 operator+(const float &i) const {
return NVec3(v[0] + i, v[1] + i, v[2] + i);
}
// Sub
NVec3 &operator-=(const NVec3 &i) {
v[0] -= i[0];
v[1] -= i[1];
v[2] -= i[2];
return *this;
}
NVec3 &operator-=(const float &i) {
v[0] -= i;
v[1] -= i;
v[2] -= i;
return *this;
}
NVec3 operator-(const NVec3 &i) const {
return NVec3(v[0] - i[0], v[1] - i[1], v[2] - i[2]);
}
NVec3 operator-(const float &i) const {
return NVec3(v[0] - i, v[1] - i, v[2] - i);
}
// Mul
NVec3 &operator*=(const NVec3 &i) {
v[0] *= i[0];
v[1] *= i[1];
v[2] *= i[2];
return *this;
}
NVec3 &operator*=(const float &i) {
v[0] *= i;
v[1] *= i;
v[2] *= i;
return *this;
}
NVec3 operator*(const NVec3 &i) const {
return NVec3(v[0] * i[0], v[1] * i[1], v[2] * i[2]);
}
NVec3 operator*(const float &i) const {
return NVec3(v[0] * i, v[1] * i, v[2] * i);
}
// Div
NVec3 &operator/=(const NVec3 &i) {
v[0] /= i[0];
v[1] /= i[1];
v[2] /= i[2];
return *this;
}
NVec3 &operator/=(const float &i) {
v[0] /= i;
v[1] /= i;
v[2] /= i;
return *this;
}
NVec3 operator/(const NVec3 &i) const {
return NVec3(v[0] / i[0], v[1] / i[1], v[2] / i[2]);
}
NVec3 operator/(const float &i) const {
return NVec3(v[0] / i, v[1] / i, v[2] / i);
}
// Compare
bool operator==(const NVec3 &in) const {
return v[0] == in[0] && v[1] == in[1] && v[2] == v[2];
}
bool operator!=(const NVec3 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
// Base
NVec3 operator-() const { return NVec3(-v[0], -v[1], -v[2]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const { return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; }
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
float z() const { return v[2]; }
float &z() { return v[2]; }
float v[3];
};
struct NVec4 {
// Init Funcs
NVec4() {
v[0] = 0.f;
v[1] = 0.f;
v[2] = 0.f;
v[3] = 0.f;
}
NVec4(float x, float y, float z, float w) {
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
}
NVec4(const NVec4 &i) {
v[0] = i[0];
v[1] = i[1];
v[2] = i[2];
v[3] = i[3];
}
NVec4(const NVec2 &i0, const NVec2 &i1) {
v[0] = i0[0];
v[1] = i0[1];
v[2] = i1[0];
v[3] = i1[1];
}
NVec4(float i) {
v[0] = i;
v[1] = i;
v[2] = i;
v[3] = i;
}
// Operators
// Add
NVec4 &operator+=(const NVec4 &i) {
v[0] += i[0];
v[1] += i[1];
v[2] += i[2];
v[3] += i[3];
return *this;
}
NVec4 operator+(const NVec4 &i) const {
return NVec4(v[0] + i[0], v[1] + i[1], v[2] + i[2], v[3] + i[3]);
}
// Sub
NVec4 &operator-=(const NVec4 &i) {
v[0] -= i[0];
v[1] -= i[1];
v[2] -= i[2];
v[3] -= i[3];
return *this;
}
NVec4 operator-(const NVec4 &i) const {
return NVec4(v[0] - i[0], v[1] - i[1], v[2] - i[2], v[3] - i[3]);
}
// Compare
bool operator==(const NVec4 &in) const {
return v[0] == in[0] && v[1] == in[1] && v[2] == in[2] && v[3] == in[3];
}
bool operator!=(const NVec4 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
// Base
NVec3 operator-() const { return NVec3(-v[0], -v[1], -v[2]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const {
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
}
// Vec Acess
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
float z() const { return v[2]; }
float &z() { return v[2]; }
float w() const { return v[3]; }
float &w() { return v[3]; }
// Quaternion Acess
float r() const { return v[0]; }
float &r() { return v[0]; }
float k() const { return v[1]; }
float &k() { return v[1]; }
float j() const { return v[2]; }
float &j() { return v[2]; }
float i() const { return v[3]; }
float &i() { return v[3]; }
// Internal Values
float v[4];
};

View File

@ -0,0 +1,34 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
namespace BitUtil {
bool IsSingleBit(u32 v);
u32 GetPow2(u32 v);
} // namespace BitUtil
} // namespace PD

102
include/pd/maths/color.hpp Normal file
View File

@ -0,0 +1,102 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
/// @brief Color class (Supports hex, rgb(a)8, u32 input)
/// @note no safeteychecks used here for performance
class Color {
public:
Color() : m_r(0), m_g(0), m_b(0), m_a(0) {}
Color(u32 color) {
m_a = (color >> 24) & 0xff;
m_b = (color >> 16) & 0xff;
m_g = (color >> 8) & 0xff;
m_r = color & 0xff;
}
Color(u8 r, u8 g, u8 b, u8 a = 255) {
m_r = r;
m_g = g;
m_b = b;
m_a = a;
}
Color(float r, float g, float b, float a = 1.f) {
m_r = static_cast<u8>(255.f * r);
m_g = static_cast<u8>(255.f * g);
m_b = static_cast<u8>(255.f * b);
m_a = static_cast<u8>(255.f * a);
}
Color(const std::string& hex) { Hex(hex); }
~Color() {}
Color& Hex(const std::string& hex);
std::string Hex(bool rgba = false) const;
Color& r(u8 v) {
m_r = v;
return *this;
}
u8 r() const { return m_r; }
Color& g(u8 v) {
m_g = v;
return *this;
}
u8 g() const { return m_r; }
Color& b(u8 v) {
m_b = v;
return *this;
}
u8 b() const { return m_r; }
Color& a(u8 v) {
m_a = v;
return *this;
}
u8 a() const { return m_r; }
Color& Fade(const Color& color, float p) {
m_a = static_cast<u8>((color.a() - m_a) * ((p + 1.f) / 2));
m_b = static_cast<u8>((color.b() - m_b) * ((p + 1.f) / 2));
m_g = static_cast<u8>((color.g() - m_g) * ((p + 1.f) / 2));
m_r = static_cast<u8>((color.r() - m_r) * ((p + 1.f) / 2));
return *this;
}
u32 Get() const { return (m_a << 24) | (m_b << 16) | (m_g << 8) | m_r; }
float Luminance() const {
// For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
return (0.3 * (m_r / 255.f) + 0.59 * (m_g / 255.f) + 0.11 * (m_b / 255.f));
}
bool IsLight() const { return (Luminance() >= 0.5); }
operator u32() const { return Get(); }
private:
u8 m_r;
u8 m_g;
u8 m_b;
u8 m_a;
};
} // namespace PD

View File

@ -0,0 +1,34 @@
#pragma once
/*
MIT License
Copyright (c) 2024 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
namespace ImgConvert {
void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
const int &w, const int &h);
} // namespace ImgConvert
} // namespace PD

404
include/pd/maths/vec.hpp Normal file
View File

@ -0,0 +1,404 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* Why Creating this:
* Cause using makes coding much better structured
* and easy to use like in glsl or glm
*/
#include <pd/common/common.hpp>
namespace PD {
struct vec2 {
// Init Funcs
vec2() {
v[0] = 0;
v[1] = 0;
}
vec2(float x, float y) {
v[0] = x;
v[1] = y;
}
vec2(const vec2 &i) {
v[0] = i[0];
v[1] = i[1];
}
vec2(float i) {
v[0] = i;
v[1] = i;
}
// Operations
// Add
vec2 &operator+=(const vec2 &i) {
v[0] += i[0];
v[1] += i[1];
return *this;
}
vec2 &operator+=(const float &i) {
v[0] += i;
v[1] += i;
return *this;
}
vec2 operator+(const vec2 &i) const { return vec2(v[0] + i[0], v[1] + i[1]); }
vec2 operator+(const float &i) const { return vec2(v[0] + i, v[1] + i); }
// Sub
vec2 &operator-=(const vec2 &i) {
v[0] -= i[0];
v[1] -= i[1];
return *this;
}
vec2 &operator-=(const float &i) {
v[0] -= i;
v[1] -= i;
return *this;
}
vec2 operator-(const vec2 &i) const { return vec2(v[0] - i[0], v[1] - i[1]); }
vec2 operator-(const float &i) const { return vec2(v[0] - i, v[1] - i); }
// Mul
vec2 &operator*=(const vec2 &i) {
v[0] *= i[0];
v[1] *= i[1];
return *this;
}
vec2 &operator*=(const float &i) {
v[0] *= i;
v[1] *= i;
return *this;
}
vec2 operator*(const vec2 &i) const { return vec2(v[0] * i[0], v[1] * i[1]); }
vec2 operator*(const float &i) const { return vec2(v[0] * i, v[1] * i); }
// Div
vec2 &operator/=(const vec2 &i) {
v[0] /= i[0];
v[1] /= i[1];
return *this;
}
vec2 &operator/=(const float &i) {
v[0] /= i;
v[1] /= i;
return *this;
}
vec2 operator/(const vec2 &i) const { return vec2(v[0] / i[0], v[1] / i[1]); }
vec2 operator/(const float &i) const { return vec2(v[0] / i, v[1] / i); }
// Compare
bool operator==(const vec2 &in) const {
return v[0] == in[0] && v[1] == in[1];
}
bool operator!=(const vec2 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
vec2 operator-() const { return vec2(-v[0], -v[1]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const { return v[0] * v[0] + v[1] * v[1]; }
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
// Internal Values
float v[2];
};
struct vec3 {
// Init Funcs
vec3() {
v[0] = 0.f;
v[1] = 0.f;
v[2] = 0.f;
}
vec3(float x, float y, float z) {
v[0] = x;
v[1] = y;
v[2] = z;
}
vec3(const vec3 &i) {
v[0] = i[0];
v[1] = i[1];
v[2] = i[2];
}
vec3(float i) {
v[0] = i;
v[1] = i;
v[2] = i;
}
//// PD REWRITE ADDITIONAL CONTENT ////
vec3(const vec2 &xy, float z) {
v[0] = xy[0];
v[1] = xy[1];
v[2] = z;
}
vec3(float x, const vec2 &yz) {
v[0] = x;
v[1] = yz[0];
v[2] = yz[1];
}
// Operations
// Add
vec3 &operator+=(const vec3 &i) {
v[0] += i[0];
v[1] += i[1];
v[2] += i[2];
return *this;
}
vec3 &operator+=(const float &i) {
v[0] += i;
v[1] += i;
v[2] += i;
return *this;
}
vec3 operator+(const vec3 &i) const {
return vec3(v[0] + i[0], v[1] + i[1], v[2] + i[2]);
}
vec3 operator+(const float &i) const {
return vec3(v[0] + i, v[1] + i, v[2] + i);
}
// Sub
vec3 &operator-=(const vec3 &i) {
v[0] -= i[0];
v[1] -= i[1];
v[2] -= i[2];
return *this;
}
vec3 &operator-=(const float &i) {
v[0] -= i;
v[1] -= i;
v[2] -= i;
return *this;
}
vec3 operator-(const vec3 &i) const {
return vec3(v[0] - i[0], v[1] - i[1], v[2] - i[2]);
}
vec3 operator-(const float &i) const {
return vec3(v[0] - i, v[1] - i, v[2] - i);
}
// Mul
vec3 &operator*=(const vec3 &i) {
v[0] *= i[0];
v[1] *= i[1];
v[2] *= i[2];
return *this;
}
vec3 &operator*=(const float &i) {
v[0] *= i;
v[1] *= i;
v[2] *= i;
return *this;
}
vec3 operator*(const vec3 &i) const {
return vec3(v[0] * i[0], v[1] * i[1], v[2] * i[2]);
}
vec3 operator*(const float &i) const {
return vec3(v[0] * i, v[1] * i, v[2] * i);
}
// Div
vec3 &operator/=(const vec3 &i) {
v[0] /= i[0];
v[1] /= i[1];
v[2] /= i[2];
return *this;
}
vec3 &operator/=(const float &i) {
v[0] /= i;
v[1] /= i;
v[2] /= i;
return *this;
}
vec3 operator/(const vec3 &i) const {
return vec3(v[0] / i[0], v[1] / i[1], v[2] / i[2]);
}
vec3 operator/(const float &i) const {
return vec3(v[0] / i, v[1] / i, v[2] / i);
}
// Compare
bool operator==(const vec3 &in) const {
return v[0] == in[0] && v[1] == in[1] && v[2] == v[2];
}
bool operator!=(const vec3 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
// Base
vec3 operator-() const { return vec3(-v[0], -v[1], -v[2]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const { return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; }
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
float z() const { return v[2]; }
float &z() { return v[2]; }
//// PALLADIUM REWRITE ADDITIONAL CONTENT ////
vec2 xy() const { return vec2(v[0], v[1]); }
vec2 yz() const { return vec2(v[1], v[2]); }
float v[3];
};
struct vec4 {
// Init Funcs
vec4() {
v[0] = 0.f;
v[1] = 0.f;
v[2] = 0.f;
v[3] = 0.f;
}
vec4(float x, float y, float z, float w) {
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
}
vec4(const vec4 &i) {
v[0] = i[0];
v[1] = i[1];
v[2] = i[2];
v[3] = i[3];
}
vec4(const vec2 &i0, const vec2 &i1) {
v[0] = i0[0];
v[1] = i0[1];
v[2] = i1[0];
v[3] = i1[1];
}
vec4(float i) {
v[0] = i;
v[1] = i;
v[2] = i;
v[3] = i;
}
// Operators
// Add
vec4 &operator+=(const vec4 &i) {
v[0] += i[0];
v[1] += i[1];
v[2] += i[2];
v[3] += i[3];
return *this;
}
vec4 operator+(const vec4 &i) const {
return vec4(v[0] + i[0], v[1] + i[1], v[2] + i[2], v[3] + i[3]);
}
// Sub
vec4 &operator-=(const vec4 &i) {
v[0] -= i[0];
v[1] -= i[1];
v[2] -= i[2];
v[3] -= i[3];
return *this;
}
vec4 operator-(const vec4 &i) const {
return vec4(v[0] - i[0], v[1] - i[1], v[2] - i[2], v[3] - i[3]);
}
// Compare
bool operator==(const vec4 &in) const {
return v[0] == in[0] && v[1] == in[1] && v[2] == in[2] && v[3] == in[3];
}
bool operator!=(const vec4 &in) const {
// use the first comparefuncs result
// and swap it lol
return !(*this == in);
}
// Base
vec3 operator-() const { return vec3(-v[0], -v[1], -v[2]); }
float operator[](int i) const { return v[i]; }
float &operator[](int i) { return v[i]; }
float len() const { return sqrt(sqlen()); }
float sqlen() const {
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
}
// Vec2 Acess
float x() const { return v[0]; }
float &x() { return v[0]; }
float y() const { return v[1]; }
float &y() { return v[1]; }
float z() const { return v[2]; }
float &z() { return v[2]; }
float w() const { return v[3]; }
float &w() { return v[3]; }
// Quaternion Acess
float r() const { return v[0]; }
float &r() { return v[0]; }
float k() const { return v[1]; }
float &k() { return v[1]; }
float j() const { return v[2]; }
float &j() { return v[2]; }
float i() const { return v[3]; }
float &i() { return v[3]; }
// Internal Values
float v[4];
};
} // namespace PD

View File

@ -1,30 +0,0 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#define NPI_NIMG_ (uint32_t)0x4e494d47 // Magic: NIMG
namespace Palladium {
struct nimg {
unsigned int magic; // Magic number defaults do NPI_NIMG_
int width;
int height;
int format;
int compression;
std::vector<unsigned char> pixel_buffer;
nimg(int w = 0, int h = 0, int fmt = 0, int cmp = 0) {
magic = NPI_NIMG_;
width = w;
height = h;
format = fmt;
compression = cmp;
pixel_buffer.resize((w * h) * (format ? 3 : 4));
}
};
nimg NIMG_Load(std::string path);
nimg NIMG_LoadFromMem(unsigned char* buffer, size_t bf_size);
void NIMG_Save(nimg image, std::string path);
} // namespace Palladium

View File

@ -1,183 +0,0 @@
#pragma once
/// c++ Includes
#include <cstring>
#include <map>
#include <memory>
#include <stack>
#include <string>
/// c includes
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
/// 3ds Includes
#include <3ds.h>
#include <citro3d.h>
/// Palladium Includes
#include <pd/Hardware.hpp>
#include <pd/Overlays.hpp>
#include <pd/Ovl.hpp>
#include <pd/ResultDecoder.hpp>
#include <pd/Sprite.hpp>
#include <pd/Tasks.hpp>
#include <pd/Time.hpp>
#include <pd/base/Color.hpp>
#include <pd/base/FunctionTrace.hpp>
#include <pd/base/Lang.hpp>
#include <pd/base/Memory.hpp>
#include <pd/base/stringtool.hpp>
#include <pd/parameter.hpp>
#include <pd/thread.hpp>
#define PDVSTRING "1.0.0"
#define DEFAULT_CENTER 0.5f
/// @param pd_max_objects Config Param for C2D Mac objects
extern int pd_max_objects;
namespace Palladium {
/// @brief Get Deltatime
/// @return Deltatime
float GetDeltaTime();
/// @brief Scene Class
class Scene {
public:
/// @brief Stack of the Scenes
static std::stack<std::unique_ptr<Scene>> scenes;
/// @brief Deconstructor
virtual ~Scene() {}
virtual void Update() = 0;
/// @brief Push a Scene to Stack
/// @param scene Scene to Push
/// @param fade FadeEffect (Not Correctly Implementet yet)
static void Load(std::unique_ptr<Scene> scene, bool fade = false);
/// @brief Go Back a Scene
static void Back();
/// @brief do the Draw (Called in Palladium::MainLoop())
static void doUpdate();
};
/// @brief Integrated Setting Menu of Palladium
class RSettings : public Palladium::Scene {
private:
/// @brief State (Define for Menus)
enum RState {
RSETTINGS, // Main Settings Menu
RIDB, // Internal Debugger
ROVERLAYS, // Overlay Settings
RFTRACE, // FTRace Menu
RUI7, // UI7 Menu
RLOGS, // Logs
RFV, // Font Viewer
};
/// @param shared_request Defines requests from Draw to Logic
/// As it is not planned to make Draw non const you'll need
/// A map of data or bool values that are mutable ake
/// editable by const functions
mutable std::map<unsigned int, unsigned int> shared_request;
/// @param m_state Current menu State (Default=MainMenu aka RSETTINGS)
Palladium::RSettings::RState m_state =
Palladium::RSettings::RState::RSETTINGS;
/// @brief Position in FTrace Menu
int ftrace_index = 0;
/// @param mtovlstate State of Metricks Overlay
std::string mtovlstate = "false";
/// @param mtscreenstate Screen the Overlay is Set to
std::string mtscreenstate = "Top";
std::string kbd_test;
PDKeyboardState kbd_state;
bool statemtold = false;
bool stateftold = false;
float tmp_txt;
public:
/// @brief Constructor
RSettings();
/// @brief Deconstructor
~RSettings();
void Update() override;
};
/// @brief Show Up the Palladium-Settings Menu
void LoadSettings();
/// @brief Show Up The Theme Editor
void LoadThemeEditor();
/// @brief Get's The Programs Time running
/// @return Time Running
float GetTime();
/// @brief Get Framerate as Number
/// @return FPS
int GetFps();
/// @brief Get A Rendom Int
/// @param b From
/// @param e To
/// @return Random Int
int GetRandomInt(int b, int e);
/// @brief Fade In
/// @param duration Duration in Frames
void FadeIn();
/// @brief Fade Out
/// @param duration Duration in Frames
void FadeOut();
/// @brief Display Fade Effects
void FadeDisplay();
namespace Init {
/// @brief Init Default Palladium
/// @param app_name Name of Your App
/// @return ResCode
Result Main(std::string app_name = "pdGame");
/// @brief Init Minimal Palladium (For better Hax2.x support)
/// @param app_name Name of Your App
/// @return ResCode
Result Minimal(std::string app_name = "pdGame");
/// @brief Reload the Graphics Engine
/// @return ResCode
Result Reload();
/// @brief Init Graphics Only (NOT SUPPORTET use Reload)
void Graphics();
/// @brief Init Ndsp for Sounds
void NdspFirm();
} // namespace Init
namespace FS {
/// @brief Check if File exists
/// @param path Path to the File
/// @return exists or not
bool FileExist(const std::string &path);
} // namespace FS
/// @brief Check if Ndsp is Init
/// @return is or not
bool IsNdspInit();
/// @brief Get Current Framerate as String
/// @return Framerate String
std::string GetFramerate();
/// @brief MainLoop of Palladiums
/// @return Is Still Running or not
bool MainLoop();
/// @brief Exit App (brak the MainLoop)
void ExitApp();
/// @brief Clear the Citro2D TextBuffers
/// @param
void ClearTextBufs(void);
/// @brief Draw Overlays And end the Frame. DO NEVER USE C3D_FRAMEEND cause it
/// breaks Overlay crash Security
void FrameEnd();
/// @brief Returns App Working Directory path
/// @return AppDir Path
std::string GetAppDirectory();
/// @brief returns path to the Data Directory
/// @return data dir path
std::string GetDataDirectory();
} // namespace Palladium

View File

@ -1,134 +0,0 @@
#pragma once
#include <tuple>
namespace Palladium {
class Parameter {
private:
using id = size_t;
template <typename T>
struct type {
static void id() {}
};
template <typename T>
static id type_id() {
return reinterpret_cast<id>(&type<T>::id);
}
template <typename T>
using decay = typename std::decay<T>::type;
template <typename T>
using none =
typename std::enable_if<!std::is_same<Parameter, T>::value>::type;
struct base {
virtual ~base() {}
virtual bool is(id) const = 0;
virtual base *copy() const = 0;
} *p = nullptr;
template <typename T>
struct data : base, std::tuple<T> {
using std::tuple<T>::tuple;
T &get() & { return std::get<0>(*this); }
T const &get() const & { return std::get<0>(*this); }
bool is(id i) const override { return i == type_id<T>(); }
base *copy() const override { return new data{get()}; }
};
template <typename T>
T &stat() {
return static_cast<data<T> &>(*p).get();
}
template <typename T>
T const &stat() const {
return static_cast<data<T> const &>(*p).get();
}
template <typename T>
T &dyn() {
return dynamic_cast<data<T> &>(*p).get();
}
template <typename T>
T const &dyn() const {
return dynamic_cast<data<T> const &>(*p).get();
}
public:
/**
* @brief Default constructor
*/
Parameter() {}
/**
* @brief Destructs the Parameter
*/
~Parameter() { delete p; }
/**
* @brief Copy constructor
* @param s The Parameter to copy
*/
Parameter(Parameter &&s) : p{s.p} { s.p = nullptr; }
/**
* @brief Const copy constructor
* @param s The Parameter to copy
*/
Parameter(Parameter const &s) : p{s.p->copy()} {}
/**
* @brief Initializes the Parameter with the given value
* @param x The value to initialize the Parameter with
*/
template <typename T, typename U = decay<T>, typename = none<U>>
Parameter(T &&x) : p{new data<U>{std::forward<T>(x)}} {}
/**
* @brief Overloads the assignment operator
* @param s The value to set the Parameter to
*/
Parameter &operator=(Parameter s) {
swap(*this, s);
return *this;
}
friend void swap(Parameter &s, Parameter &r) { std::swap(s.p, r.p); }
/**
* @brief Clears the Parameter
*/
void clear() {
delete p;
p = nullptr;
}
/**
* @brief Checks whether the Parameter is the given type
* @tparam T The type to check
* @return Whether the Parameter has the given type or not
*/
template <typename T>
bool is() const {
return p ? p->is(type_id<T>()) : false;
}
/**
* @brief Returns the value of the Parameter
* @tparam T The type of the Parameter
* @return The value of the Parameter
* @warning If the type of the Parameter doesn't match the type of it's stored
* value, it will result in undefined behaviour.
*/
template <typename T>
T &get() & {
return stat<T>();
}
};
} // namespace Palladium

View File

@ -1,10 +0,0 @@
#pragma once
#include <memory>
#define PD_SMART_CTOR(type) \
using Ref = std::shared_ptr<type>; \
template <typename... args> \
static Ref New(args&&... cargs) { \
return std::make_shared<type>(std::forward<args>(cargs)...); \
}

View File

@ -0,0 +1,46 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <3ds.h>
#include <pd/common/common.hpp>
#include <pd/common/memory.hpp>
namespace PD {
class Sound : public SmartCtor<Sound> {
public:
Sound();
~Sound();
void Play();
void Stop();
private:
u32 dataSize;
ndspWaveBuf wavBuf;
std::vector<u8, LinearAllocator<u8>> dat;
int channel;
};
} // namespace PD

View File

@ -1,122 +0,0 @@
#pragma once
#include <3ds.h>
#include <atomic>
#include <functional>
#include <pd/parameter.hpp>
using CTRU_Thread = Thread;
#define THREAD_STACK_SIZE 0x1000
namespace Palladium {
class Thread {
public:
/**
* @brief Default constructor
* @note This should only be called when calling m3d::Thread::initialize()
* before calling m3d::Thread::start()
*/
Thread();
/**
* @brief Constructs the thread
* @param t_function The thread function
* @param t_parameter The parameter to pass to the function
* @param t_autostart Whether the thread should start instantly
* @param t_detached Whether the thread starts detached or not
* @param t_stackSize The stacksize allocated for the thread in bytes (rounded
* to multiples of 8 bytes)
* @note t_function needs to be of type `void` and take one (and only one)
* parameter of type m3d::Parameter
* @warning If the thread priority is lower than the priority of the calling
* thread, the thread will never get executed. Use
* m3d::Thread::getCurrentPriority() to get the priority of the current thread
*/
Thread(std::function<void(Palladium::Parameter)> t_function,
Palladium::Parameter t_parameter = nullptr, bool t_autostart = false,
bool t_detached = false,
unsigned long long int t_stackSize = 4 * 1024);
/**
* @brief Destructs the thread
*/
virtual ~Thread();
/**
* @brief Initializes the thread
* @param t_function The thread function
* @param t_parameter The parameter to pass to the function
* @param t_autostart Whether the thread should start instantly
* @param t_detached Whether the thread starts detached or not
* @param t_stackSize The stacksize allocated for the thread in bytes (rounded
* to multiples of 8 bytes)
* @note t_function needs to be of type `void` and take one (and only one)
* parameter of type m3d::Parameter
* @warning If the thread priority is lower than the priority of the calling
* thread, the thread will never get executed. Use
* m3d::Thread::getCurrentPriority() to get the priority of the current thread
*/
void initialize(std::function<void(Palladium::Parameter)> t_function,
Palladium::Parameter t_parameter = nullptr,
bool t_autostart = false, bool t_detached = false,
unsigned long long int t_stackSize = 4 * 1024);
/**
* @brief Sets the size of the stack that gets allocated for the next thread
* that get's started
* @param t_stackSize The allocated space in bytes (rounded to multiples of 8
* bytes)
*/
void setStackSize(unsigned long long int t_stackSize);
/**
* @brief Starts the thread. To restart it, call Thread::join() before
* @param t_detached Whether the thread should start detached or not
*/
void start(bool t_detached = false);
/**
* @brief Detaches the thread
*/
void kill();
/**
* @brief Waits for the thread to finish
* @param t_timeout The timeout in nanoseconds. Leave it for no timeout
*/
void join(long long unsigned int t_timeout = U64_MAX);
bool isRunning();
/**
* @brief Puts the thread to sleep
*
* This is needed if you have multiple threads running at the same time. It
* doesn't affect the execution-time of the thread, it just makes it possible
* for the other threads to get their chance to shine.
*/
static void sleep();
/**
* @brief Sleeps for the given time
* @param t_milliseconds The time to sleep in milliseconds
*/
static void sleep(int t_milliseconds);
private:
struct ThreadData {
Palladium::Parameter m_parameter;
std::function<void(Palladium::Parameter)> m_function;
std::atomic<bool> *m_running;
};
static void threadFunction(void *t_arg);
/* data */
int m_priority, m_stackSize;
bool m_started;
std::atomic<bool> m_running;
Palladium::Thread::ThreadData m_data;
CTRU_Thread m_thread;
};
} // namespace Palladium

View File

@ -0,0 +1,103 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
namespace PD {
class Markdown {
public:
Markdown() = default;
~Markdown() = default;
void Header(const std::string& hdr, int lvl = 2) {
if (task != 0 || lvl < 1 || lvl > 10) {
return;
}
/// Directly create the string with its amount of #
std::string str(lvl, '#');
str += " ";
str += hdr;
s << str << std::endl << std::endl;
}
void BeginTable(const std::vector<std::string>& head) {
if (task != 0) {
return;
}
ctc = head.size();
for (auto& it : head) {
s << "| " << it << " ";
}
s << "|\n";
for (int i = 0; i < ctc; i++) {
s << "|---";
}
s << "|\n";
task = 1;
}
Markdown& TableAddEntry(const std::string& e) {
if (task != 1) {
return *this;
}
ctci++;
s << "| " << e << " ";
if (ctci == ctc) {
s << "|\n";
ctci = 0;
}
return *this;
}
void EndTable() {
if (task != 1) {
return;
}
s << std::endl;
task = 0;
}
void Write(const std::string& path) {
std::ofstream f(path);
if (!f) {
return;
}
f << s.str();
f.close();
}
private:
/// @brief Tasks
/// 0 = free
/// 1 = table
/// 2 = text
int task = 0;
/// @brief Current Table Columns
int ctc = 0;
/// @brief Current Table Column Index
int ctci = 0;
std::stringstream s;
};
} // namespace PD

View File

@ -0,0 +1,37 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <3ds.h>
#include <pd/common/common.hpp>
#include <pd/tools/markdown.hpp>
namespace PD {
class ResultDecoder {
public:
ResultDecoder(Result res);
};
} // namespace PD

View File

@ -0,0 +1,53 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
#include <pd/graphics/lithium.hpp>
#include <pd/ui7/theme.hpp>
namespace PD {
class UI7DrawList : SmartCtor<UI7DrawList> {
public:
UI7DrawList(LI::Renderer::Ref r) { ren = r; }
~UI7DrawList() = default;
void AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr);
void AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2, const UI7Color& clr);
void AddText(vec2 pos, const std::string& text, const UI7Color& clr,
LITextFlags flags = 0, vec2 box = vec2());
void AddImage(vec2 pos, Texture::Ref img);
void Clear();
void Process();
int Layer() const { return layer; }
void Layer(int v) { layer = v; }
private:
int layer;
LI::Renderer::Ref ren;
std::vector<LI::Command::Ref> commands;
};
} // namespace PD

35
include/pd/ui7/flags.hpp Normal file
View File

@ -0,0 +1,35 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using UI7MenuFlags = unsigned int;
enum UI7MenuFlags_ {
UI7MenuFlags_None = 0,
UI7MenuFlags_NoTitlebar = 1 << 0,
UI7MenuFlags_CenterTitle = 1 << 1,
UI7MenuFlags_HzScrolling = 1 << 2,
UI7MenuFlags_VtScrolling = 1 << 3,
UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling,
};

52
include/pd/ui7/theme.hpp Normal file
View File

@ -0,0 +1,52 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/common/common.hpp>
using UI7Color = unsigned int;
enum UI7Color_ {
UI7Color_Background,
};
namespace PD {
/// Using UI7Color as a Class to be able to
/// define it as struct as well as using it as enum
class UI7Color {
public:
UI7Color() {
/// No Color
}
UI7Color(unsigned int c) { color = c; }
UI7Color(UI7Color_ c) {}
~UI7Color() {}
operator u32() const { return color; }
private:
u32 color;
};
} // namespace PD

53
include/pd/ui7/ui7.hpp Normal file
View File

@ -0,0 +1,53 @@
#pragma once
/*
MIT License
Copyright (c) 2024 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pd/ui7/drawlist.hpp>
#include <pd/ui7/flags.hpp>
#include <pd/ui7/theme.hpp>
namespace PD {
class UI7Context : SmartCtor<UI7Context> {
public:
UI7Context() {}
~UI7Context() {}
private:
// Timing
float delta;
float time;
float last;
// Context
bool in_menu;
// Debug
bool debug;
// Menu Handlers
// Context DrawList
UI7DrawList::Ref debug;
UI7DrawList::Ref front;
UI7DrawList::Ref back;
// Promt Handler
};
} // namespace PD

View File

@ -1,44 +0,0 @@
site_name: RenderD7 Docs
site_description:
theme:
name: material
custom_dir: docs/overrides
features:
- navigation.indexes
palette:
# Palette toggle for light mode
- scheme: default
primary: red
accent: red
toggle:
icon: material/brightness-7
name: Switch to dark mode
# Palette toggle for dark mode
- scheme: slate
primary: red
accent: red
toggle:
icon: material/brightness-4
name: Switch to light mode
markdown_extensions:
- def_list
- attr_list
- admonition
- pymdownx.details
- pymdownx.superfences
- pymdownx.arithmatex:
generic: true
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
plugins:
- search
extra_css:
- stylesheets/doxide.css
extra_javascript:
- javascripts/mathjax.js
- https://polyfill.io/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

View File

@ -1,59 +0,0 @@
#include <3ds.h>
#include <fstream>
#include <pd/Error.hpp>
#include <pd/UI7.hpp>
#include <pd/internal_db.hpp>
#include <pd/palladium.hpp>
void pdi_save_report(const std::string& msg) {
auto ts = Palladium::GetTimeStr();
std::ofstream f("sdmc:/Palladium/Reports/report_" + ts + ".txt");
f << "Palladium Error [" << pdi_app_name << ", " << ts << "]" << std::endl;
f << "Error Message: " << std::endl;
f << msg << std::endl;
f << "SysInfo: " << std::endl;
f << "- Citra -> " << (pdi_is_citra ? "true" : "false") << std::endl;
f.close();
}
namespace Palladium {
void Error(const std::string& msg) {
pdi_save_report(msg);
if (pdi_graphics_on) {
while (aptMainLoop()) {
hidScanInput();
if (hidKeysDown() & KEY_START) break;
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_RenderTargetClear(pd_top, C3D_CLEAR_ALL, 0x00000000, 0);
C3D_RenderTargetClear(pd_top_right, C3D_CLEAR_ALL, 0x00000000, 0);
C3D_RenderTargetClear(pd_bottom, C3D_CLEAR_ALL, 0x00000000, 0);
Palladium::LI::OnScreen(false);
if (UI7::BeginMenu("Palladium - Error Manager", NVec2(),
UI7MenuFlags_TitleMid)) {
UI7::Label(msg);
UI7::Label("Press Start to Exit!");
UI7::EndMenu();
}
Palladium::LI::OnScreen(true);
UI7::Update();
Palladium::LI::Render(pd_top, pd_bottom);
C3D_FrameEnd(0);
}
exit(0);
} else {
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
printf("Palladium - ERROR MANAGER\n\n%s\n", msg.c_str());
printf("Report Saved in\nsdmc:/Palladium/Reports\n");
printf("Press Start to Exit\n");
while (aptMainLoop()) {
hidScanInput();
if (hidKeysDown() & KEY_START) break;
gfxSwapBuffers();
}
gfxExit();
exit(0);
}
}
} // namespace Palladium

View File

@ -1,47 +0,0 @@
#include <pd/Hardware.hpp>
#include <pd/internal_db.hpp>
// Os Specific includes
#include <3ds.h>
void Palladium::Hardware::Initialisize() {
mcuHwcInit();
atexit(mcuHwcExit);
ptmuInit();
atexit(ptmuExit);
}
bool Palladium::Hardware::IsHeadphones() {
if (pdi_is_ndsp) {
bool inserted;
DSP_GetHeadphoneStatus(&inserted);
return inserted;
} else
return false;
}
bool Palladium::Hardware::IsCharging() {
uint8_t var;
PTMU_GetBatteryChargeState(&var);
// Some Security Stuff
if (var < 0x00 && var > 0x01) {
return false;
}
return (var == 0x01 ? true : false);
}
int Palladium::Hardware::GetBatteryPercentage() {
uint8_t percentLevel = 0;
MCUHWC_GetBatteryLevel(&percentLevel);
return percentLevel;
}
float Palladium::Hardware::Get3dSliderLevel() { return osGet3DSliderState(); }
float Palladium::Hardware::GetSoundSliderLevel() {
uint8_t percentLevel;
MCUHWC_GetSoundSliderLevel(&percentLevel);
return (float)percentLevel / 100;
}
int Palladium::Hardware::GetWifiLevel() { return osGetWifiStrength(); }

View File

@ -1,118 +0,0 @@
#include <map>
#include <pd/Hid.hpp>
namespace Palladium {
class HidApi {
public:
HidApi() {}
~HidApi() {}
void setKdown(uint32_t &in) { actions[Hid::Down] = &in; }
void setKheld(uint32_t &in) { actions[Hid::Held] = &in; }
void setKup(uint32_t &in) { actions[Hid::Up] = &in; }
void setKrepeat(uint32_t &in) { actions[Hid::DownRepeat] = &in; }
void setTouchCoords(NVec2 &touch_coords) { touch_pos = &touch_coords; }
void setJS1Movement(NVec2 &mvmt) { js1_mv = &mvmt; }
void setJS2Movement(NVec2 &mvmt) { js2_mv = &mvmt; }
void bindKey(const std::string &event, uint32_t key) {
key_bindings[event] = key; // Overrides if existing
}
void lock(bool lock) { locked = lock; }
void clear() {
// Clears Functionality for 1 Frame
last_touch_pos = NVec2();
touch_pos[0] = NVec2();
dtp = NVec2();
backups[Hid::Down] = 0;
backups[Hid::Held] = 0;
backups[Hid::Up] = 0;
backups[Hid::DownRepeat] = 0;
}
bool isEvent(const std::string &event, Hid::Actions action) {
if (locked) return false;
if (key_bindings.find(event) == key_bindings.end())
return false; // Unknown Event
if (backups.find(action) == backups.end())
return false; // What? NOT Alowed acrion
if (backups[action] & key_bindings[event])
return true; // Action contains key as flag
return false; // Nothing to do
}
NVec2 getTouchPos() { return touch_pos[0]; }
NVec2 getLastTouchPos() { return last_touch_pos; }
NVec2 getTouchDownPos() { return dtp; }
void update() {
last_touch_pos = touch_pos[0];
if (isEvent("touch", Hid::Down)) {
dtp = touch_pos[0];
}
if (isEvent("touch", Hid::Up)) {
dtp = NVec2();
}
for (const auto &it : actions) {
backups[it.first] = it.second[0];
}
if (locked) {
actions[Hid::Down][0] = 0;
actions[Hid::Held][0] = 0;
actions[Hid::Up][0] = 0;
actions[Hid::DownRepeat][0] = 0;
}
}
private:
std::map<Hid::Actions, uint32_t *> actions;
std::map<Hid::Actions, uint32_t> backups;
NVec2 *touch_pos = nullptr;
NVec2 *js1_mv = nullptr;
NVec2 *js2_mv = nullptr;
NVec2 last_touch_pos;
NVec2 dtp;
std::map<std::string, uint32_t> key_bindings;
bool locked = false;
};
static HidApi hid_handler;
namespace Hid {
// Register Functions
// Register Current state values
void RegKeyDown(uint32_t &key_down) { hid_handler.setKdown(key_down); }
void RegKeyHeld(uint32_t &key_held) { hid_handler.setKheld(key_held); }
void RegKeyUp(uint32_t &key_up) { hid_handler.setKup(key_up); }
void RegKeyRepeat(uint32_t &repeat) { hid_handler.setKrepeat(repeat); }
void RegTouchCoords(NVec2 &touch_pos) { hid_handler.setTouchCoords(touch_pos); }
void RegAnalog1Movement(NVec2 &movement) {
hid_handler.setJS1Movement(movement);
}
void RegAnalog2Movement(NVec2 &movement) {
hid_handler.setJS2Movement(movement);
}
// Register Keys
void RegKeyEvent(const std::string &event, uint32_t key) {
hid_handler.bindKey(event, key);
}
bool IsEvent(const std::string &event, Actions action) {
return hid_handler.isEvent(event, action);
}
NVec2 GetTouchPosition() { return hid_handler.getTouchPos(); }
NVec2 GetLastTouchPosition() { return hid_handler.getLastTouchPos(); }
NVec2 GetTouchDownPosition() { return hid_handler.getTouchDownPos(); }
void Update() { hid_handler.update(); }
void Lock() { hid_handler.lock(true); }
void Unlock() { hid_handler.lock(false); }
void Clear() { hid_handler.clear(); }
} // namespace Hid
} // namespace Palladium

View File

@ -1,44 +0,0 @@
#include <pd/external/stb_image.h>
#include <pd/Image.hpp>
#include <pd/internal_db.hpp>
#include <vector>
namespace Palladium {
void Image::Load(const std::string &path) {
// Make sure to cleanup
Delete();
if (!img) img = Texture::New();
img->LoadFile(path);
}
void Image::From_NIMG(const nimg &image) {
// Make sure to cleanup
Delete();
if (!img) img = Texture::New();
img->LoadPixels(image.pixel_buffer, image.width, image.height);
}
Texture::Ref Image::Get() {
if (!Loadet()) {
return nullptr;
}
return img;
}
void Image::Set(Texture::Ref i, NVec4 uvs) {
Delete();
if (uvs.x() != -1) custom_uvs = uvs;
img = i;
}
NVec2 Image::GetSize() {
if (!img) return NVec2(0, 0);
return img->GetSize();
}
void Image::Delete() { img = nullptr; }
bool Image::Loadet() { return img != nullptr; }
} // namespace Palladium

View File

@ -1,149 +0,0 @@
#include <3ds.h>
#include <pd/Installer.hpp>
#include <pd/internal_db.hpp>
namespace Palladium {
Result DeletePrevious(u64 id, FS_MediaType mt) {
if (!pdi_is_am_init) return -1;
u32 num_titles = 0;
Result ret = AM_GetTitleCount(mt, &num_titles);
if (R_FAILED(ret)) {
return ret;
}
u32 read_titles = 0;
auto ids = new u64[num_titles];
ret = AM_GetTitleList(&read_titles, mt, num_titles, ids);
if (R_FAILED(ret)) {
delete[] ids;
return ret;
}
for (u32 i = 0; i < read_titles; i++) {
if (ids[i] == id) {
ret = AM_DeleteAppTitle(mt, id);
break;
}
}
delete[] ids;
if (R_FAILED(ret)) {
return ret;
}
return 0;
}
FS_MediaType GetTitleDest(u64 id) {
u16 platform = (u16)((id >> 48) & 0xFFFF);
u16 category = (u16)((id >> 32) & 0xFFFF);
u8 variation = (u8)(id & 0xFF);
/* DSiWare 3DS DSiWare, System, DLP
* Application System Title */
return platform == 0x0003 || (platform == 0x0004 &&
((category & 0x8011) != 0 ||
(category == 0x0000 && variation == 0x02)))
? MEDIATYPE_NAND
: MEDIATYPE_SD;
}
InstallerInfo pdi_installer_info;
InstallerInfo InstallGetInfo() { return pdi_installer_info; }
void InstallSetBuffersSize(unsigned int bytes) {
if (pdi_installer_info.active) return;
if (bytes == 0) return;
if (bytes >= 0x200000) bytes = 0x200000;
pdi_installer_info.mem_size = bytes;
}
Result InstallCia(const std::string& path, bool self) {
if (!pdi_is_am_init) return -1;
if (pdi_installer_info.active) return -1;
u32 bytes_read = 0;
u32 bytes_written = 0;
pdi_installer_info.current = 0;
// Set 1 to avoid div0 error
pdi_installer_info.total = 1;
u64 size = 0;
Handle cia, file;
AM_TitleEntry info;
Result ret = 0;
FS_MediaType media = MEDIATYPE_SD;
std::string pth;
if (path[0] == '/') {
pth = path;
} else if (path.substr(0, 5) == "sdmc:") {
pth = path.substr(5);
} else {
return -1;
}
ret = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""),
fsMakePath(PATH_ASCII, pth.c_str()),
FS_OPEN_READ, 0);
if (R_FAILED(ret)) {
return ret;
}
ret = AM_GetCiaFileInfo(media, &info, file);
if (R_FAILED(ret)) {
return ret;
}
media = GetTitleDest(info.titleID);
if (!self) {
ret = DeletePrevious(info.titleID, media);
if (R_FAILED(ret)) return ret;
}
ret = FSFILE_GetSize(file, &size);
if (R_FAILED(ret)) {
return ret;
}
ret = AM_StartCiaInstall(media, &cia);
if (R_FAILED(ret)) {
return ret;
}
std::vector<unsigned char> buf(pdi_installer_info.mem_size);
pdi_installer_info.total = size;
do {
FSFILE_Read(file, &bytes_read, pdi_installer_info.current, &buf[0],
buf.size());
FSFILE_Write(cia, &bytes_written, pdi_installer_info.current, &buf[0],
buf.size(), FS_WRITE_FLUSH);
pdi_installer_info.current += bytes_read;
} while (pdi_installer_info.current < pdi_installer_info.total);
ret = AM_FinishCiaInstall(cia);
if (R_FAILED(ret)) {
return ret;
}
ret = FSFILE_Close(file);
if (R_FAILED(ret)) {
return ret;
}
if (self) {
aptSetChainloaderToSelf();
}
return 0;
}
} // namespace Palladium

View File

@ -1,789 +0,0 @@
#include <pd/external/stb_truetype.h>
#include <algorithm>
#include <cmath>
#include <codecvt>
#include <filesystem>
#include <fstream>
#include <pd/Lithium.hpp>
#include <pd/base/Color.hpp>
#include <pd/li7_shader.hpp>
#include <pd/palladium.hpp>
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
std::wstring make_wstring(const std::string& str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
return converter.from_bytes(str);
}
namespace Palladium {
PDLithiumFlags LI::flags = PDLithiumFlags_Default;
const float LI::default_font_size = 24.f;
const float LI::default_text_size = 0.7f;
float LI::text_scale = 0.7f;
// Renderer Stuff
bool LI::bottom_screen = false;
NVec2 LI::screen_size;
int LI::layer = 0;
std::vector<LI::Cmd> LI::draw_lists[2];
Texture::Ref LI::active_texture;
Texture::Ref LI::single_color;
std::vector<LI::Vtx, LinearAllocator<LI::Vtx>> LI::vertex_buffer;
std::vector<unsigned short, LinearAllocator<unsigned short>> LI::idx_buffer;
size_t LI::vertex_index = 0;
size_t LI::idx_index = 0;
bool LI::font_update = false;
LIFont::Ref LI::font;
bool LI::sysfont_render = false;
std::map<std::string, LI::TextBox> LI::text_sizes;
int LI::cmd_index = 0;
// Debug
int LI::num_vertices = 0;
int LI::num_drawcalls = 0;
int LI::num_commands = 0;
int LI::num_indices = 0;
// Shader
DVLB_s* LI::li7_dvlb;
shaderProgram_s LI::li7_prog;
C3D_AttrInfo LI::li7_attr;
int LI::uLoc_proj;
void LIFont::LoadTFF(const std::string path, int px_size) {
sysfnt = false;
Palladium::Ftrace::ScopedTrace st(
"LIFont", std::filesystem::path(path).filename().string());
this->pixel_height = px_size;
if (!Palladium::FS::FileExist(path)) return;
int type = px_size * 16;
// Load TTF
stbtt_fontinfo inf;
std::ifstream loader(path, std::ios::binary);
if (!loader.is_open()) return;
loader.seekg(0, std::ios::end);
size_t len = loader.tellg();
loader.seekg(0, std::ios::beg);
unsigned char* buffer = new unsigned char[len];
loader.read(reinterpret_cast<char*>(buffer), len);
loader.close();
stbtt_InitFont(&inf, buffer, 0);
std::vector<unsigned char> fmap(type * type * 4);
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
int ascent, descent, lineGap;
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
int baseline = static_cast<int>(ascent * scale);
name = path;
auto ftex = Texture::New();
NVec2 offset;
for (int c = 0; c < 255; c++) {
CPI codepoint;
if (stbtt_IsGlyphEmpty(&inf, c)) {
codepoint.codepoint = c;
codepoint.tex = ftex;
codepoint.invalid = true;
cpmap[c] = codepoint;
continue;
}
int width, height, xOffset, yOffset;
unsigned char* bitmap = stbtt_GetCodepointBitmap(
&inf, scale, scale, c, &width, &height, &xOffset, &yOffset);
int x0, y0, x1, y1;
stbtt_GetCodepointBitmapBox(&inf, c, scale, scale, &x0, &y0, &x1, &y1);
if (offset[0] + width > type) {
offset[1] += pixel_height;
offset[0] = 0;
}
codepoint.uv[0] = static_cast<float>((float)offset[0] / (float)type);
codepoint.uv[1] = 1.0f - static_cast<float>((float)offset[1] / (float)type);
codepoint.uv[2] =
static_cast<float>(float(offset[0] + width) / (float)type);
codepoint.uv[3] =
1.0f - static_cast<float>(float(offset[1] + height) / (float)type);
codepoint.tex = ftex;
codepoint.szs[0] = width;
codepoint.szs[1] = height;
codepoint.off = baseline + yOffset;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int map_pos = ((offset[1] + y) * type + (offset[0] + x)) * 4;
fmap[map_pos + 0] = 255;
fmap[map_pos + 1] = 255;
fmap[map_pos + 2] = 255;
fmap[map_pos + 3] = bitmap[x + y * width];
}
}
offset[0] += width;
if (offset[0] + width > type) {
offset[1] += pixel_height;
offset[0] = 0;
}
free(bitmap);
cpmap[c] = codepoint;
}
ftex->LoadPixels(fmap, type, type, Palladium::Texture::RGBA32,
Palladium::Texture::LINEAR);
this->tex.push_back(ftex);
}
void LIFont::LoadBitmapFont(const std::string& path) {}
void LIFont::LoadSystemFont() {
Palladium::Ftrace::ScopedTrace st("li", "sysfnt");
sysfnt = true;
name = "System Font";
// Code to Load the System Font
const auto fnt = fontGetSystemFont();
const auto fnt_info = fontGetInfo(fnt);
const auto glyph_info = fontGetGlyphInfo(fnt);
this->tex.resize(glyph_info->nSheets + 1);
pixel_height = glyph_info->cellHeight;
for (size_t i = 0; i < glyph_info->nSheets; i++) {
auto stex = Texture::New();
auto tx = new C3D_Tex;
tx->data = fontGetGlyphSheetTex(fnt, i);
tx->fmt = (GPU_TEXCOLOR)glyph_info->sheetFmt;
tx->size = glyph_info->sheetSize;
tx->width = glyph_info->sheetWidth;
tx->height = glyph_info->sheetHeight;
tx->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) |
GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT);
tx->border = 0xffffffff;
tx->lodParam = 0;
stex->ExternalLoad(tx, NVec2(tx->width, tx->height), NVec4(0, 1, 1, 0));
tex[i] = stex;
}
std::vector<unsigned int> charSet;
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
if (cmap->codeEnd >= cmap->codeBegin) {
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
if (cmap->indexOffset + (i - cmap->codeBegin) == 0xFFFF) break;
charSet.emplace_back(i);
}
}
} else if (cmap->mappingMethod == CMAP_TYPE_TABLE) {
if (cmap->codeEnd >= cmap->codeBegin) {
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
if (cmap->indexTable[i - cmap->codeBegin] == 0xFFFF) continue;
charSet.emplace_back(i);
}
}
} else if (cmap->mappingMethod == CMAP_TYPE_SCAN) {
charSet.reserve(charSet.size() + cmap->nScanEntries);
for (unsigned i = 0; i < cmap->nScanEntries; ++i) {
if (cmap->scanEntries[i].code >= cmap->codeBegin &&
cmap->scanEntries[i].code <= cmap->codeEnd) {
if (cmap->scanEntries[i].glyphIndex != 0xFFFF) {
charSet.emplace_back(cmap->scanEntries[i].code);
}
}
}
} else {
continue;
}
}
std::sort(charSet.begin(), charSet.end());
charSet.erase(std::unique(charSet.begin(), charSet.end()));
for (auto cp : charSet) {
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
if (gidx >= 0xFFFF) continue;
CPI codepoint;
fontGlyphPos_s dat;
fontCalcGlyphPos(&dat, fnt, gidx, GLYPH_POS_CALC_VTXCOORD, 1.f, 1.f);
codepoint.codepoint = cp;
codepoint.uv[0] = dat.texcoord.left;
codepoint.uv[1] = dat.texcoord.top;
codepoint.uv[2] = dat.texcoord.right;
codepoint.uv[3] = dat.texcoord.bottom;
if (tex.at(dat.sheetIndex) != nullptr) codepoint.tex = tex[dat.sheetIndex];
codepoint.szs[0] = dat.vtxcoord.right;
codepoint.szs[1] = dat.vtxcoord.bottom;
codepoint.off = 0;
cpmap[cp] = codepoint;
}
}
int LIFont::GetPixelHeight() { return this->pixel_height; }
LIFont::CPI LIFont::GetCodepoint(unsigned int c) {
auto res = cpmap.find(c);
if (res == cpmap.end()) return CPI(true);
return res->second;
}
void LIFont::Dump() {
// std::ofstream ofs("sdmc:/font.txt", std::ios::out);
// ofs << "LI7 Font Dump" << std::endl;
// ofs << "Pixel Height: " << (int)pixel_height << std::endl;
// for (auto& it : this->cpmap) {
// ofs << " Codepoint: " << (int)it.codepoint << std::endl;
// ofs << " Tex: " << (unsigned int)it.tex->Get() << std::endl;
// ofs << " Szs: (" << (int)it.szs[0] << ", " << (int)it.szs[1] << ")"
// << std::endl;
// ofs << " UV: (" << (float)it.uv[0] << ", " << (float)it.uv[1] << ", "
// << (float)it.uv[2] << ", " << (float)it.uv[3] << ")" << std::endl;
// }
// ofs.close();
}
void LI::Init() {
vertex_buffer.resize(4 * 4096);
idx_buffer.resize(6 * 4096);
li7_dvlb = DVLB_ParseFile((u32*)li7_shader, li7_shader_size);
shaderProgramInit(&li7_prog);
shaderProgramSetVsh(&li7_prog, &li7_dvlb->DVLE[0]);
uLoc_proj =
shaderInstanceGetUniformLocation(li7_prog.vertexShader, "projection");
AttrInfo_Init(&li7_attr);
AttrInfo_AddLoader(&li7_attr, 0, GPU_FLOAT, 3);
AttrInfo_AddLoader(&li7_attr, 1, GPU_FLOAT, 2);
AttrInfo_AddLoader(&li7_attr, 2, GPU_UNSIGNED_BYTE, 4);
single_color = Texture::New();
std::vector<unsigned char> pixels(16 * 16 * 4, 255);
single_color->LoadPixels(pixels, 16, 16);
// C3D_Tex* w = new C3D_Tex;
// C3D_TexInit(w, 16, 16, GPU_L8);
// C3D_TexLoadImage(w, pixels.data(), GPU_TEXFACE_2D, 0);
// single_color->ExternalLoad(w, NVec2(16, 16), NVec4(0, 1, 1, 0));
font = LIFont::New();
font->LoadSystemFont();
}
void LI::Exit() {
shaderProgramFree(&li7_prog);
DVLB_Free(li7_dvlb);
}
void LI::OnScreen(bool bottom) {
screen_size[0] = bottom ? 320 : 400;
screen_size[1] = 240;
bottom_screen = bottom;
}
bool LI::CompareCommands(const LI::Cmd& a, const LI::Cmd& b) {
if (a.layer == b.layer) {
if (a.tex == b.tex) return a.index < b.index;
return a.tex > b.tex;
}
return a.layer < b.layer;
}
void LI::RotateCorner(NVec2& v, float s, float c) {
float x = v[0] * c - v[1] * s;
float y = v[1] * c + v[0] * s;
v = NVec2(x, y);
}
void LI::MakeRect(NVec4& top, NVec4& bot, NVec2 pos, NVec2 szs, float angle) {
NVec2 c; // Center
NVec2 tl(-c[0], -c[1]); // Top Left Corner
NVec2 tr(-c[0] + szs[0], -c[1]); // Top Right Corner
NVec2 bl(-c[0], -c[1] + szs[1]); // Bottom Left Corner
NVec2 br(-c[0] + szs[0], -c[1] + szs[1]); // Bottom Right Corner
// Calculate Rotation if required
if (angle != 0.f) {
float s = std::sin(angle);
float c = std::cos(angle);
RotateCorner(tl, s, c);
RotateCorner(tr, s, c);
RotateCorner(bl, s, c);
RotateCorner(br, s, c);
}
// Generate top and bottom positions
top = NVec4(tl + pos + c, tr + pos + c);
bot = NVec4(bl + pos + c, br + pos + c);
}
void LI::RenderFrame(bool bottom) {
Palladium::Ftrace::ScopedTrace st(
"LI", "Render" + std::string(bottom ? "Bot" : "Top"));
// Create and Setup Projection Matrix
C3D_Mtx proj;
Mtx_OrthoTilt(&proj, 0.f, (bottom ? 320 : 400), screen_size[1], 0.f, 1.f,
-1.f, false);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_proj, &proj);
// Disable Depth Test
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
bool sfr = false;
// Set Tex Env to use Texture 0
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0);
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
// Setup vars for performance data
int total_vertices = 0;
int total_indices = 0;
num_drawcalls = 0;
// Get DrawCmd List and reverse it
auto& draw_cmds = draw_lists[bottom];
if (flags & PDLithiumFlags_LRS) {
std::sort(draw_cmds.begin(), draw_cmds.end(), CompareCommands);
}
num_commands = draw_cmds.size();
size_t index = 0;
// Process Command List
while (index < draw_cmds.size()) {
// Get Active Texture and Setup Vertex List for every command with same tex
C3D_Tex* texture = draw_cmds[index].tex->Get();
size_t start_vtx = vertex_index;
size_t start_idx = idx_index;
while (index < draw_cmds.size() && draw_cmds[index].tex->Get() == texture) {
auto c = draw_cmds[index];
if (c.sfr != sfr) {
if (c.sfr == 0) {
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR,
(GPU_TEVSRC)0);
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
} else if (c.sfr == 1) {
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env);
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR, (GPU_TEVSRC)0,
(GPU_TEVSRC)0);
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
C3D_TexEnvSrc(env, C3D_Alpha, GPU_PRIMARY_COLOR, GPU_TEXTURE0,
(GPU_TEVSRC)0);
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
}
sfr = c.sfr;
}
// FCS
if (c.fcs) {
c.top[0] = std::floor(c.top[0]);
c.top[1] = std::floor(c.top[1]);
c.top[2] = std::ceil(c.top[2]);
c.top[3] = std::floor(c.top[3]);
c.bot[0] = std::floor(c.bot[0]);
c.bot[1] = std::ceil(c.bot[1]);
c.bot[2] = std::ceil(c.bot[2]);
c.bot[3] = std::ceil(c.bot[3]);
}
if (c.cmd_type == 1) {
// Tiangle 1
idx_buffer[idx_index++] = vertex_index + 0;
idx_buffer[idx_index++] = vertex_index + 1;
idx_buffer[idx_index++] = vertex_index + 2;
// Tirangle 2
idx_buffer[idx_index++] = vertex_index + 0;
idx_buffer[idx_index++] = vertex_index + 2;
idx_buffer[idx_index++] = vertex_index + 3;
// Vertices
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.bot[2], c.bot[3]), c.uv[2], c.uv[3], c.clr);
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.top[2], c.top[3]), c.uv[2], c.uv[1], c.clr);
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.top[0], c.top[1]), c.uv[0], c.uv[1], c.clr);
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.bot[0], c.bot[1]), c.uv[0], c.uv[3], c.clr);
} else if (c.cmd_type == 2) {
// Triangle
idx_buffer[idx_index++] = vertex_index + 0;
idx_buffer[idx_index++] = vertex_index + 1;
idx_buffer[idx_index++] = vertex_index + 2;
// Vertices
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.bot[0], c.bot[1]), c.uv[0], c.uv[3], c.clr);
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.top[2], c.top[3]), c.uv[2], c.uv[3], c.clr);
vertex_buffer[vertex_index++] =
Vtx(NVec2(c.top[0], c.top[1]), c.uv[0], c.uv[1], c.clr);
} else if (c.cmd_type == 3) {
for (size_t i = 1; i < (size_t)c.top[3] - 1; i++) {
idx_buffer[idx_index++] = vertex_index;
idx_buffer[idx_index++] = vertex_index + i + 1;
idx_buffer[idx_index++] = vertex_index + i;
}
float as = 2.0f * M_PI / c.top[3];
for (int i = 0; i < (int)c.top[3]; i++) {
float a = i * as;
float x = c.top[0] + c.top[2] * cos(a);
float y = c.top[1] + c.top[2] * sin(a);
vertex_buffer[vertex_index++] =
Vtx(NVec2(x, y), (cos(a) + 1) / 2, (sin(a) + 1) / 2, c.clr);
}
}
index++;
}
// Bind Texture
C3D_TexBind(0, texture);
// Setup Buffer
C3D_BufInfo* bufinfo = C3D_GetBufInfo();
BufInfo_Init(bufinfo);
BufInfo_Add(bufinfo, vertex_buffer.data(), sizeof(Vtx), 3, 0x210);
// Draw
C3D_DrawElements(GPU_TRIANGLES, idx_index - start_idx, C3D_UNSIGNED_SHORT,
idx_buffer.data() + start_idx);
num_drawcalls++;
total_vertices += vertex_index - start_vtx;
total_indices += idx_index - start_idx;
}
draw_cmds.clear();
// Enable DepthTest
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
num_vertices = total_vertices;
num_indices = total_indices;
active_texture = nullptr;
}
void LI::Render(C3D_RenderTarget* top, C3D_RenderTarget* bot) {
Palladium::Ftrace::ScopedTrace st("Li7", "Render");
if (font_update) {
text_sizes.clear();
font_update = false;
}
vertex_index = 0;
idx_index = 0;
C3D_BindProgram(&li7_prog);
C3D_SetAttrInfo(&li7_attr);
C3D_FrameDrawOn(top);
RenderFrame(false);
int d_tmp_cmds1 = num_commands;
int d_tmp_dcls1 = num_drawcalls;
int d_tmp_vtxs1 = num_vertices;
int d_tmp_idx1 = num_indices;
C3D_FrameDrawOn(bot);
RenderFrame(true);
num_commands += d_tmp_cmds1;
num_drawcalls += d_tmp_dcls1;
num_vertices += d_tmp_vtxs1;
num_indices += d_tmp_idx1;
layer = 0;
cmd_index = 0;
if (flags & PDLithiumFlags_TMS) {
std::vector<std::string> rem;
for (auto& it : text_sizes) {
if (Palladium::GetTime() - it.second.time_created > 5)
rem.push_back(it.first);
}
for (auto it : rem) text_sizes.erase(it);
} else {
if (text_sizes.size()) text_sizes.clear();
}
}
void LI::DrawRect(NVec2 pos, NVec2 size, unsigned int clr, NVec4 uvs) {
Cmd c;
if (pos[0] > screen_size[0] || pos[0] + size[0] < 0 ||
pos[1] > screen_size[1] || pos[1] + size[1] < 0)
return;
MakeRect(c.top, c.bot, pos, size);
c.fcs = flags & PDLithiumFlags_FCS;
c.uv = uvs;
c.clr = clr;
c.tex = active_texture;
c.cmd_type = 1;
c.layer = layer;
c.sfr = sysfont_render;
c.index = cmd_index++;
sysfont_render = false;
draw_lists[bottom_screen].push_back(c);
}
void LI::DrawTriangle(NVec2 a, NVec2 b, NVec2 c, unsigned int clr) {
UseTexture();
Cmd cmd;
if ((a[0] > screen_size[0] && b[0] > screen_size[0] &&
c[0] > screen_size[0]) ||
(a[1] > screen_size[1] && b[1] > screen_size[1] &&
c[1] > screen_size[1]) ||
(a[0] < 0 && b[0] < 0 && c[0] < 0) || (a[1] < 0 && b[1] < 0 && c[1] < 0))
return;
cmd.fcs = flags & PDLithiumFlags_FCS;
cmd.top = NVec4(a, b);
cmd.bot = NVec4(c, NVec2());
cmd.uv = NVec4(0, 1, 1, 0);
cmd.layer = layer;
cmd.clr = clr;
cmd.tex = active_texture;
cmd.cmd_type = 2;
cmd.index = cmd_index++;
draw_lists[bottom_screen].push_back(cmd);
}
void LI::DrawCircle(NVec2 pos, float r, unsigned int color, int segments) {
if (segments < 3) return;
Cmd c;
// Not Tested yet ...
c.fcs = flags & PDLithiumFlags_FCS;
c.top = NVec4(pos, NVec2(r, segments));
c.bot = NVec4();
c.uv = NVec4(0, 1, 1, 0);
c.clr = color;
c.tex = active_texture;
c.layer = layer;
c.cmd_type = 3;
c.index = cmd_index++;
draw_lists[bottom_screen].push_back(c);
}
void LI::DrawLine(NVec2 a, NVec2 b, unsigned int clr, int t) {
UseTexture();
NVec2 direction = {b[0] - a[0], b[1] - a[1]};
float length =
std::sqrt(direction[0] * direction[0] + direction[1] * direction[1]);
NVec2 unit_direction = {direction[0] / length, direction[1] / length};
NVec2 perpendicular = {-unit_direction[1], unit_direction[0]};
float half_t = t / 2.0f;
NVec2 offset = {perpendicular[0] * half_t, perpendicular[1] * half_t};
// Calculate corner positions
float px0 = a[0] + offset[0];
float py0 = a[1] + offset[1];
float px1 = b[0] + offset[0];
float py1 = b[1] + offset[1];
float px2 = a[0] - offset[0];
float py2 = a[1] - offset[1];
float px3 = b[0] - offset[0];
float py3 = b[1] - offset[1];
Cmd c;
// Schould be always true as lines otherwise could disappear for some reason
c.fcs = flags & PDLithiumFlags_FCS;
c.top = NVec4(px2, py2, px3, py3);
c.bot = NVec4(px0, py0, px1, py1);
c.uv = NVec4(0, 1, 1, 0);
c.clr = clr;
c.tex = active_texture;
c.layer = layer;
c.cmd_type = 1;
c.index = cmd_index++;
draw_lists[bottom_screen].push_back(c);
}
std::string LI::WrapText(const std::string& in, int maxlen, NVec2& dim) {
if (flags & PDLithiumFlags_TMS) {
if (text_sizes.find(in) != text_sizes.end()) {
text_sizes[in].time_created = Palladium::GetTime();
dim = text_sizes[in].size;
if (text_sizes[in].optinal) return text_sizes[in].text;
}
}
std::string out;
std::string line;
int line_x = 0;
std::istringstream istream(in);
std::string temp;
while (istream >> temp) {
NVec2 dim = GetTextDimensions(line + temp);
if (line_x + dim[0] <= maxlen) {
line += temp + ' ';
line_x += dim[0];
} else {
out += line + '\n';
line = temp + ' ';
line_x = GetTextDimensions(line)[0];
}
}
out += line;
dim = GetTextDimensions(out);
if (flags & PDLithiumFlags_TMS) {
text_sizes[in] = TextBox{dim, Palladium::GetTime(), true, out};
}
return out;
}
std::string LI::ShortText(const std::string& in, int maxlen, NVec2& dim) {
auto textdim = GetTextDimensions(in);
if (textdim[0] < (float)maxlen) return in;
if (flags & PDLithiumFlags_TMS) {
if (text_sizes.find(in) != text_sizes.end()) {
text_sizes[in].time_created = Palladium::GetTime();
dim = text_sizes[in].size;
if (text_sizes[in].optinal) return text_sizes[in].text;
}
}
std::string ext = "";
std::string ph = "(...)"; // placeholder
std::string worker = in;
std::string out;
size_t ext_pos = in.find_last_of('.');
if (ext_pos != in.npos) {
ext = in.substr(ext_pos);
worker = in.substr(0, ext_pos);
}
maxlen -= GetTextDimensions(ext)[0];
maxlen -= GetTextDimensions(ph)[0];
for (auto& it : worker) {
if (GetTextDimensions(out)[0] > (float)maxlen) {
out += ph;
out += ext;
dim = GetTextDimensions(out);
if (flags & PDLithiumFlags_TMS) {
text_sizes[in] = TextBox{dim, Palladium::GetTime(), true, out};
}
return out;
}
out += it;
}
return out; // Impossible to reach
}
NVec2 LI::GetTextDimensions(const std::string& text) {
if (!font) return NVec2();
if (flags & PDLithiumFlags_TMS) {
if (text_sizes.find(text) != text_sizes.end()) {
text_sizes[text].time_created = Palladium::GetTime();
return text_sizes[text].size;
}
}
// FONT
auto txt = make_wstring(text + "\0");
NVec2 pos(0, 0); // Temp Pos
NVec2 offset;
float txt_scale = text_scale;
if (font->IsSystemFont()) txt_scale *= 0.9;
float gapm = 1;
float maxWidth = 0.f;
float ntxtszs = default_font_size * txt_scale;
float cpm = ntxtszs / font->GetPixelHeight();
float line_height = font->GetPixelHeight() * cpm;
for (size_t i = 0; i < txt.length(); i++) {
if (txt[i] == '\0') break;
auto cp = font->GetCodepoint(txt[i]);
if (cp.invalid && txt[i] != '\n' && txt[i] != ' ' && txt[i] != '\t')
continue;
bool implicitBreak = false;
if (txt[i] == '\n' || implicitBreak) {
offset[1] += line_height;
maxWidth = std::max(maxWidth, offset[0]);
offset[0] = 0;
if (implicitBreak) continue;
} else if (txt[i] == '\t') {
offset[0] = ((offset[0] / ntxtszs) / 4 + 1) * 4 * ntxtszs;
} else {
if (txt[i] == ' ') {
// this will make the space twice
if (!font->IsSystemFont()) offset[0] += 4 * gapm * txt_scale;
}
if (i == txt.length() - 1)
offset[0] += cp.szs[0] * cpm + txt_scale;
else
offset[0] += cp.szs[0] * cpm + (gapm * txt_scale);
}
}
maxWidth = std::max(maxWidth, offset[0]);
NVec2 res = NVec2(maxWidth, offset[1] + (default_font_size * txt_scale));
if (flags & PDLithiumFlags_TMS)
text_sizes[text] = TextBox{res, Palladium::GetTime(), false, ""};
return res;
}
void LI::DrawText(NVec2 pos, unsigned int color, const std::string& text,
PDTextFlags flags, NVec2 ap) {
if (!font) return;
PDLithiumFlags tmp_flags = flags;
// Do not use FCS in Text Rendering...
flags &= ~PDLithiumFlags_FCS;
std::string txt = text;
NVec2 offset;
float txt_scale = text_scale;
if (font->IsSystemFont()) txt_scale *= 0.9;
float gapm = 1;
float ntxtszs = default_font_size * txt_scale;
float cpm = ntxtszs / font->GetPixelHeight();
float line_height = font->GetPixelHeight() * cpm;
NVec2 td;
if (flags & PDTextFlags_Wrap)
txt = WrapText(text, ap[0] - pos[0], td);
else if (flags & PDTextFlags_Short)
txt = ShortText(text, ap[0] - pos[0], td);
if (td[0] == 0 && td[1] == 0) td = GetTextDimensions(text);
if (flags & PDTextFlags_AlignRight)
pos[0] -= td[0];
else if (flags & PDTextFlags_AlignMid) {
pos[0] = (ap[0] * 0.5) - (td[0] * 0.5) + pos[0];
}
std::vector<std::string> lines;
std::istringstream iss(txt);
std::string temp;
while (std::getline(iss, temp)) {
lines.push_back(temp);
}
for (auto& it : lines) {
if (pos[1] + offset[1] + line_height < 0) {
offset[1] += line_height;
continue;
} else if (pos[1] + offset[1] > screen_size[1]) {
// Break func as we dont want loop over lines that get skipped too
break;
}
auto wstr = make_wstring(it);
// Loop over line
for (auto& jt : wstr) {
auto cp = font->GetCodepoint(jt);
if (cp.invalid && jt != '\n' && jt != ' ' && jt != '\t') continue;
active_texture = cp.tex;
if (jt == '\t') {
offset[0] = ((offset[0] / ntxtszs) / 4 + 1) * 4 * ntxtszs;
} else {
if (jt != ' ') {
int lr = layer;
if (flags & PDTextFlags_Shaddow) {
sysfont_render = true;
DrawRect(
pos + NVec2(offset[0] + 1, (offset[1] + (cp.off * cpm)) + 1),
NVec2(cp.szs[0] * cpm, cp.szs[1] * cpm),
Palladium::Color::RGBA(color).is_light() ? 0xff111111
: 0xffeeeeee,
cp.uv);
layer++;
}
sysfont_render = true;
DrawRect(pos + offset + NVec2(0, (cp.off * cpm)),
NVec2(cp.szs[0] * cpm, cp.szs[1] * cpm), color, cp.uv);
layer = lr;
} else {
// this will make the space twice
if (!font->IsSystemFont()) offset[0] += 4 * gapm * txt_scale;
}
offset[0] += cp.szs[0] * cpm + (gapm * txt_scale);
}
}
offset[1] += line_height;
offset[0] = 0;
}
flags = tmp_flags;
}
} // namespace Palladium

View File

@ -1,94 +0,0 @@
#include <algorithm>
#include <memory>
#include <pd/Lithium.hpp>
#include <pd/Message.hpp>
#include <pd/base/Color.hpp>
#include <pd/palladium.hpp>
#include <vector>
extern bool pdi_debugging;
static std::vector<std::shared_ptr<Palladium::Message>> msg_lst;
static int fade_outs = 200; // Start of fadeout
static int idles = 60; // start of Idle
static int anim_len = 300; // Full Length of Animation
static NVec2 msg_box = NVec2(170, 50); // Message Box Size
NVec2 MakePos(float anim_time, int entry) {
float fol = anim_len - fade_outs;
if (anim_time > fade_outs)
return NVec2(
5, static_cast<int>(240 - ((entry + 1) * 55) - 5 +
(float)((anim_time - fade_outs) / fol) * -20));
if (anim_time > idles) return NVec2(5, 240 - ((entry + 1) * 55) - 5);
return NVec2(
static_cast<int>(-150 + ((float)(anim_time / (float)idles) * 155)),
240 - ((entry + 1) * 55) - 5);
}
namespace Palladium {
float GetDeltaTime(); // Extern from Palladium.cpp
void ProcessMessages() {
float tmp_txt = LI::GetTextScale();
LI::DefaultTextScale();
// Draw in ovl mode
LI::OnScreen(false);
LI::NewLayer();
float fol = anim_len - fade_outs;
std::reverse(msg_lst.begin(), msg_lst.end());
for (size_t i = 0; i < msg_lst.size(); i++) {
NVec2 pos = MakePos(msg_lst[i]->animtime, i);
if ((pos.y() + 150) < 0) {
// Dont Render Out of Screen
// And as thay aren't relevant anymore
// Thay get deleted!
msg_lst.erase(msg_lst.begin() + i);
} else {
int new_alpha = 200;
if (msg_lst[i]->animtime > fade_outs) {
new_alpha = 200 - (float(msg_lst[i]->animtime - fade_outs) / fol) * 200;
}
// Wtf is this function lol
auto bgc = Palladium::Color::RGBA(PDColor_MessageBackground)
.changeA(new_alpha)
.toRGBA();
auto tc =
Palladium::Color::RGBA(PDColor_Text2).changeA(new_alpha).toRGBA();
LI::DrawRect(pos, msg_box, bgc);
LI::NewLayer();
LI::DrawText(pos + NVec2(5, 1), tc, msg_lst[i]->title);
LI::DrawText(pos + NVec2(5, 17), tc, msg_lst[i]->message);
if (pdi_debugging)
LI::DrawText(pos + NVec2(msg_box.x() + 5, 1), tc,
std::to_string((int)msg_lst[i]->animtime));
// fix for Startup lol
// Todo: Only do this on AppStart
if (msg_lst[i]->animtime == 0) {
msg_lst[i]->animtime += 1;
} else {
msg_lst[i]->animtime += Palladium::GetDeltaTime() * 0.1f;
}
if (msg_lst[i]->animtime > anim_len) {
msg_lst.erase(msg_lst.begin() + i);
}
}
}
// ReReverse ?? lol
// Cause otherwise the Toasts will swap
std::reverse(msg_lst.begin(), msg_lst.end());
LI::SetTextScale(tmp_txt);
}
void PushMessage(const Message &msg) {
msg_lst.push_back(std::make_shared<Palladium::Message>(msg));
}
void SetMessageIdleStartFrame(int frame) { idles = frame; }
void SetMessageTotalAnimationFrames(int total_frames) {
anim_len = total_frames;
}
void SetMessageFadeOutStartFrame(int frame) { fade_outs = frame; }
} // namespace Palladium

View File

@ -1,243 +0,0 @@
// TODO: Make Download2File faster on large files
#include <3ds.h>
#include <curl/curl.h>
#include <malloc.h>
#include <unistd.h>
#include <filesystem>
#include <fstream>
#include <pd/Net.hpp>
#include <pd/internal_db.hpp>
#include <regex>
static Palladium::Net::Error pdi_check_wifi() {
// if (pdi_is_citra) return 0;
int s = osGetWifiStrength();
return (s == 0 ? Palladium::Net::Error_NoWifi : 0);
}
static size_t pdi_handle_data(char* ptr, size_t size, size_t nmemb,
void* userdata) {
size_t ms = size * nmemb;
((std::string*)userdata)->append(ptr, ms);
return ms;
}
static size_t pdi_handle_file(char* ptr, size_t size, size_t nmemb, void* out) {
size_t ms = size * nmemb;
((std::ofstream*)out)->write(reinterpret_cast<const char*>(ptr), ms);
return ms;
}
struct pdi_net_dl {
unsigned long long current = 0;
unsigned long long total = 1;
void Reset() {
current = 0;
total = 1;
}
};
static pdi_net_dl pdi_net_dl_spec;
static int pdi_handle_curl_progress(CURL* hnd, curl_off_t dltotal,
curl_off_t dlnow, curl_off_t ultotal,
curl_off_t ulnow) {
pdi_net_dl_spec.total = dltotal;
pdi_net_dl_spec.current = dlnow;
return 0;
}
static void pdi_setup_curl_context(CURL* hnd, const std::string& url,
void* userptr, bool mem) {
std::string user_agent =
pdi_app_name + "/Palladium (Version: " + std::string(PDVSTRING) + ")";
if (!mem) {
curl_easy_setopt(hnd, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, "gzip");
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, pdi_handle_curl_progress);
}
curl_easy_setopt(hnd, CURLOPT_URL, url.c_str());
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, user_agent.c_str());
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, userptr);
curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION,
mem ? pdi_handle_data : pdi_handle_file);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_STDERR, stdout);
}
static bool pdi_curl_is_busy = false;
static bool pdi_apir_is_busy = false;
namespace Palladium {
namespace Net {
Error Download(const std::string& url, std::string& data) {
if (pdi_curl_is_busy) return Error_Busy;
Error ret = pdi_check_wifi();
if (ret != 0) {
return ret;
}
pdi_curl_is_busy = true;
pdi_net_dl_spec.Reset();
auto hnd = curl_easy_init();
pdi_setup_curl_context(hnd, url, &data, true);
CURLcode curl_res = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
if (curl_res != CURLE_OK) {
data.clear();
pdi_curl_is_busy = false;
return ((static_cast<Error>(curl_res) << 32) |
static_cast<Error>(Error_Curl));
}
pdi_curl_is_busy = false;
return 0;
}
Error Download2File(const std::string& url, const std::string& path) {
if (pdi_curl_is_busy) return Error_Busy;
Error ret = pdi_check_wifi();
if (ret != 0) {
return ret;
}
pdi_curl_is_busy = true;
pdi_net_dl_spec.Reset();
// std::filesystem::create_directories(
// std::filesystem::path(path).remove_filename());
std::ofstream file(path, std::ios::binary);
if (!file.is_open()) {
pdi_curl_is_busy = false;
return Error_Write;
}
auto hnd = curl_easy_init();
pdi_setup_curl_context(hnd, url, &file, false);
CURLcode curl_res = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
file.close();
if (curl_res != CURLE_OK) {
if (Palladium::FS::FileExist(path)) {
std::filesystem::remove(path);
}
pdi_curl_is_busy = false;
return ((static_cast<Error>(curl_res) << 32) |
static_cast<Error>(Error_Curl));
}
pdi_curl_is_busy = false;
return 0;
}
Error GitDownloadRelease(const std::string& url, const std::string& asset_name,
const std::string& path, bool prerelease) {
if (pdi_apir_is_busy) return Error_Busy;
Error ret = pdi_check_wifi();
if (ret != 0) {
return ret;
}
pdi_apir_is_busy = true;
std::regex parse("github\\.com\\/(.+)\\/(.+)");
std::smatch res;
std::regex_search(url, res, parse);
std::string user = res[1].str();
std::string repo = res[2].str();
std::stringstream req;
req << "https://api.github.com/repos/" << user << "/" << repo
<< (prerelease ? "/releases" : "/releases/latest");
std::string buf;
ret = Download(req.str(), buf);
if (ret) {
pdi_apir_is_busy = false;
return ret;
}
int pret = 0;
std::string freq;
if (nlohmann::json::accept(buf)) {
nlohmann::json api = nlohmann::json::parse(buf);
if (!api.size()) pret = -1;
if (pret != -1) {
if (prerelease) api = api[0];
if (api["assets"].is_array()) {
for (const auto& asset : api["assets"]) {
if (asset.is_object() && asset["name"].is_string() &&
asset["browser_download_url"].is_string()) {
if (std::regex_match(std::string(asset["name"]),
std::regex(asset_name))) {
freq = asset["browser_download_url"];
break;
}
}
}
}
}
} else {
pret = -1;
}
if (pret != 0 || freq.empty()) {
pdi_apir_is_busy = false;
return Error_Git;
}
ret = Download2File(freq, path);
pdi_apir_is_busy = false;
return ret;
}
Error JsonApiRequest(const std::string& api_url, nlohmann::json& res) {
if (pdi_apir_is_busy) return Error_Busy;
Error ret = pdi_check_wifi();
if (ret != 0) {
return ret;
}
pdi_apir_is_busy = true;
std::string buf;
ret = Download(api_url, buf);
if (ret) {
pdi_apir_is_busy = false;
return ret;
}
if (nlohmann::json::accept(buf)) {
res = nlohmann::json::parse(buf);
if (!res.size()) {
pdi_apir_is_busy = false;
return Error_Invalid;
}
} else {
pdi_apir_is_busy = false;
return Error_Invalid;
}
pdi_apir_is_busy = false;
return 0;
}
unsigned long long GetProgressCurrent() { return pdi_net_dl_spec.current; }
unsigned long long GetProgressTotal() {
// As curl sets total to 0 we need
// to return a 1 as devide by zeroi will crash
if (pdi_net_dl_spec.total <= 0) return 1;
return pdi_net_dl_spec.total;
}
} // namespace Net
} // namespace Palladium

View File

@ -1,616 +0,0 @@
#include <format>
#include <pd/Hid.hpp>
#include <pd/Lithium.hpp>
#include <pd/Overlays.hpp>
#include <pd/base/FunctionTrace.hpp>
#include <pd/internal_db.hpp>
#include <pd/palladium.hpp>
///////////////////////////////
struct Key {
std::string disp;
NVec2 pos;
NVec2 size;
// 0 = default key
// 1 = Shift
// 2 = Backsp
// 3 = Enter
// 4 = Cancel
// 5 = Confirm
// 6 = Tab
// 7 = Caps
// 8 = Space
int action = 0;
};
std::vector<Key> keyboard_layout_num{
// 1st row
{"7", NVec2(5, 135), NVec2(36, 24), 0},
{"8", NVec2(43, 135), NVec2(36, 24), 0},
{"9", NVec2(81, 135), NVec2(36, 24), 0},
// 2nd row
{"4", NVec2(5, 161), NVec2(36, 24), 0},
{"5", NVec2(43, 161), NVec2(36, 24), 0},
{"6", NVec2(81, 161), NVec2(36, 24), 0},
// 3rd row
{"1", NVec2(5, 187), NVec2(36, 24), 0},
{"2", NVec2(43, 187), NVec2(36, 24), 0},
{"3", NVec2(81, 187), NVec2(36, 24), 0},
// 4th row
{"0", NVec2(5, 213), NVec2(74, 24), 0},
{".", NVec2(81, 213), NVec2(36, 24), 0},
// additional actions
{"<---", NVec2(119, 135), NVec2(74, 24), 2},
//{"", NVec2(119, 161), NVec2(74, 24), 0},
{"Confirm", NVec2(119, 187), NVec2(74, 24), 5},
{"Cancel", NVec2(119, 213), NVec2(74, 24), 4},
};
std::vector<Key> keyboard_layout = {
// 1st row
{"`", NVec2(5, 137), NVec2(18, 18), 0},
{"1", NVec2(25, 137), NVec2(18, 18), 0},
{"2", NVec2(45, 137), NVec2(18, 18), 0},
{"3", NVec2(65, 137), NVec2(18, 18), 0},
{"4", NVec2(85, 137), NVec2(18, 18), 0},
{"5", NVec2(105, 137), NVec2(18, 18), 0},
{"6", NVec2(125, 137), NVec2(18, 18), 0},
{"7", NVec2(145, 137), NVec2(18, 18), 0},
{"8", NVec2(165, 137), NVec2(18, 18), 0},
{"9", NVec2(185, 137), NVec2(18, 18), 0},
{"0", NVec2(205, 137), NVec2(18, 18), 0},
{"-", NVec2(225, 137), NVec2(18, 18), 0},
{"=", NVec2(245, 137), NVec2(18, 18), 0},
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
// 2nd row
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
{"q", NVec2(47, 157), NVec2(18, 18), 0},
{"w", NVec2(67, 157), NVec2(18, 18), 0},
{"e", NVec2(87, 157), NVec2(18, 18), 0},
{"r", NVec2(107, 157), NVec2(18, 18), 0},
{"t", NVec2(127, 157), NVec2(18, 18), 0},
{"y", NVec2(147, 157), NVec2(18, 18), 0},
{"u", NVec2(167, 157), NVec2(18, 18), 0},
{"i", NVec2(187, 157), NVec2(18, 18), 0},
{"o", NVec2(207, 157), NVec2(18, 18), 0},
{"p", NVec2(227, 157), NVec2(18, 18), 0},
{"[", NVec2(247, 157), NVec2(18, 18), 0},
{"]", NVec2(267, 157), NVec2(18, 18), 0},
{"\\", NVec2(287, 157), NVec2(28, 18), 0},
// 3rd row
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
{"a", NVec2(57, 177), NVec2(18, 18), 0},
{"s", NVec2(77, 177), NVec2(18, 18), 0},
{"d", NVec2(97, 177), NVec2(18, 18), 0},
{"f", NVec2(117, 177), NVec2(18, 18), 0},
{"g", NVec2(137, 177), NVec2(18, 18), 0},
{"h", NVec2(157, 177), NVec2(18, 18), 0},
{"j", NVec2(177, 177), NVec2(18, 18), 0},
{"k", NVec2(197, 177), NVec2(18, 18), 0},
{"l", NVec2(217, 177), NVec2(18, 18), 0},
{";", NVec2(237, 177), NVec2(18, 18), 0},
{"'", NVec2(257, 177), NVec2(18, 18), 0},
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
// 4th row
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
{"z", NVec2(67, 197), NVec2(18, 18), 0},
{"x", NVec2(87, 197), NVec2(18, 18), 0},
{"c", NVec2(107, 197), NVec2(18, 18), 0},
{"v", NVec2(127, 197), NVec2(18, 18), 0},
{"b", NVec2(147, 197), NVec2(18, 18), 0},
{"n", NVec2(167, 197), NVec2(18, 18), 0},
{"m", NVec2(187, 197), NVec2(18, 18), 0},
{",", NVec2(207, 197), NVec2(18, 18), 0},
{".", NVec2(227, 197), NVec2(18, 18), 0},
{"/", NVec2(247, 197), NVec2(18, 18), 0},
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
// 5th row
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
/*{"←", NVec2(237, 217), NVec2(18, 18)},
{"", NVec2(257, 217), NVec2(18, 18)},
{"", NVec2(277, 217), NVec2(18, 18)},
{"", NVec2(297, 217), NVec2(18, 18)},*/
};
std::vector<Key> keyboard_layout_caps = {
// 1st row
{"`", NVec2(5, 137), NVec2(18, 18), 0},
{"1", NVec2(25, 137), NVec2(18, 18), 0},
{"2", NVec2(45, 137), NVec2(18, 18), 0},
{"3", NVec2(65, 137), NVec2(18, 18), 0},
{"4", NVec2(85, 137), NVec2(18, 18), 0},
{"5", NVec2(105, 137), NVec2(18, 18), 0},
{"6", NVec2(125, 137), NVec2(18, 18), 0},
{"7", NVec2(145, 137), NVec2(18, 18), 0},
{"8", NVec2(165, 137), NVec2(18, 18), 0},
{"9", NVec2(185, 137), NVec2(18, 18), 0},
{"0", NVec2(205, 137), NVec2(18, 18), 0},
{"-", NVec2(225, 137), NVec2(18, 18), 0},
{"=", NVec2(245, 137), NVec2(18, 18), 0},
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
// 2nd row
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
{"Q", NVec2(47, 157), NVec2(18, 18), 0},
{"W", NVec2(67, 157), NVec2(18, 18), 0},
{"E", NVec2(87, 157), NVec2(18, 18), 0},
{"R", NVec2(107, 157), NVec2(18, 18), 0},
{"T", NVec2(127, 157), NVec2(18, 18), 0},
{"Y", NVec2(147, 157), NVec2(18, 18), 0},
{"U", NVec2(167, 157), NVec2(18, 18), 0},
{"I", NVec2(187, 157), NVec2(18, 18), 0},
{"O", NVec2(207, 157), NVec2(18, 18), 0},
{"P", NVec2(227, 157), NVec2(18, 18), 0},
{"[", NVec2(247, 157), NVec2(18, 18), 0},
{"]", NVec2(267, 157), NVec2(18, 18), 0},
{"\\", NVec2(287, 157), NVec2(28, 18), 0},
// 3rd row
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
{"A", NVec2(57, 177), NVec2(18, 18), 0},
{"S", NVec2(77, 177), NVec2(18, 18), 0},
{"D", NVec2(97, 177), NVec2(18, 18), 0},
{"F", NVec2(117, 177), NVec2(18, 18), 0},
{"G", NVec2(137, 177), NVec2(18, 18), 0},
{"H", NVec2(157, 177), NVec2(18, 18), 0},
{"J", NVec2(177, 177), NVec2(18, 18), 0},
{"K", NVec2(197, 177), NVec2(18, 18), 0},
{"L", NVec2(217, 177), NVec2(18, 18), 0},
{";", NVec2(237, 177), NVec2(18, 18), 0},
{"'", NVec2(257, 177), NVec2(18, 18), 0},
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
// 4th row
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
{"Z", NVec2(67, 197), NVec2(18, 18), 0},
{"X", NVec2(87, 197), NVec2(18, 18), 0},
{"C", NVec2(107, 197), NVec2(18, 18), 0},
{"V", NVec2(127, 197), NVec2(18, 18), 0},
{"B", NVec2(147, 197), NVec2(18, 18), 0},
{"N", NVec2(167, 197), NVec2(18, 18), 0},
{"M", NVec2(187, 197), NVec2(18, 18), 0},
{",", NVec2(207, 197), NVec2(18, 18), 0},
{".", NVec2(227, 197), NVec2(18, 18), 0},
{"/", NVec2(247, 197), NVec2(18, 18), 0},
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
// 5th row
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
/*{"←", NVec2(237, 217), NVec2(18, 18)},
{"", NVec2(257, 217), NVec2(18, 18)},
{"", NVec2(277, 217), NVec2(18, 18)},
{"", NVec2(297, 217), NVec2(18, 18)},*/
};
std::vector<Key> keyboard_layout_shift = {
// 1st row
{"~", NVec2(5, 137), NVec2(18, 18), 0},
{"!", NVec2(25, 137), NVec2(18, 18), 0},
{"@", NVec2(45, 137), NVec2(18, 18), 0},
{"#", NVec2(65, 137), NVec2(18, 18), 0},
{"$", NVec2(85, 137), NVec2(18, 18), 0},
{"%", NVec2(105, 137), NVec2(18, 18), 0},
{"^", NVec2(125, 137), NVec2(18, 18), 0},
{"&", NVec2(145, 137), NVec2(18, 18), 0},
{"*", NVec2(165, 137), NVec2(18, 18), 0},
{"(", NVec2(185, 137), NVec2(18, 18), 0},
{")", NVec2(205, 137), NVec2(18, 18), 0},
{"_", NVec2(225, 137), NVec2(18, 18), 0},
{"+", NVec2(245, 137), NVec2(18, 18), 0},
{"<---", NVec2(265, 137), NVec2(50, 18), 2},
// 2nd row
{"Tab", NVec2(5, 157), NVec2(40, 18), 6},
{"Q", NVec2(47, 157), NVec2(18, 18), 0},
{"W", NVec2(67, 157), NVec2(18, 18), 0},
{"E", NVec2(87, 157), NVec2(18, 18), 0},
{"R", NVec2(107, 157), NVec2(18, 18), 0},
{"T", NVec2(127, 157), NVec2(18, 18), 0},
{"Y", NVec2(147, 157), NVec2(18, 18), 0},
{"U", NVec2(167, 157), NVec2(18, 18), 0},
{"I", NVec2(187, 157), NVec2(18, 18), 0},
{"O", NVec2(207, 157), NVec2(18, 18), 0},
{"P", NVec2(227, 157), NVec2(18, 18), 0},
{"{", NVec2(247, 157), NVec2(18, 18), 0},
{"}", NVec2(267, 157), NVec2(18, 18), 0},
{"|", NVec2(287, 157), NVec2(28, 18), 0},
// 3rd row
{"Caps", NVec2(5, 177), NVec2(50, 18), 7},
{"A", NVec2(57, 177), NVec2(18, 18), 0},
{"S", NVec2(77, 177), NVec2(18, 18), 0},
{"D", NVec2(97, 177), NVec2(18, 18), 0},
{"F", NVec2(117, 177), NVec2(18, 18), 0},
{"G", NVec2(137, 177), NVec2(18, 18), 0},
{"H", NVec2(157, 177), NVec2(18, 18), 0},
{"J", NVec2(177, 177), NVec2(18, 18), 0},
{"K", NVec2(197, 177), NVec2(18, 18), 0},
{"L", NVec2(217, 177), NVec2(18, 18), 0},
{":", NVec2(237, 177), NVec2(18, 18), 0},
{"\"", NVec2(257, 177), NVec2(18, 18), 0},
{"Enter", NVec2(277, 177), NVec2(38, 18), 3},
// 4th row
{"Shift", NVec2(5, 197), NVec2(60, 18), 1},
{"Z", NVec2(67, 197), NVec2(18, 18), 0},
{"X", NVec2(87, 197), NVec2(18, 18), 0},
{"C", NVec2(107, 197), NVec2(18, 18), 0},
{"V", NVec2(127, 197), NVec2(18, 18), 0},
{"B", NVec2(147, 197), NVec2(18, 18), 0},
{"N", NVec2(167, 197), NVec2(18, 18), 0},
{"M", NVec2(187, 197), NVec2(18, 18), 0},
{"<", NVec2(207, 197), NVec2(18, 18), 0},
{">", NVec2(227, 197), NVec2(18, 18), 0},
{"?", NVec2(247, 197), NVec2(18, 18), 0},
{"Shift", NVec2(267, 197), NVec2(48, 18), 1},
// 5th row
{"Cancel", NVec2(5, 217), NVec2(70, 18), 4},
{"(X)", NVec2(77, 217), NVec2(23, 18), 10},
{"Space", NVec2(102, 217), NVec2(108, 18), 8},
{"(!)", NVec2(212, 217), NVec2(23, 18), 10},
{"Confirm", NVec2(237, 217), NVec2(78, 18), 5},
/*{"←", NVec2(237, 217), NVec2(18, 18)},
{"", NVec2(257, 217), NVec2(18, 18)},
{"", NVec2(277, 217), NVec2(18, 18)},
{"", NVec2(297, 217), NVec2(18, 18)},*/
};
// From UI7
bool UI7_InBox(NVec2 inpos, NVec2 boxpos, NVec2 boxsize) {
if ((inpos.x() > boxpos.x()) && (inpos.y() > boxpos.y()) &&
(inpos.x() < boxpos.x() + boxsize.x()) &&
(inpos.y() < boxpos.y() + boxsize.y()))
return true;
return false;
}
namespace Palladium {
Ovl_Ftrace::Ovl_Ftrace(bool* is_enabled) { i_is_enabled = is_enabled; }
void Ovl_Ftrace::Draw(void) const {
float tmp_txt = LI::GetTextScale();
LI::DefaultTextScale();
LI::OnScreen(false);
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_FillBg) {
LI::NewLayer();
Palladium::Color::RGBA bg(PDColor_Background);
bg.changeA(150);
LI::DrawRect(NVec2(0, 0), NVec2(400, 20), bg.toRGBA());
}
LI::NewLayer();
int lrb = LI::Layer();
std::string label = "FTrace Overlay";
auto lbdim = LI::GetTextDimensions(label);
LI::DrawRect(NVec2(), lbdim,
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
LI::Layer(lrb + 1);
LI::DrawText(NVec2(0, 0), Palladium::ThemeActive()->Get(PDColor_Text2),
label);
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayHelp) {
std::string hlp =
(pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayName ? "Name" : "#");
hlp += ": Current";
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage ||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin ||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) {
hlp += " |";
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage)
hlp += " Avg";
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin) hlp += " Min";
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) hlp += " Max";
}
auto hlpdim = LI::GetTextDimensions(hlp);
LI::Layer(lrb);
LI::DrawRect(NVec2(0, 20), hlpdim,
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
LI::Layer(lrb + 1);
LI::DrawText(NVec2(0, 20), Palladium::ThemeActive()->Get(PDColor_Text2),
hlp);
}
std::vector<Palladium::Ftrace::FTRes> dt;
for (auto const& it : Palladium::Ftrace::pd_traces)
if (it.second.is_ovl && dt.size() < 10) dt.push_back(it.second);
for (size_t i = 0; i < (dt.size() < 10 ? dt.size() : 10); i++) {
std::string slot = (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayName
? dt[i].func_name
: std::to_string(i));
slot += ": " + MsTimeFmt(dt[i].time_of);
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage ||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin ||
pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax) {
slot += " |";
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayAverage)
slot += " " + MsTimeFmt(dt[i].ts.GetAverage());
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMin)
slot += " " + MsTimeFmt(dt[i].ts.GetMin());
if (pd_ftrace_ovl_flags & PDFTraceOverlayFlags_DisplayMax)
slot += " " + MsTimeFmt(dt[i].ts.GetMax());
}
auto dim = LI::GetTextDimensions(slot);
LI::Layer(lrb);
LI::DrawRect(NVec2(0, 37 + i * dim.y()), dim,
Palladium::ThemeActive()->Get(PDColor_TextDisabled));
LI::Layer(lrb + 1);
LI::DrawText(NVec2(0, 37 + i * dim.y()),
Palladium::ThemeActive()->Get(PDColor_Text2), slot);
}
LI::SetTextScale(tmp_txt);
}
void Ovl_Ftrace::Logic() {
if (!i_is_enabled[0]) this->Kill();
}
Ovl_Metrik::Ovl_Metrik(bool* is_enabled, bool* screen, unsigned int* mt_color,
unsigned int* txt_color, float* txt_size)
: cpu_stats(300), gpu_stats(300) {
i_is_enabled = is_enabled;
i_screen = screen;
i_mt_color = mt_color;
i_txt_color = txt_color;
i_txt_size = txt_size;
v_update.Reset();
}
int MetrikEntry(const std::string& text, NVec2 pos, unsigned int clr1,
unsigned int clr2) {
int dim_y = LI::GetTextDimensions(text).y();
int lr = LI::Layer();
LI::DrawRect(pos, LI::GetTextDimensions(text), clr1);
LI::Layer(lr + 1);
LI::DrawText(pos, clr2, text);
LI::Layer(lr);
return dim_y + !LI::GetFont()->IsSystemFont();
}
void Graph(Palladium::Ftrace::TimeStats& s, NVec2 pos, NVec2 size, NVec2 range,
unsigned int clr, int lod = 1) {
float xs = static_cast<float>(size.x() / s.GetLen());
float ys = static_cast<float>(size.y() / (range.y() - range.x()));
std::vector<NVec2> nodes;
for (size_t i = 0; i < s.GetNumValues(); i += lod) {
nodes.push_back(
NVec2(pos.x() + i * xs, pos.y() + size.y() - (s[i] - range.x()) * ys));
}
for (size_t i = 1; i < nodes.size(); i++)
LI::DrawLine(nodes[i - 1], nodes[i], clr);
}
void Ovl_Metrik::Draw(void) const {
float tmp_txt = LI::GetTextScale();
LI::SetTextScale(*i_txt_size);
LI::OnScreen(i_screen[0]);
LI::NewLayer();
std::string info = "Palladium " + std::string(PDVSTRING) + " Debug Overlay";
float dim_y = LI::GetTextDimensions(info).y();
mt_fps = std::format("{:.2f}ms/f -> {:.1f} FPS", Palladium::GetDeltaTime(),
1000.f / Palladium::GetDeltaTime());
if (pdi_idb_running) mt_fps += " IDB -> ON";
float cpu_time = C3D_GetProcessingTime();
cpu_stats.Add(cpu_time);
float gpu_time = C3D_GetDrawingTime();
gpu_stats.Add(gpu_time);
v_update.Tick();
if (v_update.Get() > 500.f) {
float fps_lim = C3D_FrameRate(0.f) / 10.f;
mt_cpu = std::format("CPU: {:.1f}% | {:.2f}ms | {:.2f}ms",
cpu_time * fps_lim, cpu_time, cpu_stats.GetAverage());
mt_gpu = std::format("GPU: {:.1f}% | {:.2f}ms | {:.2f}ms",
gpu_time * fps_lim, gpu_time, gpu_stats.GetAverage());
v_update.Reset();
}
mt_cmd = std::format("CMD: {:.2f}%", C3D_GetCmdBufUsage() * 100.f);
mt_lfr = "Linear: " + Palladium::FormatBytes(linearSpaceFree());
if (pd_flags & PDFlags_MemTrack)
mt_mem = "Mem: " + Palladium::FormatBytes(Palladium::Memory::GetCurrent()) +
" | " +
Palladium::FormatBytes(Palladium::Memory::GetTotalAllocated()) +
" | " + Palladium::FormatBytes(Palladium::Memory::GetTotalFreed());
mt_vtx = "Vertices: " + std::to_string(LI::Vertices());
mt_idx = "Indices: " + std::to_string(LI::Indices());
mt_dmc = "DrawCmds: " + std::to_string(LI::DarwCommands());
mt_drc = "DrawCalls: " + std::to_string(LI::Drawcalls());
// Rendering
int posy = 0;
if (pd_ovl_flags & PDMetrikOverlayFlags_FPS)
posy += MetrikEntry(mt_fps, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
// Mod PosY to 50
posy = 50;
if (pd_ovl_flags & PDMetrikOverlayFlags_CPU)
posy += MetrikEntry(mt_cpu, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_GPU)
posy += MetrikEntry(mt_gpu, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_CMD)
posy += MetrikEntry(mt_cmd, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_LMM)
posy += MetrikEntry(mt_lfr, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_LVT)
posy += MetrikEntry(mt_vtx, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_LID)
posy += MetrikEntry(mt_idx, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_LDM)
posy += MetrikEntry(mt_dmc, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_LDC)
posy += MetrikEntry(mt_drc, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_flags & PDFlags_MemTrack && pd_ovl_flags & PDMetrikOverlayFlags_MTD)
posy += MetrikEntry(mt_mem, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
posy = 240 - dim_y;
if (pd_ovl_flags & PDMetrikOverlayFlags_PDO)
posy += MetrikEntry(info, NVec2(0, posy), i_mt_color[0], i_txt_color[0]);
if (pd_ovl_flags & PDMetrikOverlayFlags_CGR ||
pd_ovl_flags & PDMetrikOverlayFlags_GGR) {
LI::NewLayer();
float tl = 1000.f / GetFps();
std::string tlt = std::format("{:.2f}ms", tl);
auto tldim = LI::GetTextDimensions(tlt);
LI::DrawRect(NVec2(0, 17), NVec2(150 + tldim.x(), 33), i_mt_color[0]);
LI::NewLayer();
LI::DrawText(NVec2(150, 17), i_txt_color[0], tlt);
if (pd_ovl_flags & PDMetrikOverlayFlags_CGR)
Graph(cpu_stats, NVec2(0, 17), NVec2(150, 33), NVec2(0, tl), 0xff0000ff,
2);
if (pd_ovl_flags & PDMetrikOverlayFlags_GGR)
Graph(gpu_stats, NVec2(0, 17), NVec2(150, 33), NVec2(0, tl), 0xffff0000,
2);
}
// Force Bottom (Debug Touchpos)
LI::OnScreen(true);
if (Hid::IsEvent("touch", Hid::Held)) {
LI::DrawLine(NVec2((int)Hid::GetTouchPosition().x(), 0),
NVec2((int)Hid::GetTouchPosition().x(), 240),
Palladium::Color::Hex("#ff0000"));
LI::DrawLine(NVec2(0, (int)Hid::GetTouchPosition().y()),
NVec2(320, (int)Hid::GetTouchPosition().y()),
Palladium::Color::Hex("#ff0000"));
}
LI::SetTextScale(tmp_txt);
}
void Ovl_Metrik::Logic() {
if (!i_is_enabled[0]) this->Kill();
}
Ovl_Keyboard::Ovl_Keyboard(std::string& ref, PDKeyboardState& state,
const std::string& hint, PDKeyboard type,
PDKeyboardFlags flags) {
// Blocks All Input outside of Keyboard
// Doesnt work for Hidkeys down etc
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Lock();
typed_text = &ref;
this->state = &state;
this->type = type;
this->flags = flags;
*this->state = PDKeyboardState_None;
str_bak = ref;
ft3 = 0;
}
Ovl_Keyboard::~Ovl_Keyboard() {
// And Unlock when closing Keyboard lol
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Unlock();
}
void Ovl_Keyboard::Draw(void) const {
float tmp_txt = LI::GetTextScale();
LI::DefaultTextScale();
if (ft3 > 5) {
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Unlock();
}
auto key_table =
(type == PDKeyboard_Numpad) ? keyboard_layout_num : keyboard_layout;
if (mode == 1)
key_table = keyboard_layout_caps;
else if (mode == 2)
key_table = keyboard_layout_shift;
if (flags & PDKeyboardFlags_BlendTop) {
LI::OnScreen(false);
LI::NewLayer();
LI::DrawRect(NVec2(0, 0), NVec2(400, 240),
Palladium::Color::RGBA(PDColor_FrameBg).changeA(150).toRGBA());
}
LI::OnScreen(true);
LI::NewLayer();
if (flags & PDKeyboardFlags_BlendBottom) {
LI::DrawRect(NVec2(0, 0), NVec2(320, 112),
Palladium::Color::RGBA(PDColor_FrameBg).changeA(150).toRGBA());
}
LI::DrawRect(NVec2(0, 112), NVec2(320, 128),
ThemeActive()->Get(PDColor_FrameBg));
LI::DrawRect(NVec2(0, 112), NVec2(320, 20),
ThemeActive()->Get(PDColor_Header));
LI::NewLayer();
LI::DrawText(
NVec2(5, 114),
ThemeActive()->Get(Palladium::ThemeActive()->AutoText(PDColor_Header)),
"> " + *typed_text);
int lr = LI::Layer();
for (auto const& it : key_table) {
NVec2 szs = it.size;
NVec2 pos = it.pos;
NVec2 txtdim = LI::GetTextDimensions(it.disp);
PDColor btn = PDColor_Button;
if (Palladium::Hid::IsEvent("cancel", Palladium::Hid::Up)) {
Palladium::Hid::Clear();
shared_data[0x05] = 1;
}
if (Palladium::Hid::IsEvent("touch", Palladium::Hid::Up) &&
UI7_InBox(Palladium::Hid::GetLastTouchPosition(), pos, szs)) {
if (mode == 2) // Request Disable Shift
shared_data[0x02] = 1;
if (it.action == 0)
shared_data[0x01] = it.disp[0];
else if (it.action == 1)
shared_data[0x02] = 1;
else if (it.action == 2)
shared_data[0x03] = 1;
else if (it.action == 3)
shared_data[0x04] = 1;
else if (it.action == 4)
shared_data[0x05] = 1;
else if (it.action == 5)
shared_data[0x06] = 1;
else if (it.action == 6)
shared_data[0x07] = 1;
else if (it.action == 7)
shared_data[0x08] = 1;
else if (it.action == 8)
shared_data[0x09] = 1;
} else if (Palladium::Hid::IsEvent("touch", Palladium::Hid::Held) &&
UI7_InBox(Palladium::Hid::GetTouchPosition(), it.pos, it.size)) {
btn = PDColor_ButtonHovered;
pos -= NVec2(1, 1);
szs += NVec2(2, 2);
}
NVec2 txtpos = NVec2(pos.x() + szs.x() * 0.5 - txtdim.x() * 0.5,
pos.y() + szs.y() * 0.5 - txtdim.y() * 0.5);
LI::Layer(lr);
LI::DrawRect(pos, szs, ThemeActive()->Get(btn));
LI::Layer(lr + 1);
LI::DrawText(txtpos,
ThemeActive()->Get(Palladium::ThemeActive()->AutoText(btn)),
it.disp);
}
if (ft3 > 5) {
if (flags & PDKeyboardFlags_LockControls) Palladium::Hid::Lock();
}
LI::SetTextScale(tmp_txt);
}
void Ovl_Keyboard::Logic() {
ft3++;
for (const auto& it : shared_data) {
if (it.first == 0x01) {
typed_text->push_back(it.second);
} else if (it.first == 0x02) {
// Shift
mode = (mode == 2) ? 0 : 2;
} else if (it.first == 0x03) {
if (typed_text->length() >= 1)
typed_text->erase(typed_text->begin() + typed_text->length() - 1);
} else if (it.first == 0x04) {
// Enter
} else if (it.first == 0x05) {
*typed_text = str_bak;
*state = PDKeyboardState_Cancel;
this->Kill();
} else if (it.first == 0x06) {
*state = PDKeyboardState_Confirm;
this->Kill();
} else if (it.first == 0x07) {
// this->typed_text += '\t'; // Tab
} else if (it.first == 0x08) {
// Caps
mode = (mode == 1) ? 0 : 1;
} else if (it.first == 0x09) {
typed_text->append(" "); // Space
}
}
shared_data.clear();
}
} // namespace Palladium

View File

@ -1,460 +0,0 @@
#include <filesystem>
#include <fstream>
#include <map>
#include <pd/ResultDecoder.hpp>
#include <pd/internal_db.hpp>
#include <sstream>
static std::map<int, std::string> modules = {
{0, "common"},
{1, "kernel"},
{2, "util"},
{3, "file server"},
{4, "loader server"},
{5, "tcb"},
{6, "os"},
{7, "dbg"},
{8, "dmnt"},
{9, "pdn"},
{10, "gsp"},
{11, "i2c"},
{12, "gpio"},
{13, "dd"},
{14, "codec"},
{15, "spi"},
{16, "pxi"},
{17, "fs"},
{18, "di"},
{19, "hid"},
{20, "cam"},
{21, "pi"},
{22, "pm"},
{23, "pm_low"},
{24, "fsi"},
{25, "srv"},
{26, "ndm"},
{27, "nwm"},
{28, "soc"},
{29, "ldr"},
{30, "acc"},
{31, "romfs"},
{32, "am"},
{33, "hio"},
{34, "updater"},
{35, "mic"},
{36, "fnd"},
{37, "mp"},
{38, "mpwl"},
{39, "ac"},
{40, "http"},
{41, "dsp"},
{42, "snd"},
{43, "dlp"},
{44, "hio_low"},
{45, "csnd"},
{46, "ssl"},
{47, "am_low"},
{48, "nex"},
{49, "friends"},
{50, "rdt"},
{51, "applet"},
{52, "nim"},
{53, "ptm"},
{54, "midi"},
{55, "mc"},
{56, "swc"},
{57, "fatfs"},
{58, "ngc"},
{59, "card"},
{60, "cardnor"},
{61, "sdmc"},
{62, "boss"},
{63, "dbm"},
{64, "config"},
{65, "ps"},
{66, "cec"},
{67, "ir"},
{68, "uds"},
{69, "pl"},
{70, "cup"},
{71, "gyroscope"},
{72, "mcu"},
{73, "ns"},
{74, "news"},
{75, "ro"},
{76, "gd"},
{77, "card spi"},
{78, "ec"},
{79, "web browser"},
{80, "test"},
{81, "enc"},
{82, "pia"},
{83, "act"},
{84, "vctl"},
{85, "olv"},
{86, "neia"},
{87, "npns"},
{90, "avd"},
{91, "l2b"},
{92, "mvd"},
{93, "nfc"},
{94, "uart"},
{95, "spm"},
{96, "qtm"},
{97, "nfp"},
{254, "application"},
};
static std::map<int, std::string> levels = {
{0, "Success"}, {1, "Info"}, {25, "Status"},
{26, "Temporary"}, {27, "Permanent"}, {28, "Usage"},
{29, "Reinitialize"}, {30, "Reset"}, {31, "Fatal"},
};
static std::map<int, std::string> summaries = {
{0, "Success"},
{1, "Nothing happened"},
{2, "Would block"},
{3, "Out of resource"},
{4, "Not found"},
{5, "Invalid state"},
{6, "Not supported"},
{7, "Invalid argument"},
{8, "Wrong argument"},
{9, "Canceled"},
{10, "Status changed"},
{11, "Internal"},
{63, "Invalid result value"},
};
static std::map<int, std::string> desccommon = {
{0, "Success"},
{1000, "Invalid selection"},
{1001, "Too large"},
{1002, "Not authorized"},
{1003, "Already done"},
{1004, "Invalid size"},
{1005, "Invalid enum value"},
{1006, "Invalid combination"},
{1007, "No data"},
{1008, "Busy"},
{1009, "Misaligned address"},
{1010, "Misaligned size"},
{1011, "Out of memory"},
{1012, "Not implemented"},
{1013, "Invalid address"},
{1014, "Invalid pointer"},
{1015, "Invalid handle"},
{1016, "Not initialized"},
{1017, "Already initialized"},
{1018, "Not found"},
{1019, "Cancel requested"},
{1020, "Already exists"},
{1021, "Out of range"},
{1022, "Timeout"},
{1023, "Invalid result value"},
};
static std::map<int, std::string> desckernel = {
{2, "Invalid memory permissions."},
};
static std::map<int, std::string> descos = {
{10, "Not enough memory."},
{26, "Session closed by remote."},
{47, "Invalid command header."},
};
// Need to Fix The Range based Values
static std::map<int, std::string> descfs = {
{101, "Archive not mounted or mount-point not found."},
{120, "Title or object not found."},
{141, "Gamecard not inserted."},
{230, "Invalid open flags or permissions."},
{391, "NCCH hash check failed."},
{302, "RSA or AES-MAC verification failed."},
{395, "RomFS or Savedata hash check failed."},
{630, "Command not allowed, or missing permissions."},
{702, "Invalid path."},
{761, "Incorrect ExeFS read size."},
{100, "[Media] not found."},
{180, "Exists already."},
{200, "Not enough space."},
{220, "Invalidated archive."},
{230, "Unacceptable or write protected."},
{340, "0x01"},
{360, "Bad format."},
{390, "Verification failure."},
{400, "0x01"},
{600, "Out of resources."},
{630, "Access denied."},
{661, "0x01"},
{700, "Invalid argument."},
{730, "Not initialized."},
{750, "Already initialized."},
{760, "Not supported."},
{780, "0x01"},
};
static std::map<int, std::string> descsrv = {
{5,
"Invalid string length (service name length is zero or longer than 8 "
"chars)."},
{6,
"Access to service denied (requested a service the application does "
"not have access to)."},
{7,
"String size does not match contents (service name contains unexpected "
"null byte)."},
};
static std::map<int, std::string> descnwm = {
{2,
"This error usually indicates the wifi chipset in the console is dying "
"or dead."},
};
static std::map<int, std::string> descam = {
{4, "Invalid ticket version."},
{32, "Empty CIA."},
{37, "Invalid NCCH."},
{39, "Invalid title version."},
{43, "Database doesn\"t exist, or it failed to open."},
{44, "Trying to uninstall system-app."},
{106,
"Invalid signature/CIA. Usually happens when developer UNITINFO is "
"enabled in Luma3DS."},
{393, "Invalid database."},
};
static std::map<int, std::string> deschttp = {
{105, "Request timed out."},
};
static std::map<int, std::string> descnim = {
{1,
"Invalid string IPC paramater (non null terminated at its indicated "
"length)."},
{12,
"Invalid country code returned by CFG module reading config save "
"0xB0000."},
{13,
"Zero string length console serial number or '000000000000000' "
"returned by CFG's SecureInfoGetSerialNo."},
{18,
"General data reading error of NIM's .dat files from its system save, "
"bad data or bad data lengths."},
{22,
"General invalid data or length of data returned from nintendo "
"servers. (Only applicable for some operations)"},
{25,
"IntegrityVerificationSeed is waiting on servers to be synced into "
"console. Can't processed with online services without sync being "
"completed first over IPC request."},
{26,
"Unavailable/unaccessable IntegrityVerificationSeed on Nintendo "
"servers. May happen if NIM is told to import "
"IntegrityVerificationSeed from servers at any time other than after "
"the successful System Transfer reboot."},
{27,
"Invalid country language code returned by CFG module reading config "
"save 0xA0002."},
{37,
"Service is in Standby Mode. (eShop ban? General service is down? "
"This caused by a server response flag on account information. "
"Account is not referring to NNID.)"},
{39, "HTTP Status non 200. (Only applicable for some operations)"},
{40, "General XML read/write error while processing Auto Delivery XMLs."},
{41,
"General XML read/write error while processing Auto Delivery XMLs. "
"(Stubbed virtual call was called)"},
{58,
"Invalid NPNS token returned by CFG module reading config save 0xF0006."},
{67, "HTTP Status 404 while trying to download a game's seed."},
{68, "HTTP Status 503 while trying to download a game's seed."},
};
static std::map<int, std::string> descmvd = {
{271, "Invalid configuration."},
};
static std::map<int, std::string> descqtm = {
{8, "Camera is already in use or busy."},
};
// Need to Fix The Range based Values
static std::map<int, std::string> descapplication = {
{0,
"The application raised an error. Please consult the application's "
"source code or ask the author for assistance with it."},
{1024, "0x01"},
};
namespace Palladium {
void ResultDecoder::Load(Result rescode) { this->m_rescode = rescode; }
void ResultDecoder::Load(std::string rescode) {
std::stringstream ss;
ss << rescode;
ss >> std::hex >> this->m_rescode;
}
std::string Palladium::ResultDecoder::GetCode() {
std::stringstream ss;
ss << std::hex << m_rescode;
std::string reshex(ss.str());
return reshex;
}
std::string ResultDecoder::GetLevel() {
std::string res = levels.at(this->GetLevelInt()) + " (" +
std::to_string(this->GetLevelInt()) + ")";
return res;
}
int ResultDecoder::GetLevelInt() { return R_LEVEL(m_rescode); }
std::string ResultDecoder::GetModule() {
std::string res = modules.at(this->GetModuleInt()) + " (" +
std::to_string(this->GetModuleInt()) + ")";
return res;
}
int ResultDecoder::GetModuleInt() { return R_MODULE(m_rescode); }
std::string ResultDecoder::GetDescription() {
std::string res = "Desc Not Implemented!";
switch (this->GetModuleInt()) {
case 0:
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
break;
case 1:
if ((desckernel.find(this->GetDescriptionInt()) == desckernel.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = desckernel.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 6:
if ((descos.find(this->GetDescriptionInt()) == descos.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descos.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 17:
if ((descfs.find(this->GetDescriptionInt()) == descfs.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descfs.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 25:
if ((descsrv.find(this->GetDescriptionInt()) == descsrv.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descsrv.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 27:
if ((descnwm.find(this->GetDescriptionInt()) == descnwm.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descnwm.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 32:
if ((descam.find(this->GetDescriptionInt()) == descam.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descam.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 40:
if ((deschttp.find(this->GetDescriptionInt()) == deschttp.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = deschttp.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 52:
if ((descnim.find(this->GetDescriptionInt()) == descnim.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descnim.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 92:
if ((descmvd.find(this->GetDescriptionInt()) == descmvd.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descmvd.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 96:
if ((descqtm.find(this->GetDescriptionInt()) == descqtm.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descqtm.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
case 254:
if ((descapplication.find(this->GetDescriptionInt()) ==
descapplication.end())) {
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
} else {
res = descapplication.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
}
break;
default:
res = desccommon.at(this->GetDescriptionInt()) + " (" +
std::to_string(this->GetDescriptionInt()) + ")";
break;
}
return res;
}
int ResultDecoder::GetDescriptionInt() { return R_DESCRIPTION(m_rescode); }
std::string ResultDecoder::GetSummary() {
std::string res = summaries.at(this->GetSummaryInt()) + " (" +
std::to_string(this->GetSummaryInt()) + ")";
return res;
}
void Palladium::ResultDecoder::WriteLog() {
std::string out_path = "sdmc:/Palladium/Apps/" + pdi_app_name + "/resdec";
std::filesystem::create_directories(out_path);
out_path += "/err_result_" + std::to_string(time(0)) + ".log";
std::ofstream out(out_path, std::ios::app);
out << "+-------------------\n";
out << "| Error: " << GetCode() << "\n";
out << "+-------------------\n";
out << "| Module: " << GetModule() << "\n";
out << "+-------------------\n";
out << "| Level: " << GetLevel() << "\n";
out << "+-------------------\n";
out << "| Summary: " << GetSummary() << "\n";
out << "+-------------------\n";
out << "| Description: " << GetDescription() << "\n";
out << "+-------------------\n";
out.close();
}
int ResultDecoder::GetSummaryInt() { return R_SUMMARY(m_rescode); }
} // namespace Palladium

View File

@ -1,124 +0,0 @@
#include <pd/external/stb_image.h>
#include <pd/Rubidium.hpp>
#include <pd/base/Color.hpp>
void d7_pixel_blend(Palladium::Rubidium* rb, int x, int y, unsigned int clr,
float blend) {
Palladium::Color::RGBA cl(clr);
cl.fade_to(Palladium::Color::RGBA(0.f, 0.f, 0.f, 1.f), blend);
rb->DrawPixel(x, y, cl.toRGBA());
}
namespace Palladium {
Rubidium::Rubidium(int w, int h) { image = Palladium::nimg(w, h); }
Rubidium::Rubidium() { image = Palladium::nimg(1, 1); }
Rubidium::~Rubidium() {
// Do nothing
}
void Rubidium::LoadFile(const std::string& path) {
int w, h, c;
uint8_t* dat = stbi_load(path.c_str(), &w, &h, &c, 4);
image = nimg(w, h);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int pos = (y * w + x) * 4;
image.pixel_buffer[pos + 0] = dat[pos + 0];
image.pixel_buffer[pos + 1] = dat[pos + 1];
image.pixel_buffer[pos + 2] = dat[pos + 2];
image.pixel_buffer[pos + 3] = dat[pos + 3];
}
}
stbi_image_free(dat);
}
void Rubidium::LoadNimg(const std::string& path) {
image = Palladium::NIMG_Load(path);
}
void Rubidium::DrawPixel(int x, int y, unsigned int color) {
if (x > image.width || x < 0 || y > image.height || y < 0) return;
Palladium::Color::RGBA splitter(color);
image.pixel_buffer[((y * image.width + x) * 4) + 0] = splitter.m_r;
image.pixel_buffer[((y * image.width + x) * 4) + 1] = splitter.m_g;
image.pixel_buffer[((y * image.width + x) * 4) + 2] = splitter.m_b;
image.pixel_buffer[((y * image.width + x) * 4) + 3] = splitter.m_a;
}
void Rubidium::DrawRect(int x, int y, int w, int h, unsigned int color, int t) {
DrawLine(x, y, x + w, y, color, t);
DrawLine(x, y, x, y + h, color, t);
DrawLine(x, y + h, x + w, y + h, color, t);
DrawLine(x + w, y, x + w, y + h, color, t);
}
void Rubidium::DrawRectSolid(int x, int y, int w, int h, unsigned int color) {
for (int ix = x; ix < x + w; ix++) {
for (int iy = y; iy < y + h; iy++) {
DrawPixel(ix, iy, color);
}
}
}
void Rubidium::DrawLine(int x1, int y1, int x2, int y2, unsigned int color,
int t) {
// Reference
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
int ht = t / 2;
while (true) {
for (int i = -ht; i <= ht; i++) {
if (dy <= dx) {
DrawPixel(x1, y1 + i, color);
} else {
DrawPixel(x1 + i, y1, color);
}
}
if (x1 == x2 && y1 == y2) break;
int e2 = err * 2;
if (e2 > -dy) {
err -= dy;
x1 += sx;
}
if (e2 < dx) {
err += dx;
y1 += sy;
}
}
}
void Rubidium::Flip(bool h, bool v) {
const nimg _bak = image;
if (h) {
for (int x = 0; x < image.width; x++) {
for (int y = 0; y < image.height; y++) {
int src = (y * image.width + x) * 4;
int dst = ((image.height - 1 - y) * image.width + x) * 4;
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
}
}
}
if (v) {
for (int x = 0; x < image.width; x++) {
for (int y = 0; y < image.height; y++) {
int src = (y * image.width + x) * 4;
int dst = (y * image.width + (image.width - 1 - x)) * 4;
image.pixel_buffer[src + 0] = _bak.pixel_buffer[dst + 0];
image.pixel_buffer[src + 1] = _bak.pixel_buffer[dst + 1];
image.pixel_buffer[src + 2] = _bak.pixel_buffer[dst + 2];
image.pixel_buffer[src + 3] = _bak.pixel_buffer[dst + 3];
}
}
}
}
} // namespace Palladium

View File

@ -1,51 +0,0 @@
#include <3ds.h>
#include <fstream>
#include <pd/Sheet.hpp>
namespace Palladium {
void Sheet::LoadT3X(const std::string& path) {
if (sheet_tex) {
C3D_TexDelete(sheet_tex);
delete sheet_tex;
sheet_tex = nullptr;
}
sheet_tex = new C3D_Tex;
std::fstream f(path, std::ios::in | std::ios::binary);
if (!f) {
delete sheet_tex;
sheet_tex = nullptr;
return;
}
f.seekg(0, std::ios::end);
std::vector<unsigned char> dat(f.tellg());
f.seekg(0, std::ios::beg);
f.read(reinterpret_cast<char*>(dat.data()), dat.size());
sheet =
Tex3DS_TextureImport(dat.data(), dat.size(), sheet_tex, nullptr, true);
C3D_TexSetFilter(sheet_tex, GPU_LINEAR, GPU_LINEAR);
f.close();
int st = Tex3DS_GetNumSubTextures(sheet);
sprites.resize(st);
for (int i = 0; i < st; i++) {
sprites[i] = Texture::New();
auto stex = Tex3DS_GetSubTexture(sheet, i);
sprites[i]->ExternalLoad(
sheet_tex, NVec2(stex->width, stex->height),
NVec4(stex->left, stex->top, stex->right, stex->bottom));
sprites[i]->AutoDelete(false);
}
}
Texture::Ref Sheet::Get(int idx) {
if (idx < 0 || idx >= (int)sprites.size()) return nullptr;
return sprites[idx];
}
Image::Ref Sheet::GetImage(int idx) {
if (idx < 0 || idx >= (int)sprites.size()) return nullptr;
Image::Ref img = Image::New();
img->Set(sprites[idx], sprites[idx]->GetUV());
return img;
}
} // namespace Palladium

View File

@ -1,129 +0,0 @@
#include <cstring>
#include <fstream>
#include <pd/Sound.hpp>
#include <pd/internal_db.hpp>
#include <string>
using std::string;
// Reference: http://yannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/
typedef struct _WavHeader {
char magic[4]; // "RIFF"
u32 totallength; // Total file length, minus 8.
char wavefmt[8]; // Should be "WAVEfmt "
u32 format; // 16 for PCM format
u16 pcm; // 1 for PCM format
u16 channels; // Channels
u32 frequency; // Sampling frequency
u32 bytes_per_second;
u16 bytes_by_capture;
u16 bits_per_sample;
char data[4]; // "data"
u32 bytes_in_data;
} WavHeader;
static_assert(sizeof(WavHeader) == 44, "WavHeader size is not 44 bytes.");
using namespace Palladium;
Sound::Sound(const string &path, int channel, bool toloop) {
if (pdi_is_ndsp) {
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
ndspSetOutputCount(2); // Num of buffers
// Reading wav file
std::fstream fp(path, std::ios::in | std::ios::binary);
if (!fp.is_open()) {
return;
}
WavHeader wavHeader;
fp.read(reinterpret_cast<char *>(&wavHeader), sizeof(WavHeader));
size_t read = fp.tellg();
if (read != sizeof(wavHeader)) {
// Short read.
fp.close();
return;
}
// Verify the header.
static const char RIFF_magic[4] = {'R', 'I', 'F', 'F'};
if (memcmp(wavHeader.magic, RIFF_magic, sizeof(wavHeader.magic)) != 0) {
// Incorrect magic number.
fp.close();
return;
}
if (wavHeader.totallength == 0 ||
(wavHeader.channels != 1 && wavHeader.channels != 2) ||
(wavHeader.bits_per_sample != 8 && wavHeader.bits_per_sample != 16)) {
// Unsupported WAV file.
fp.close();
return;
}
// Get the file size.
fp.seekg(0, std::ios::end);
dataSize = fp.tellg();
dataSize -= sizeof(WavHeader);
// Allocating and reading samples
data = static_cast<u8 *>(linearAlloc(dataSize));
fp.seekg(44, std::ios::beg);
fp.read(reinterpret_cast<char *>(data), dataSize);
fp.close();
dataSize /= 2; // FIXME: 16-bit or stereo?
// Find the right format
u16 ndspFormat;
if (wavHeader.bits_per_sample == 8) {
ndspFormat = (wavHeader.channels == 1) ? NDSP_FORMAT_MONO_PCM8
: NDSP_FORMAT_STEREO_PCM8;
} else {
ndspFormat = (wavHeader.channels == 1) ? NDSP_FORMAT_MONO_PCM16
: NDSP_FORMAT_STEREO_PCM16;
}
ndspChnReset(channel);
ndspChnSetInterp(channel, NDSP_INTERP_NONE);
ndspChnSetRate(channel, float(wavHeader.frequency));
ndspChnSetFormat(channel, ndspFormat);
// Create and play a wav buffer
memset(&waveBuf, 0, sizeof(waveBuf));
waveBuf.data_vaddr = reinterpret_cast<u32 *>(data);
waveBuf.nsamples = dataSize / (wavHeader.bits_per_sample >> 3);
waveBuf.looping = toloop;
waveBuf.status = NDSP_WBUF_FREE;
chnl = channel;
}
}
Sound::~Sound() {
if (pdi_is_ndsp) {
waveBuf.data_vaddr = 0;
waveBuf.nsamples = 0;
waveBuf.looping = false;
waveBuf.status = 0;
ndspChnWaveBufClear(chnl);
if (data) {
linearFree(data);
}
}
}
void Sound::Play() {
if (pdi_is_ndsp) {
if (!data) return;
DSP_FlushDataCache(data, dataSize);
ndspChnWaveBufAdd(chnl, &waveBuf);
}
}
void Sound::Stop() {
if (pdi_is_ndsp) {
if (!data) return;
ndspChnWaveBufClear(chnl);
}
}

View File

@ -1,53 +0,0 @@
#include <pd/Sprite.hpp>
/*
void Palladium::Sprite::FromSheet(Palladium::Sheet::Ref sheet, size_t index) {
C2D_SpriteFromSheet(&this->sprite, sheet->Get(), index);
}
bool Palladium::Sprite::Draw() {
// Patch Depth before draw
sprite.params.depth = 0.5;
return C2D_DrawSprite(&this->sprite);
}
void Palladium::Sprite::SetCenter(float x, float y) {
C2D_SpriteSetCenter(&this->sprite, x, y);
}
void Palladium::Sprite::SetPos(float x, float y) {
C2D_SpriteSetPos(&this->sprite, x, y);
}
void Palladium::Sprite::SetRotation(float rotation) {
C2D_SpriteSetRotation(&this->sprite, rotation);
}
void Palladium::Sprite::Rotate(float speed) {
C2D_SpriteRotateDegrees(&this->sprite, speed);
}
float Palladium::Sprite::GetHeight() { return GetSize().x; }
float Palladium::Sprite::GetWidth() { return GetSize().y; }
float Palladium::Sprite::GetPosX() { return GetPos().x; }
float Palladium::Sprite::GetPosY() { return GetPos().y; }
NVec2 Palladium::Sprite::GetPos() {
return NVec2(this->sprite.params.pos.x, this->sprite.params.pos.y);
}
NVec2 Palladium::Sprite::GetSize() {
return NVec2(this->sprite.params.pos.w, this->sprite.params.pos.h);
}
void Palladium::Sprite::SetPos(NVec2 pos) {
C2D_SpriteSetPos(&this->sprite, pos.x, pos.y);
}
void Palladium::Sprite::SetScale(NVec2 scale) {
C2D_SpriteScale(&this->sprite, scale.x, scale.y);
}
void Palladium::Sprite::SetRotCenter(NVec2 percentage) {
C2D_SpriteSetCenter(&this->sprite, percentage.x, percentage.y);
}
void Palladium::Sprite::FromImage(Palladium::Image::Ref img) {
// C2D_SpriteFromImage(&this->sprite, img->Get());
}
void Palladium::Sprite::SetScale(float x, float y) {
C2D_SpriteScale(&this->sprite, x, y);
}*/

View File

@ -1,22 +0,0 @@
#include <memory>
#include <pd/Tasks.hpp>
#include <thread>
#include <vector>
static std::vector<std::shared_ptr<std::thread>> threads;
int Palladium::Tasks::Create(std::function<void()> fun) {
auto thrd = std::make_shared<std::thread>(fun);
threads.push_back(thrd);
return threads.size();
}
void Palladium::Tasks::DestroyAll() {
for (auto& it : threads) {
if (it && it->joinable()) {
it->join();
}
}
// Delete Pointers
threads.clear();
}

View File

@ -1,243 +0,0 @@
#include <pd/external/stb_image.h>
#include <pd/external/stb_image_write.h>
#include <pd/Error.hpp>
#include <pd/Texture.hpp>
#include <pd/internal_db.hpp>
namespace pdi {
static bool single_bit(unsigned int v) { return v && !(v & (v - 1)); }
static u32 get_pow2(u32 v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return (v >= 64 ? v : 64);
}
static void RGB24toRGBA32(std::vector<uint8_t> &out,
const std::vector<uint8_t> &in, const int &w,
const int &h) {
// Converts RGB24 to RGBA32
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int src = (y * w + x) * 3;
int dst = (y * w + x) * 4;
out[dst + 0] = in[src + 0];
out[dst + 1] = in[src + 1];
out[dst + 2] = in[src + 2];
out[dst + 3] = 255;
}
}
}
} // namespace pdi
namespace Palladium {
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
if (type == Texture::RGBA32)
return GPU_RGBA8;
else if (type == Texture::RGB24)
return GPU_RGB8;
else if (type == Texture::A8)
return GPU_A8;
return GPU_RGBA8; // Default
}
int GetBPP(Texture::Type type) {
if (type == Texture::RGBA32)
return 4;
else if (type == Texture::RGB24)
return 3;
else if (type == Texture::A8)
return 1;
return 0; // Error
}
void Texture::MakeTex(std::vector<unsigned char> &buf, int w, int h, Type type,
Filter filter) {
if (!tex) {
return;
}
// Don't check here as check done before
int bpp = GetBPP(type);
if (bpp == 4) {
//// RGBA -> Abgr
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pos = (x + y * w) * bpp;
auto r = buf[pos + 0];
auto g = buf[pos + 1];
auto b = buf[pos + 2];
auto a = buf[pos + 3];
buf[pos + 0] = a;
buf[pos + 1] = b;
buf[pos + 2] = g;
buf[pos + 3] = r;
}
}
} else if (bpp == 3) {
// RGBA -> Abgr
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pos = (x + y * w) * bpp;
auto r = buf[pos + 0];
auto g = buf[pos + 1];
auto b = buf[pos + 2];
buf[pos + 0] = b;
buf[pos + 1] = g;
buf[pos + 2] = r;
}
}
}
NVec2 tex_size(w, h);
// Pow2
if (!pdi::single_bit(w)) tex_size.x() = pdi::get_pow2((unsigned int)w);
if (!pdi::single_bit(h)) tex_size.y() = pdi::get_pow2((unsigned int)h);
this->img_size.x() = (u16)w;
this->img_size.y() = (u16)h;
this->uvs.x() = 0.0f;
this->uvs.y() = 1.0f;
this->uvs.z() = ((float)w / (float)tex_size.x());
this->uvs.w() = 1.0 - ((float)h / (float)tex_size.y());
// Texture Setup
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
auto tex_fmt = GetTexFmt(type);
C3D_TexInit(tex, (u16)tex_size.x(), (u16)tex_size.y(), tex_fmt);
C3D_TexSetFilter(tex, fltr, fltr);
memset(tex->data, 0, tex->size);
if (bpp == 3 || bpp == 4) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) |
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
bpp;
int src_pos = (y * w + x) * bpp;
memcpy(&((unsigned char *)tex->data)[dst_pos], &buf[src_pos], bpp);
}
}
C3D_TexFlush(tex);
} else if (bpp == 1) {
C3D_TexLoadImage(tex, buf.data(), GPU_TEXFACE_2D, 0);
}
tex->border = 0x00000000;
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
}
void Texture::LoadFile(const std::string &path) {
Palladium::Ftrace::ScopedTrace st("texldr", path);
int w, h, c = 0;
unsigned char *image = stbi_load(path.c_str(), &w, &h, &c, 4);
if (image == nullptr) {
//_pdi_logger()->Write("Failed to Load Image: " + path);
return;
}
// Size/Fmt Check
if (w > 1024 || h > 1024) {
// Reason: Image to Large
//_pdi_logger()->Write("Image too Large!");
stbi_image_free(image);
return;
}
std::vector<unsigned char> wimg;
if (c == 3) {
//_pdi_logger()->Write("Convert Image to RGBA");
stbi_image_free(image);
image = stbi_load(path.c_str(), &w, &h, &c, 3);
wimg.resize(w * h * 4);
pdi::RGB24toRGBA32(
wimg, std::vector<unsigned char>(image, image + (w * h * 3)), w, h);
} else {
wimg.assign(&image[0], &image[(w * h * 4) - 1]);
stbi_image_free(image);
}
// Create C2D_Image
tex = new C3D_Tex;
MakeTex(wimg, w, h);
}
void Texture::LoadFromMemory(const std::vector<unsigned char> &data) {
int w, h, c = 0;
unsigned char *image =
stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 4);
if (image == nullptr) {
//_pdi_logger()->Write("Failed to Load Image: " + path);
return;
}
// Size/Fmt Check
if (w > 1024 || h > 1024) {
// Reason: Image to Large
//_pdi_logger()->Write("Image too Large!");
stbi_image_free(image);
return;
}
std::vector<unsigned char> wimg;
if (c == 3) {
//_pdi_logger()->Write("Convert Image to RGBA");
stbi_image_free(image);
image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 3);
wimg.resize(w * h * 4);
pdi::RGB24toRGBA32(
wimg, std::vector<unsigned char>(image, image + (w * h * 3)), w, h);
} else {
wimg.assign(&image[0], &image[(w * h * 4) - 1]);
stbi_image_free(image);
}
// Create C2D_Image
tex = new C3D_Tex;
MakeTex(wimg, w, h);
}
NVec2 Texture::GetTexSize() {
if (!tex) return NVec2();
return NVec2(tex->width, tex->height);
}
void Texture::LoadPixels(const std::vector<unsigned char> &data, int w, int h,
Type type, Filter filter) {
Delete();
int bpp = GetBPP(type);
Palladium::InlineAssert(bpp, "Invalid Type");
if (w * h * bpp != (int)data.size()) {
return;
}
if (w > 1024 || h > 1024) {
// Reason: Image to Large
//_pdi_logger()->Write("Image too Large!");
return;
}
tex = new C3D_Tex;
std::vector<unsigned char> wimg(data);
MakeTex(wimg, w, h, type, filter);
}
void Texture::ExternalLoad(C3D_Tex *tex, NVec2 rszs, NVec4 uvs) {
Delete();
this->tex = tex;
this->img_size = rszs;
this->uvs = uvs;
}
void Texture::Delete() {
if (!ad) return;
if (tex) {
C3D_TexDelete(tex);
delete tex;
tex = nullptr;
img_size = NVec2();
this->uvs.x() = 0.0f;
this->uvs.y() = 1.0f;
this->uvs.z() = 1.0f;
this->uvs.w() = 0.0f;
}
}
} // namespace Palladium

View File

@ -1,138 +0,0 @@
#include <filesystem>
#include <pd/Hid.hpp>
#include <pd/Message.hpp>
#include <pd/ThemeEditor.hpp>
#include <pd/UI7.hpp>
std::map<PDColor, std::string> color_names = {
{PDColor_Background, "Background"},
{PDColor_Button, "Button"},
{PDColor_ButtonActive, "ButtonActive"},
{PDColor_ButtonDisabled, "ButtonDisabled"},
{PDColor_ButtonHovered, "ButtonHovered"},
{PDColor_Checkmark, "Checkmark"},
{PDColor_FrameBg, "FrameBg"},
{PDColor_FrameBgHovered, "FrameBgHovered"},
{PDColor_Header, "Header"},
{PDColor_List0, "List0"},
{PDColor_List1, "List1"},
{PDColor_MessageBackground, "Message Background"},
{PDColor_Progressbar, "Progressbar"},
{PDColor_Selector, "Selector"},
{PDColor_SelectorFade, "SelectorFade"},
{PDColor_Text2, "Text Light"},
{PDColor_Text, "Text Dark"},
{PDColor_TextDisabled, "Text Disabled"},
};
Palladium::ThemeEditor::ThemeEditor() {
// Backup active Theme and create New one to edit
temp_theme = Palladium::ThemeActive();
edit_theme = Palladium::Theme::New();
edit_theme->CopyOther(temp_theme);
Palladium::ThemeSet(edit_theme);
}
Palladium::ThemeEditor::~ThemeEditor() {
// Set Back to Acrive Theme
Palladium::ThemeSet(temp_theme);
}
void Palladium::ThemeEditor::Update() {
// Rendering / UI Logic
Palladium::LI::OnScreen(false);
if (UI7::BeginMenu("Palladium -> Theme Editor")) {
UI7::Label("Sample Text");
UI7::Checkbox("Checkbox", cm);
UI7::InputText("Input Text", inpt, "Input Text");
UI7::Button("Button");
UI7::Progressbar(0.5f);
UI7::ColorSelector("Color Selector",
edit_theme->GetTableRef()[PDColor_Progressbar]);
UI7::EndMenu();
}
Palladium::LI::OnScreen(true);
if (UI7::BeginMenu("Theme", NVec2(), UI7MenuFlags_Scrolling)) {
if (menu == 0) {
if (UI7::Button("Create New")) {
menu = 1;
edit_theme->Default();
} else if (UI7::Button("Edit Current")) {
menu = 1;
} else if (UI7::Button("Select Theme")) {
menu = 2;
theme_list.clear();
for (const auto& it : std::filesystem::directory_iterator(
Palladium::GetAppDirectory() + "/themes")) {
theme_list.push_back(it.path().filename().string());
}
}
} else if (menu == 1) {
if (UI7::Button("Go back")) {
edit_theme->CopyOther(temp_theme);
menu = 0;
} else if (UI7::Button("Save")) {
Palladium::AddOvl(std::make_unique<Ovl_Keyboard>(kbd_text, kbd_state,
"<name>.theme"));
}
for (auto& it : color_names) {
UI7::ColorSelector(it.second, edit_theme->GetTableRef()[it.first]);
}
} else if (menu == 2) {
if (UI7::Button("Go back")) {
menu = 0;
}
for (auto& it : theme_list) {
if (UI7::Button(it)) {
edit_theme->Load(Palladium::GetAppDirectory() + "/themes/" + it);
menu = 1;
}
UI7::SameLine();
if (UI7::Button("Make Current")) {
edit_theme->Load(Palladium::GetAppDirectory() + "/themes/" + it);
temp_theme->CopyOther(edit_theme);
menu = 0;
}
UI7::SameLine();
if (UI7::Button("Delete")) {
if (std::string(it) != "Palladium.theme") {
std::filesystem::remove(Palladium::GetAppDirectory() + "/themes/" +
it);
theme_list.clear();
for (const auto& it : std::filesystem::directory_iterator(
Palladium::GetAppDirectory() + "/themes")) {
theme_list.push_back(it.path().filename().string());
}
} else {
Palladium::PushMessage("ThemeEditor",
"Cannot Delete\nPalladium.theme!");
}
}
}
}
UI7::EndMenu();
}
// Standart Logic
if (kbd_state) {
if (kbd_state == PDKeyboardState_Confirm) {
auto path =
Palladium::GetAppDirectory() + "/themes/" + kbd_text + ".theme";
kbd_text = "";
if (std::filesystem::exists(path)) {
// Prompt Override
return;
}
edit_theme->Save(path);
}
kbd_state = PDKeyboardState_None;
}
if (Hid::IsEvent("cancel", Hid::Down)) {
if (menu == 0) {
Palladium::Scene::Back();
} else {
if (menu == 1) edit_theme->CopyOther(temp_theme);
menu = 0;
}
}
}

View File

@ -1,30 +0,0 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <memory>
#include <pd/Time.hpp>
#include <string>
std::string Palladium::FormatString(std::string fmt_str, ...) {
va_list ap;
char *fp = NULL;
va_start(ap, fmt_str);
vasprintf(&fp, fmt_str.c_str(), ap);
va_end(ap);
std::unique_ptr<char, decltype(free) *> formatted(fp, free);
return std::string(formatted.get());
}
std::string Palladium::GetTimeStr(void) {
time_t unixTime;
struct tm timeStruct;
time(&unixTime);
localtime_r(&unixTime, &timeStruct);
return FormatString("%04i-%02i-%02i_%02i-%02i-%02i",
timeStruct.tm_year + 1900, timeStruct.tm_mon + 1,
timeStruct.tm_mday, timeStruct.tm_hour, timeStruct.tm_min,
timeStruct.tm_sec);
}

View File

@ -1,31 +0,0 @@
#include <pd/Timer.hpp>
// Ticks per MSEC
#define TPMS 268111.856
namespace Palladium {
Timer::Timer(bool autostart) {
if (autostart) is_running = true;
last = svcGetSystemTick();
current = last;
}
void Timer::Reset() {
last = svcGetSystemTick();
current = last;
}
void Timer::Tick() {
if (is_running) current = svcGetSystemTick();
}
void Timer::Pause() { is_running = false; }
void Timer::Resume() { is_running = true; }
bool Timer::Running() { return is_running; }
float Timer::Get() { return (float)((current - last) / TPMS); }
float Timer::GetLive() { return (float)((svcGetSystemTick() - last) / TPMS); }
} // namespace Palladium

File diff suppressed because it is too large Load Diff

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