From 481ccd0cf954638bc1bc9f61851777431315a1ea Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 23 Jan 2023 10:19:18 -0300 Subject: [PATCH 1/7] feat: load fileXio and iomanX iop drivers --- engine/inc/irx/irx_loader.hpp | 1 + engine/src/irx/fileXio.irx-em | 2 ++ engine/src/irx/iomanX.irx-em | 2 ++ engine/src/irx/irx_loader.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 29 insertions(+) create mode 100644 engine/src/irx/fileXio.irx-em create mode 100644 engine/src/irx/iomanX.irx-em diff --git a/engine/inc/irx/irx_loader.hpp b/engine/inc/irx/irx_loader.hpp index a9aa19f..d0dbcac 100644 --- a/engine/inc/irx/irx_loader.hpp +++ b/engine/inc/irx/irx_loader.hpp @@ -27,6 +27,7 @@ class IrxLoader { void loadSio2man(const bool& verbose); void loadPadman(const bool& verbose); void loadLibsd(const bool& verbose); + void loadPOSIX(const bool& verbose); void loadUsbModules(const bool& verbose); void loadAudsrv(const bool& verbose); diff --git a/engine/src/irx/fileXio.irx-em b/engine/src/irx/fileXio.irx-em new file mode 100644 index 0000000..fbdfe29 --- /dev/null +++ b/engine/src/irx/fileXio.irx-em @@ -0,0 +1,2 @@ +$PS2SDK/iop/irx/fileXio.irx +fileXio_irx diff --git a/engine/src/irx/iomanX.irx-em b/engine/src/irx/iomanX.irx-em new file mode 100644 index 0000000..d83e4fc --- /dev/null +++ b/engine/src/irx/iomanX.irx-em @@ -0,0 +1,2 @@ +$PS2SDK/iop/irx/iomanX.irx +iomanX_irx diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index c36f9b8..ae7bca9 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -33,6 +33,12 @@ extern int size_audsrv_irx; extern u8 libsd_irx[]; extern int size_libsd_irx; +extern u8 fileXio_irx_irx[]; +extern int size_fileXio_irx_irx; + +extern u8 iomanX_irx_irx[]; +extern int size_iomanX_irx_irx; + extern u8 bdm_irx[]; extern int size_bdm_irx; @@ -116,6 +122,24 @@ void IrxLoader::loadLibsd(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Libsd loaded!"); } +void IrxLoader::loadPOSIX(const bool& verbose) { + if (verbose) TYRA_LOG("IRX: Loading fileXio..."); + + int ret; + SifExecModuleBuffer(&fileXio_irx, size_fileXio_irx, 0, nullptr, &ret); + TYRA_ASSERT(ret >= 0, "Failed to load module: fileXio_irx"); + + if (verbose) TYRA_LOG("IRX: fileXio_irx loaded!"); + + if (verbose) TYRA_LOG("IRX: Loading iomanX..."); + + int ret; + SifExecModuleBuffer(&iomanX_irx, size_iomanX_irx, 0, nullptr, &ret); + TYRA_ASSERT(ret >= 0, "Failed to load module: iomanX_irx"); + + if (verbose) TYRA_LOG("IRX: iomanX loaded!"); +} + void IrxLoader::loadUsbModules(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading usb modules..."); From d196290a3fa5e915b0be30fe8406c2bc60e3fcca Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 23 Jan 2023 10:24:24 -0300 Subject: [PATCH 2/7] fix: extern variables names --- engine/src/irx/irx_loader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index ae7bca9..b3770ea 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -33,11 +33,11 @@ extern int size_audsrv_irx; extern u8 libsd_irx[]; extern int size_libsd_irx; -extern u8 fileXio_irx_irx[]; -extern int size_fileXio_irx_irx; +extern u8 fileXio_irx[]; +extern int size_fileXio_irx; -extern u8 iomanX_irx_irx[]; -extern int size_iomanX_irx_irx; +extern u8 iomanX_irx[]; +extern int size_iomanX_irx; extern u8 bdm_irx[]; extern int size_bdm_irx; From f546604ba3c76d750cea0e6f362fcfe3d660e7a7 Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 23 Jan 2023 10:27:55 -0300 Subject: [PATCH 3/7] fix: redefinition of ret --- engine/src/irx/irx_loader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index b3770ea..2cb7d59 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -133,7 +133,6 @@ void IrxLoader::loadPOSIX(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading iomanX..."); - int ret; SifExecModuleBuffer(&iomanX_irx, size_iomanX_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: iomanX_irx"); From 17d2d93d45b9d000e514a86cc019b03ffa593b4d Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 23 Jan 2023 14:54:20 -0300 Subject: [PATCH 4/7] fix: irx loading order --- engine/src/irx/irx_loader.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index 2cb7d59..de37d73 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -76,6 +76,7 @@ void IrxLoader::loadAll(const bool& withUsb, const bool& isLoggingToFile) { return; } + loadPOSIX(!isLoggingToFile); loadSio2man(!isLoggingToFile); loadPadman(!isLoggingToFile); loadLibsd(!isLoggingToFile); @@ -123,20 +124,21 @@ void IrxLoader::loadLibsd(const bool& verbose) { } void IrxLoader::loadPOSIX(const bool& verbose) { - if (verbose) TYRA_LOG("IRX: Loading fileXio..."); - int ret; - SifExecModuleBuffer(&fileXio_irx, size_fileXio_irx, 0, nullptr, &ret); - TYRA_ASSERT(ret >= 0, "Failed to load module: fileXio_irx"); - - if (verbose) TYRA_LOG("IRX: fileXio_irx loaded!"); - if (verbose) TYRA_LOG("IRX: Loading iomanX..."); SifExecModuleBuffer(&iomanX_irx, size_iomanX_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: iomanX_irx"); if (verbose) TYRA_LOG("IRX: iomanX loaded!"); + + if (verbose) TYRA_LOG("IRX: Loading fileXio..."); + + SifExecModuleBuffer(&fileXio_irx, size_fileXio_irx, 0, nullptr, &ret); + TYRA_ASSERT(ret >= 0, "Failed to load module: fileXio_irx"); + + if (verbose) TYRA_LOG("IRX: fileXio_irx loaded!"); + } void IrxLoader::loadUsbModules(const bool& verbose) { From 200a68e2194054956416fa62913fa9cde15aa820 Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 24 Jul 2023 14:43:21 -0300 Subject: [PATCH 5/7] fix: accelerated audio --- engine/src/audio/audio_song.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/src/audio/audio_song.cpp b/engine/src/audio/audio_song.cpp index 25a6e11..b05f198 100644 --- a/engine/src/audio/audio_song.cpp +++ b/engine/src/audio/audio_song.cpp @@ -148,6 +148,7 @@ void AudioSong::work() { if (chunkReadStatus > 0) { WaitSema(fillbufferSema); // wait until previous chunk wasn't finished + audsrv_wait_audio(chunkReadStatus); audsrv_play_audio(chunk, chunkReadStatus); for (u32 i = 0; i < getListenersCount(); i++) songListeners[i]->listener->onAudioTick(); From 1e046d9dda6b4c823abbf6e83e3b334d7248b85a Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sat, 11 Nov 2023 12:32:04 -0300 Subject: [PATCH 6/7] merge: merge changes from upstream master --- Makefile.base | 2 +- README.MD | 1 + docs/install/README.MD | 13 +- engine/inc/debug/debug.hpp | 37 ++- engine/inc/info/version.hpp | 2 +- .../inc/renderer/core/2d/renderer_core_2d.hpp | 4 + engine/inc/renderer/core/2d/sprite/sprite.hpp | 2 +- engine/src/debug/debug.cpp | 21 +- engine/src/irx/irx_loader.cpp | 42 +-- .../src/renderer/core/2d/renderer_core_2d.cpp | 16 +- engine/src/renderer/core/2d/sprite/sprite.cpp | 1 + tutorials/10-sprite-sheet/Makefile | 24 ++ tutorials/10-sprite-sheet/bin/.gitignore | 4 + tutorials/10-sprite-sheet/inc/font_sprite.hpp | 37 +++ tutorials/10-sprite-sheet/inc/tutorial_10.hpp | 45 +++ tutorials/10-sprite-sheet/obj/.gitignore | 4 + tutorials/10-sprite-sheet/res/.gitignore | 4 + tutorials/10-sprite-sheet/run.ps1 | 4 + tutorials/10-sprite-sheet/src/font_sprite.cpp | 109 +++++++ tutorials/10-sprite-sheet/src/main.cpp | 26 ++ tutorials/10-sprite-sheet/src/tutorial_10.cpp | 290 ++++++++++++++++++ 21 files changed, 619 insertions(+), 69 deletions(-) create mode 100644 tutorials/10-sprite-sheet/Makefile create mode 100644 tutorials/10-sprite-sheet/bin/.gitignore create mode 100644 tutorials/10-sprite-sheet/inc/font_sprite.hpp create mode 100644 tutorials/10-sprite-sheet/inc/tutorial_10.hpp create mode 100644 tutorials/10-sprite-sheet/obj/.gitignore create mode 100644 tutorials/10-sprite-sheet/res/.gitignore create mode 100644 tutorials/10-sprite-sheet/run.ps1 create mode 100644 tutorials/10-sprite-sheet/src/font_sprite.cpp create mode 100644 tutorials/10-sprite-sheet/src/main.cpp create mode 100644 tutorials/10-sprite-sheet/src/tutorial_10.cpp diff --git a/Makefile.base b/Makefile.base index e31c0b7..653ac9a 100644 --- a/Makefile.base +++ b/Makefile.base @@ -16,7 +16,7 @@ IRXEMBEDDEDEXT := irx-em CFLAGS += -D_EE -Wall -O3 LINKFLAGS += -O3 -Wl,-zmax-page-size=128 ASFLAGS += -O3 -LIB += -lstdc++ -ldma -lpacket2 -lgraph -ldraw -lmath3d -lpng -lz -lpad -laudsrv -lpatches -lcdvd +LIB += -lstdc++ -ldma -lpacket2 -lgraph -ldraw -lmath3d -lpng -ldebug -lz -lpad -laudsrv -lpatches -lcdvd INC += -I$(PS2DEV)/ps2sdk/ee/include -I$(PS2DEV)/ps2sdk/common/include -I$(PS2DEV)/ps2sdk/ports/include #--------------------------------------------------------------------------------- diff --git a/README.MD b/README.MD index 673dc28..10a3736 100644 --- a/README.MD +++ b/README.MD @@ -121,6 +121,7 @@ List of games developed with Tyra. If you created one, please contact me - I will add it to the list :) * [Tyracraft](https://github.com/Wellinator/tyracraft) by [Wellinator](https://github.com/Wellinator) +* [Game with car](https://github.com/freebytego/gwc-ps2) by [freebytego](https://github.com/freebytego) * [Rock, paper, scissors](https://github.com/GuidoDQR/my-ps2-game) by [GuidoDQR](https://github.com/GuidoDQR) * [TyraTale](https://github.com/Br4k2n/TyraTale) by [Br4k2n](https://github.com/Br4k2n) diff --git a/docs/install/README.MD b/docs/install/README.MD index f7b4646..e6decdb 100644 --- a/docs/install/README.MD +++ b/docs/install/README.MD @@ -17,9 +17,10 @@ docker pull h4570/tyra git clone https://github.com/h4570/tyra.git ``` -3. Open `VSCode` and open previously cloned directory. -4. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/` -5. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2. -6. Click `CTRL+SHIFT+P`, type `Tasks: Run task` and run `Start docker container` - Repeat this step every time you want to start working with Tyra (every reboot) -7. Click `CTRL+SHIFT+P`, type `Tasks: Run build task` -8. Tyra should automatically compile engine, `demo` game and run `PCSX2`. If you want to compile & run tutorials, please change `buildDirectory` in `settings.json` to example `tutorials/01-hello` +3. Download the [assets.zip](https://github.com/h4570/tyra/releases) file and unzip it into the tyra directory +4. Open `VSCode` and open previously cloned directory. +5. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/` +6. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2. +7. Click `CTRL+SHIFT+P`, type `Tasks: Run task` and run `Start docker container` - Repeat this step every time you want to start working with Tyra (every reboot) +8. Click `CTRL+SHIFT+P`, type `Tasks: Run build task` +9. Tyra should automatically compile engine, `demo` game and run `PCSX2`. If you want to compile & run tutorials, please change `buildDirectory` in `settings.json` to example `tutorials/01-hello` diff --git a/engine/inc/debug/debug.hpp b/engine/inc/debug/debug.hpp index d919b0e..a8d3e97 100644 --- a/engine/inc/debug/debug.hpp +++ b/engine/inc/debug/debug.hpp @@ -20,6 +20,7 @@ #else // IF Debug #include +#include #include #include #include @@ -48,9 +49,7 @@ class TyraDebug { (void)expander{0, (void(ss << std::forward(args)), 0)...}; if (Tyra::Info::writeLogsToFile) { - auto* logFile = getLogFile(); - *logFile << ss.str(); - logFile->flush(); + writeInLogFile(&ss); } else { printf("%s", ss.str().c_str()); } @@ -65,9 +64,7 @@ class TyraDebug { ss1 << "|\n"; if (Tyra::Info::writeLogsToFile) { - auto* logFile = getLogFile(); - *logFile << ss1.str(); - logFile->flush(); + writeInLogFile(&ss1); } else { printf("%s", ss1.str().c_str()); } @@ -80,20 +77,22 @@ class TyraDebug { ss2 << "====================================\n\n"; if (Tyra::Info::writeLogsToFile) { - auto* logFile = getLogFile(); - *logFile << ss2.str(); - logFile->flush(); + writeInLogFile(&ss2); } else { printf("%s", ss2.str().c_str()); } + init_scr(); for (;;) { + scr_setXY(20, 10); + scr_printf(ss1.str().c_str()); + writeAssertLinesInScreen(args...); + scr_printf(ss2.str().c_str()); } } private: - static std::unique_ptr logFile; - static std::ofstream* getLogFile(); + static void writeInLogFile(std::stringstream* ss); template static void writeAssertLines(Arg&& arg, Args&&... args) { @@ -105,13 +104,23 @@ class TyraDebug { 0, (void(ss << "| " << std::forward(args) << "\n"), 0)...}; if (Tyra::Info::writeLogsToFile) { - auto* logfile = getLogFile(); - *logfile << ss.str(); - logFile->flush(); + writeInLogFile(&ss); } else { printf("%s", ss.str().c_str()); } } + + template + static void writeAssertLinesInScreen(Arg&& arg, Args&&... args) { + std::stringstream ss; + + ss << "| " << std::forward(arg) << "\n"; + using expander = int[]; + (void)expander{ + 0, (void(ss << "| " << std::forward(args) << "\n"), 0)...}; + + scr_printf(ss.str().c_str()); + } }; #endif // NDEBUG \ No newline at end of file diff --git a/engine/inc/info/version.hpp b/engine/inc/info/version.hpp index d4be1d3..e5c53fc 100644 --- a/engine/inc/info/version.hpp +++ b/engine/inc/info/version.hpp @@ -21,7 +21,7 @@ class Version { ~Version() {} static const u8 major = 2; - static const u8 minor = 1; + static const u8 minor = 2; static const u8 patch = 0; static std::string toString() { diff --git a/engine/inc/renderer/core/2d/renderer_core_2d.hpp b/engine/inc/renderer/core/2d/renderer_core_2d.hpp index aaa1d4d..177687f 100644 --- a/engine/inc/renderer/core/2d/renderer_core_2d.hpp +++ b/engine/inc/renderer/core/2d/renderer_core_2d.hpp @@ -13,6 +13,7 @@ #include "debug/debug.hpp" #include "renderer/core/2d/sprite/sprite.hpp" #include "renderer/core/texture/renderer_core_texture_buffers.hpp" +#include "renderer/3d/pipeline/shared/pipeline_texture_mapping_type.hpp" #include "renderer/core/texture/models/texture.hpp" #include "renderer/renderer_settings.hpp" #include @@ -30,6 +31,9 @@ class RendererCore2D { void render(const Sprite& sprite, const RendererCoreTextureBuffers& texBuffers, Texture* texture); + void setTextureMappingType( + const PipelineTextureMappingType textureMappingType); + private: void setPrim(); void setLod(); diff --git a/engine/inc/renderer/core/2d/sprite/sprite.hpp b/engine/inc/renderer/core/2d/sprite/sprite.hpp index 6580a2d..439a5c2 100644 --- a/engine/inc/renderer/core/2d/sprite/sprite.hpp +++ b/engine/inc/renderer/core/2d/sprite/sprite.hpp @@ -24,7 +24,7 @@ class Sprite { ~Sprite(); u32 id; - Vec2 position, size; + Vec2 position, size, offset; float scale; Color color; SpriteMode mode; diff --git a/engine/src/debug/debug.cpp b/engine/src/debug/debug.cpp index 292a10a..aff2466 100644 --- a/engine/src/debug/debug.cpp +++ b/engine/src/debug/debug.cpp @@ -10,16 +10,11 @@ #include "debug/debug.hpp" -std::unique_ptr TyraDebug::logFile; - -std::ofstream* TyraDebug::getLogFile() { - if (logFile) { - return logFile.get(); - } else { - logFile = std::make_unique(); - logFile->open(Tyra::FileUtils::fromCwd("log.txt"), - std::ofstream::out | std::ofstream::app); - return logFile.get(); - } - -} // namespace Tyra +void TyraDebug::writeInLogFile(std::stringstream* ss) { + std::ofstream logFile; + logFile.open(Tyra::FileUtils::fromCwd("log.txt"), + std::ofstream::out | std::ofstream::app); + logFile << ss->str(); + logFile.flush(); + // logFile.close(); +} diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index de37d73..214db51 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -20,36 +20,20 @@ #include "file/file_utils.hpp" // external IRX modules +#define EXTERN_IRX(_irx) \ + extern u8 _irx[]; \ + extern int size_##_irx -extern u8 sio2man_irx[]; -extern int size_sio2man_irx; - -extern u8 padman_irx[]; -extern int size_padman_irx; - -extern u8 audsrv_irx[]; -extern int size_audsrv_irx; - -extern u8 libsd_irx[]; -extern int size_libsd_irx; - -extern u8 fileXio_irx[]; -extern int size_fileXio_irx; - -extern u8 iomanX_irx[]; -extern int size_iomanX_irx; - -extern u8 bdm_irx[]; -extern int size_bdm_irx; - -extern u8 bdmfs_fatfs_irx[]; -extern int size_bdmfs_fatfs_irx; - -extern u8 usbd_irx[]; -extern int size_usbd_irx; - -extern u8 usbmass_bd_irx[]; -extern int size_usbmass_bd_irx; +EXTERN_IRX(sio2man_irx); +EXTERN_IRX(padman_irx); +EXTERN_IRX(audsrv_irx); +EXTERN_IRX(libsd_irx); +EXTERN_IRX(fileXio_irx); +EXTERN_IRX(iomanX_irx); +EXTERN_IRX(bdm_irx); +EXTERN_IRX(bdmfs_fatfs_irx); +EXTERN_IRX(usbd_irx); +EXTERN_IRX(usbmass_bd_irx); namespace Tyra { diff --git a/engine/src/renderer/core/2d/renderer_core_2d.cpp b/engine/src/renderer/core/2d/renderer_core_2d.cpp index 3f4f397..44fb7bd 100644 --- a/engine/src/renderer/core/2d/renderer_core_2d.cpp +++ b/engine/src/renderer/core/2d/renderer_core_2d.cpp @@ -84,10 +84,12 @@ void RendererCore2D::render(const Sprite& sprite, else if (sizeY > sizeX) texS = texMax / (sizeY / sizeX); - rect->t0.s = sprite.flipHorizontal ? texS : 0.0F; - rect->t0.t = sprite.flipVertical ? texT : 0.0F; - rect->t1.s = sprite.flipHorizontal ? 0.0F : texS; - rect->t1.t = sprite.flipVertical ? 0.0F : texT; + rect->t0.s = + sprite.flipHorizontal ? (texS + sprite.offset.x) : sprite.offset.x; + rect->t0.t = sprite.flipVertical ? (texT + sprite.offset.y) : sprite.offset.y; + rect->t1.s = + sprite.flipHorizontal ? sprite.offset.x : (texS + sprite.offset.x); + rect->t1.t = sprite.flipVertical ? sprite.offset.y : (texT + sprite.offset.y); rect->color.r = sprite.color.r; rect->color.g = sprite.color.g; @@ -131,4 +133,10 @@ void RendererCore2D::render(const Sprite& sprite, context = !context; } +void RendererCore2D::setTextureMappingType( + const PipelineTextureMappingType textureMappingType) { + lod.mag_filter = textureMappingType; + lod.min_filter = textureMappingType; +} + } // namespace Tyra diff --git a/engine/src/renderer/core/2d/sprite/sprite.cpp b/engine/src/renderer/core/2d/sprite/sprite.cpp index 59a0e86..9827749 100644 --- a/engine/src/renderer/core/2d/sprite/sprite.cpp +++ b/engine/src/renderer/core/2d/sprite/sprite.cpp @@ -18,6 +18,7 @@ Sprite::Sprite() { flipVertical = false; size.set(32.0F, 32.0F); position.set(100.0F, 100.0F); + offset.set(0.0F, 0.0F); scale = 1.0F; mode = MODE_REPEAT; setDefaultColor(); diff --git a/tutorials/10-sprite-sheet/Makefile b/tutorials/10-sprite-sheet/Makefile new file mode 100644 index 0000000..e7d6385 --- /dev/null +++ b/tutorials/10-sprite-sheet/Makefile @@ -0,0 +1,24 @@ +TARGET := tutorial_10.elf +ENGINEDIR := ../../engine + +#The Directories, Source, Includes, Objects, Binary and Resources +SRCDIR := src +INCDIR := inc +BUILDDIR := obj +TARGETDIR := bin +RESDIR := res +SRCEXT := cpp +VSMEXT := vsm +VCLEXT := vcl +VCLPPEXT := vclpp +DEPEXT := d +OBJEXT := o + +#Flags, Libraries and Includes +CFLAGS := +LIB := +LIBDIRS := +INC := -I$(INCDIR) +INCDEP := -I$(INCDIR) + +include ../Makefile.tutorials-base \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/bin/.gitignore b/tutorials/10-sprite-sheet/bin/.gitignore new file mode 100644 index 0000000..44c5ea8 --- /dev/null +++ b/tutorials/10-sprite-sheet/bin/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/inc/font_sprite.hpp b/tutorials/10-sprite-sheet/inc/font_sprite.hpp new file mode 100644 index 0000000..b139003 --- /dev/null +++ b/tutorials/10-sprite-sheet/inc/font_sprite.hpp @@ -0,0 +1,37 @@ +/* +# _____ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022-2023, tyra - https://github.com/h4570/tyra +# Licensed under Apache License 2.0 +# Guido Diego Quispe Robles +*/ + +#pragma once + +#include + +#define FONT_CHAR_SIZE 96 + +namespace Tyra { + +class Font { + public: + Font(); + void load(TextureRepository& repository, Renderer2D* renderer); + void free(TextureRepository& repository); + void drawText(const char* text, const int& x, const int& y, Color color); + void drawText(const std::string& text, const int& x, const int& y, + Color color); + + private: + const static int chars[FONT_CHAR_SIZE]; + const static int charWidths[FONT_CHAR_SIZE]; + + Renderer2D* renderer2D; + Sprite allFont; + std::array font; +}; + +} // namespace Tyra \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/inc/tutorial_10.hpp b/tutorials/10-sprite-sheet/inc/tutorial_10.hpp new file mode 100644 index 0000000..e11d626 --- /dev/null +++ b/tutorials/10-sprite-sheet/inc/tutorial_10.hpp @@ -0,0 +1,45 @@ +/* +# _____ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022-2023, tyra - https://github.com/h4570/tyra +# Licensed under Apache License 2.0 +# Guido Diego Quispe Robles +*/ + +#pragma once + +#include +#include "font_sprite.hpp" + +namespace Tyra { + +class Tutorial10 : public Game { + public: + explicit Tutorial10(Engine* engine); + ~Tutorial10(); + + void init(); + void loop(); + + private: + void loadTexture(); + void loadSprite(); + void handlePad(); + + int padTimer; + Engine* engine; + Pad* pad; + Font font; + + Sprite sprite; + Sprite spriteFlip; + Sprite spriteScale; + Sprite spriteStretch; + std::string strFilter; + + PipelineTextureMappingType textureFilter; +}; + +} // namespace Tyra diff --git a/tutorials/10-sprite-sheet/obj/.gitignore b/tutorials/10-sprite-sheet/obj/.gitignore new file mode 100644 index 0000000..44c5ea8 --- /dev/null +++ b/tutorials/10-sprite-sheet/obj/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/res/.gitignore b/tutorials/10-sprite-sheet/res/.gitignore new file mode 100644 index 0000000..44c5ea8 --- /dev/null +++ b/tutorials/10-sprite-sheet/res/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/run.ps1 b/tutorials/10-sprite-sheet/run.ps1 new file mode 100644 index 0000000..74646cc --- /dev/null +++ b/tutorials/10-sprite-sheet/run.ps1 @@ -0,0 +1,4 @@ +$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1' +. $ConfigFile + +RunPCSX2 diff --git a/tutorials/10-sprite-sheet/src/font_sprite.cpp b/tutorials/10-sprite-sheet/src/font_sprite.cpp new file mode 100644 index 0000000..93577a2 --- /dev/null +++ b/tutorials/10-sprite-sheet/src/font_sprite.cpp @@ -0,0 +1,109 @@ +/* +# _____ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022-2023, tyra - https://github.com/h4570/tyra +# Licensed under Apache License 2.0 +# Guido Diego Quispe Robles +*/ + +#include "font_sprite.hpp" + +namespace Tyra { + +const int Font::chars[FONT_CHAR_SIZE]{ + ' ', '!', '"', ' ', '$', '%', ' ', '{', '(', ')', ' ', '+', ',', '-', + '.', '/', '0', '1', '2', '3', '4', '5', '6', '2', '8', '9', ':', ';', + '<', '=', '>', '?', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', ' ', ' ', ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', + 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '}', ']', '~', ' '}; + +const int Font::charWidths[FONT_CHAR_SIZE]{ + 0, 1, 3, 0, 5, 9, 0, 9, 3, 3, 0, 5, 2, 2, 1, 4, 4, 2, 4, 4, 5, 4, 4, 4, + 4, 4, 1, 2, 4, 5, 4, 4, 0, 6, 5, 5, 5, 4, 4, 5, 5, 1, 4, 5, 4, 7, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 7, 5, 5, 4, 0, 0, 0, 0, 0, 0, 5, 4, 4, 4, 4, 3, 4, + 4, 1, 2, 4, 1, 7, 4, 4, 4, 4, 3, 4, 3, 4, 5, 7, 4, 4, 4, 2, 5, 2, 6, 0, +}; + +Font::Font() {} + +void Font::load(TextureRepository& repository, Renderer2D* renderer) { + renderer2D = renderer; + + float height = 16.0F; + float width = 16.0F; + + allFont.mode = MODE_REPEAT; + allFont.size = Vec2(255, 127); + + auto filepath = FileUtils::fromCwd("earthbound-Font.png"); + auto* texture = repository.add(filepath); + texture->addLink(allFont.id); + + int column = 0; + int arrow = 0; + + for (int i = 0; i < FONT_CHAR_SIZE; i++) { + font[i].id = allFont.id; + font[i].mode = MODE_REPEAT; + font[i].size = Vec2(width, height); + font[i].offset = Vec2(width * column, height * arrow); + column++; + + if (column == 16) { + arrow++; + column = 0; + } + } +} + +void Font::free(TextureRepository& repository) { + repository.freeBySprite(allFont); + for (int i = 0; i < FONT_CHAR_SIZE; i++) { + repository.freeBySprite(font[i]); + } +} + +void Font::drawText(const char* text, const int& x, const int& y, Color color) { + drawText(std::string(text), x, y, color); +} + +void Font::drawText(const std::string& text, const int& x, const int& y, + Color color) { + int sizeText = text.size(); + + int offsetY = 0; + int offsetX = 0; + + for (int i = 0; i < sizeText; i++) { + int fontPos = text[i]; + Sprite fontSpr = font[0]; + + for (int j = 0; j < FONT_CHAR_SIZE; j++) { + if (fontPos == chars[j]) { + fontPos = j; + fontSpr = font[j]; + fontSpr.color = color; + fontSpr.position = Vec2(x + offsetX, y + offsetY); + break; + } + } + + if (fontPos == '\n') { + offsetY += 18; + offsetX = 0.0f; + } else { + if ((fontPos != ' ') && (fontPos != '\t')) { + renderer2D->render(fontSpr); + offsetX += charWidths[fontPos] + 2; + } else { + offsetX += 2; + } + } + } +} + +} // namespace Tyra \ No newline at end of file diff --git a/tutorials/10-sprite-sheet/src/main.cpp b/tutorials/10-sprite-sheet/src/main.cpp new file mode 100644 index 0000000..d854e6c --- /dev/null +++ b/tutorials/10-sprite-sheet/src/main.cpp @@ -0,0 +1,26 @@ +/* +# _____ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022-2023, tyra - https://github.com/h4570/tyra +# Licensed under Apache License 2.0 +# Guido Diego Quispe Robles +*/ + +#include "engine.hpp" +#include "tutorial_10.hpp" + +/** + * In this tutorial we will learn: + * - How works the offset of the sprite + * - How works the texture mapping + * - How to write text (font) + */ + +int main() { + Tyra::Engine engine; + Tyra::Tutorial10 game(&engine); + engine.run(&game); + return 0; +} diff --git a/tutorials/10-sprite-sheet/src/tutorial_10.cpp b/tutorials/10-sprite-sheet/src/tutorial_10.cpp new file mode 100644 index 0000000..727b6cf --- /dev/null +++ b/tutorials/10-sprite-sheet/src/tutorial_10.cpp @@ -0,0 +1,290 @@ +/* +# _____ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2022-2023, tyra - https://github.com/h4570/tyra +# Licensed under Apache License 2.0 +# Guido Diego Quispe Robles +*/ + +#include +#include "tutorial_10.hpp" + +namespace Tyra { + +Tutorial10::Tutorial10(Engine* t_engine) + : padTimer(0), engine(t_engine), pad(&t_engine->pad) {} + +Tutorial10::~Tutorial10() { + engine->renderer.getTextureRepository().freeBySprite(sprite); + engine->renderer.getTextureRepository().freeBySprite(spriteFlip); + engine->renderer.getTextureRepository().freeBySprite(spriteScale); + engine->renderer.getTextureRepository().freeBySprite(spriteStretch); + font.free(engine->renderer.getTextureRepository()); +} + +void Tutorial10::init() { + engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F)); + + /** Load all the sprites of the sprite sheet. */ + font.load(engine->renderer.getTextureRepository(), + &engine->renderer.renderer2D); + + /** Sprite contains rectangle information. */ + loadSprite(); + + /** Texture contains png image. */ + loadTexture(); + + /** Set the texture filtering. */ + textureFilter = TyraNearest; + + engine->renderer.core.renderer2D.setTextureMappingType(textureFilter); +} + +void Tutorial10::loop() { + auto& renderer = engine->renderer; + + /** Change the texture filtering of the texture. + * + * The options are: + * TyraNearest (Point Sampling): + * uses the color of the texel closest to the pixel center for the pixel + * color. + * + * TyraLinear (Bilinear Sampling): + * the four nearest texels to the pixel center are sampled + * and their colors are combined by weighted average according to distance. + * + * By default it is linear. + */ + + renderer.core.renderer2D.setTextureMappingType(textureFilter); + + handlePad(); + + /** Begin frame will clear our screen. */ + renderer.beginFrame(); + + /** Render sprite. */ + renderer.renderer2D.render(sprite); + renderer.core.renderer2D.setTextureMappingType(TyraLinear); + renderer.renderer2D.render(spriteFlip); + renderer.core.renderer2D.setTextureMappingType(textureFilter); + renderer.renderer2D.render(spriteScale); + renderer.renderer2D.render(spriteStretch); + + font.drawText("tests with sprite sheet", (512 / 2) - 60, 10, + Color(255, 255, 255)); + font.drawText("Press Cross for nearest filter", (512 / 2) - 70, 50, + Color(255, 255, 255)); + font.drawText("Press Circle for linear filter", (512 / 2) - 65, 70, + Color(255, 255, 255)); + font.drawText("Use left stick for move the offsets of the sprites", + (512 / 2) - 110, 90, Color(255, 255, 255)); + font.drawText("sprite 32x32\n scaled x3", sprite.position.x + 16, + sprite.position.y - 40, Color(255, 255, 255)); + font.drawText("sprite 32x32\nscaled x3 with flip", spriteFlip.position.x + 4, + spriteFlip.position.y - 40, Color(255, 255, 255)); + font.drawText("sprite 96x96 with\n repeat mode", spriteScale.position.x + 6, + spriteScale.position.y - 40, Color(255, 255, 255)); + font.drawText("sprite 96x96 with\n stretch mode", + spriteStretch.position.x + 6, spriteStretch.position.y - 40, + Color(255, 255, 255)); + + if (textureFilter == TyraLinear) { + strFilter = "Filter: Linear"; + } else { + strFilter = "Filter: Nearest"; + } + + int posX1 = sprite.position.x + 16; + int posX2 = spriteFlip.position.x + 16; + int posX3 = spriteStretch.position.x + 16; + int posX4 = spriteScale.position.x + 16; + + int posY1 = sprite.position.y + (sprite.size.y * sprite.scale) + 16; + int posY2 = + spriteFlip.position.y + (spriteFlip.size.y * spriteFlip.scale) + 16; + int posY3 = spriteStretch.position.y + + (spriteStretch.size.y * spriteStretch.scale) + 16; + int posY4 = + spriteScale.position.y + (spriteScale.size.y * spriteScale.scale) + 16; + + font.drawText(strFilter, posX1, posY1, Color(255, 255, 255)); + font.drawText("Filter: Linear", posX2, posY2, Color(255, 255, 255)); + font.drawText(strFilter, posX3, posY3, Color(255, 255, 255)); + font.drawText(strFilter, posX4, posY4, Color(255, 255, 255)); + + /** End frame will perform vsync. */ + renderer.endFrame(); +} + +void Tutorial10::handlePad() { + if (engine->pad.getClicked().Cross) { + textureFilter = TyraNearest; + } else if (engine->pad.getClicked().Circle) { + textureFilter = TyraLinear; + } + + /** Move the offset of the sprites. + * + * The offset of the sprite need to be equal or greater to zero + * or a graphical error occurs. + * + * And the sum of the sprite size and the offset must be less than 1024 + * or a graphical error occurs. + * + * Sum with repeat mode: + * Max = sprite.size + sprite.offset. + * + * Sum with strecth mode: + * Max = original size of the image + sprite.offset. + * + * If it continues moving past these values + * in a moment it will return to normal but + * the error will be repeated with another value. + */ + + if (padTimer <= 0) { + if (pad->getLeftJoyPad().v <= 100) { // up + sprite.offset -= Vec2(0, 16); + spriteFlip.offset -= Vec2(0, 16); + spriteScale.offset -= Vec2(0, 16); + spriteStretch.offset -= Vec2(0, 16); + padTimer = 20; + printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y); + } else if (pad->getLeftJoyPad().v >= 200) { // down + sprite.offset += Vec2(0, 16); + spriteFlip.offset += Vec2(0, 16); + spriteScale.offset += Vec2(0, 16); + spriteStretch.offset += Vec2(0, 16); + padTimer = 20; + printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y); + } + + if (pad->getLeftJoyPad().h <= 100) { // left + sprite.offset -= Vec2(16, 0); + spriteFlip.offset -= Vec2(16, 0); + spriteScale.offset -= Vec2(16, 0); + spriteStretch.offset -= Vec2(16, 0); + padTimer = 20; + printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y); + } else if (pad->getLeftJoyPad().h >= 200) { // right + sprite.offset += Vec2(16, 0); + spriteFlip.offset += Vec2(16, 0); + spriteScale.offset += Vec2(16, 0); + spriteStretch.offset += Vec2(16, 0); + padTimer = 20; + printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y); + } + + } else { + padTimer--; + } +} + +void Tutorial10::loadSprite() { + const auto& screenSettings = engine->renderer.core.getSettings(); + + int offset = 25; + + sprite.mode = SpriteMode::MODE_REPEAT; + + /** Let's scale it down */ + sprite.size = Vec2(32.0F, 32.0F); + sprite.scale = 3; + + /** Set the position */ + sprite.position = + Vec2(offset, screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F); + + spriteFlip.mode = SpriteMode::MODE_REPEAT; + + spriteFlip.flipHorizontal = true; + spriteFlip.flipVertical = true; + + spriteFlip.size = Vec2(32.0F, 32.0F); + + spriteFlip.scale = 3; + + spriteFlip.position = + Vec2(((offset * 2) + (32.0F * 3)), + screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F); + + spriteScale.mode = SpriteMode::MODE_REPEAT; + + spriteScale.size = Vec2(96.0F, 96.0F); + + spriteScale.position = + Vec2(((offset * 3) + ((32.0F * 3) * 2)), + screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F); + + spriteStretch.mode = SpriteMode::MODE_STRETCH; + + spriteStretch.size = Vec2(96.0F, 96.0F); + + spriteStretch.position = + Vec2(((offset * 4) + ((32.0F * 3) * 3)), + screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F); + + TYRA_LOG("Sprite created!"); +} + +void Tutorial10::loadTexture() { + /** + * Renderer has high layer functions, + * which allows to render: + * - Sprite (2D) + * - Mesh (3D) + * + * It uses ONLY low layer functions which are in renderer.core + */ + auto& renderer = engine->renderer; + + /** + * TextureRepository is a repository of textures. + * It is a singleton class, with all game textures. + * We are linking these textures with sprite's (2D) and mesh (3D) materials. + */ + auto& textureRepository = renderer.getTextureRepository(); + + /** + * Texture is stored in "res" directory. + * Content of "res" directory is automatically copied into + * "bin" directory, which contains our final game. + * + * File utils automatically add's device prefix to the path, + * based on current working directory. + * + * In PS2 world: + * - USB has a "mass:" prefix + * - Our PC in PS2Link has a "host:" prefix + * - Our PC in PCSX2 has a "host:" prefix + */ + auto filepath = FileUtils::fromCwd("atlas.png"); + + /** + * Tyra supports following PNG formats: + * 32bpp (RGBA) + * 24bpp (RGB) + * 8bpp, palletized (RGBA) + * 4bpp, palletized (RGBA) + * + * 8bpp and 4bpp are the fastest. + * All of these formats can be easily exported via GIMP. + */ + auto* texture = textureRepository.add(filepath); + + /** Let's assign this texture to sprite. */ + texture->addLink(sprite.id); + + spriteFlip.id = sprite.id; + spriteScale.id = sprite.id; + spriteStretch.id = sprite.id; + + TYRA_LOG("Texture loaded!"); +} + +} // namespace Tyra From e229b34ad356123813246089f29f4a20d4a2e1bb Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sat, 11 Nov 2023 13:34:50 -0300 Subject: [PATCH 7/7] refactore: rename loadPOSIX to loadIO --- engine/inc/irx/irx_loader.hpp | 2 +- engine/src/irx/irx_loader.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/inc/irx/irx_loader.hpp b/engine/inc/irx/irx_loader.hpp index d0dbcac..168797e 100644 --- a/engine/inc/irx/irx_loader.hpp +++ b/engine/inc/irx/irx_loader.hpp @@ -27,7 +27,7 @@ class IrxLoader { void loadSio2man(const bool& verbose); void loadPadman(const bool& verbose); void loadLibsd(const bool& verbose); - void loadPOSIX(const bool& verbose); + void loadIO(const bool& verbose); void loadUsbModules(const bool& verbose); void loadAudsrv(const bool& verbose); diff --git a/engine/src/irx/irx_loader.cpp b/engine/src/irx/irx_loader.cpp index 214db51..ec7f77d 100644 --- a/engine/src/irx/irx_loader.cpp +++ b/engine/src/irx/irx_loader.cpp @@ -60,7 +60,7 @@ void IrxLoader::loadAll(const bool& withUsb, const bool& isLoggingToFile) { return; } - loadPOSIX(!isLoggingToFile); + loadIO(!isLoggingToFile); loadSio2man(!isLoggingToFile); loadPadman(!isLoggingToFile); loadLibsd(!isLoggingToFile); @@ -107,7 +107,7 @@ void IrxLoader::loadLibsd(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Libsd loaded!"); } -void IrxLoader::loadPOSIX(const bool& verbose) { +void IrxLoader::loadIO(const bool& verbose) { int ret; if (verbose) TYRA_LOG("IRX: Loading iomanX...");