111 Commits

Author SHA1 Message Date
Sandro Sobczyński 4f21626136 Merge pull request #181 from h4570/new-rel
new-rel -> master
2024-02-11 14:14:49 +01:00
Sandro Sobczyński 50a9070d2d Merge pull request #180 from Wellinator/feature/texture_wraping
Adds support for texture region repeat
2024-02-11 13:38:20 +01:00
Sandro Sobczyński 8ed34abb83 Merge pull request #175 from GuidoDQR/texture-generation-id
Texture generation id
2024-02-11 13:36:18 +01:00
Sandro Sobczyński f6ebd079f5 Merge pull request #174 from GuidoDQR/fix-load-sprite
Fix sprite loading
2024-02-11 13:35:29 +01:00
Wellinator 0f7083aa5b chore: fix cppcheck validation 2024-02-01 10:30:13 -03:00
Wellinator 9baad8199a Merge branch 'master' into feature/texture_wraping 2024-01-31 18:28:19 -03:00
Wellinator 5eafc0bdba chore: add tutorial 11, texture region repeat 2024-01-31 18:27:34 -03:00
Wellinator c3c649dcdc chore: add tutorial 11 ignore files 2024-01-31 18:15:36 -03:00
Wellinator 1c4a84dffa chore: implements updateTextureInfo for texture packet update 2024-01-31 17:57:19 -03:00
Wellinator f727dae150 refactore: change method from private to public 2024-01-31 17:53:20 -03:00
Wellinator 9b24ea3bb6 feat: allow changing the texture wrap settings 2024-01-31 14:27:48 -03:00
Guido Diego Quispe Robles 586180764e Update png_loader.cpp
optimization
2024-01-25 01:33:15 -03:00
Guido Diego Quispe Robles a329ea73cc new namespace 2024-01-24 12:13:01 -03:00
Guido Diego Quispe Robles 5418e28b73 Update texture.cpp
initial texturecounter is 0 because texture buffer can't be 0.
if id is 0 always create a texture buffer.
2024-01-18 22:27:03 -03:00
Guido Diego Quispe Robles d773173ece id generation texture 2024-01-18 21:53:38 -03:00
Guido Diego Quispe Robles aa21baaaf2 change core width and clut width 2024-01-04 22:11:10 -03:00
Sandro Sobczyński 0c0fcd697f Merge pull request #173 from GuidoDQR/rsync
Fixed rsync warning from copy source code to docker volume
2024-01-02 21:10:17 +01:00
Guido Diego Quispe Robles e07cfc502a Update tasks.json
fixes rsync issue and prevents files from disappearing:
rsync warning: some files vanished before they could be transferred (code 24)
2023-12-28 09:16:44 -03:00
Sandro Sobczyński ab08a385a6 Merge pull request #172 from h4570/support-new-pcsx2
Add support for new PCSX2
2023-11-25 16:55:36 +01:00
h4570 8642959d70 run in background 2023-11-25 16:36:08 +01:00
h4570 19ae6de1c7 add support for new pcsx2 2023-11-25 16:12:55 +01:00
h4570 c40558bd54 move vcl from my server to github repo 2023-11-25 14:12:42 +01:00
Sandro Sobczyński 700e878e61 Merge pull request #170 from h4570/misc-cleanup-wolf
Minor fixes
2023-11-13 20:15:10 +01:00
h4570 9ee1df81e6 Merge branch 'master' into misc-cleanup-wolf 2023-11-13 20:08:33 +01:00
Sandro Sobczyński 22ecaffe1b Merge pull request #155 from Wolf3s/Cleanup
misc cleanup
2023-11-13 19:53:02 +01:00
h4570 26285c54e9 add israpps to readme 2023-11-13 19:46:44 +01:00
h4570 a52e2bec0e move assets to github repo 2023-11-13 19:40:19 +01:00
Sandro Sobczyński 5583c7bc92 remove sha step 2023-11-13 19:12:39 +01:00
Sandro Sobczyński b8e5309119 rename artifacts 2023-11-13 19:11:05 +01:00
Sandro Sobczyński fdc5450181 Merge pull request #169 from h4570/github-actions
Github Actions refactor
2023-11-13 19:02:22 +01:00
Sandro Sobczyński 39a962c59b github actions bugfixes 2023-11-13 18:53:35 +01:00
Sandro Sobczyński b84bd99059 fix job name 2023-11-13 18:29:46 +01:00
Sandro Sobczyński caa0fd4db3 refactor github actions 2023-11-13 18:27:38 +01:00
Sandro Sobczyński daee3b4971 Merge pull request #168 from israpps/patch-5
add continous integration
2023-11-13 17:57:50 +01:00
Matías Israelson 02a23cd415 add continous integration 2023-11-13 10:23:57 -03:00
André Guilherme c2e653c059 Merge branch 'h4570:master' into Cleanup 2023-11-12 09:57:00 -03:00
Sandro Sobczyński 676ac34ec3 Merge pull request #151 from Wellinator/feature/posix-drivers
Feature posix drivers loading
2023-11-11 17:37:41 +01:00
Wellinator e229b34ad3 refactore: rename loadPOSIX to loadIO 2023-11-11 13:34:50 -03:00
Wellinator 67f70f80d8 Merge branch 'master' into feature/posix-drivers 2023-11-11 12:35:19 -03:00
Wellinator 1e046d9dda merge: merge changes from upstream master 2023-11-11 12:32:04 -03:00
Sandro Sobczyński 383cdb3675 Merge pull request #166 from israpps/patch-4
Compact IRX externs
2023-11-11 11:34:28 +01:00
israpps 795910de69 Update irx_loader.cpp 2023-11-10 14:45:57 -03:00
Matías Israelson b344fd4141 Compact IRX externs 2023-11-10 13:09:28 -03:00
Sandro Sobczyński b3ff38af06 Merge pull request #162 from GuidoDQR/screenDebug
Screen debug
2023-11-08 22:53:16 +01:00
Guido Diego Quispe Robles 19c673767c Debug Update
Screen debug for errors
2023-11-08 16:07:37 -03:00
Sandro Sobczyński 15a2dbb854 Merge pull request #161 from GuidoDQR/master
Fixed writeLogsToFile
2023-11-05 14:47:23 +01:00
Guido Diego Quispe Robles f4f527b877 Update debug.hpp
clang format
2023-11-04 23:28:09 -03:00
Guido Diego Quispe Robles ce4e2f663f optimization code
created writeInLogFile function

tested in real PS2 and emulator
2023-11-04 23:27:16 -03:00
Guido Diego Quispe Robles 7736f00d71 Update debug.hpp
formatted with clang
2023-11-04 22:40:13 -03:00
Guido Diego Quispe Robles 878adf5dbb Fix writeLogsToFile
Deleted logFile smart pointer and getLogFile function.
logfile created inside of the statics functions.
Debug.cpp can be deleted.
2023-11-04 22:35:13 -03:00
Sandro Sobczyński d2da130771 Update README.MD 2023-10-19 21:22:56 +02:00
Sandro Sobczyński 588f45e870 Update README.MD 2023-10-19 21:22:20 +02:00
André Guilherme b19d4f42f5 Merge branch 'h4570:master' into Cleanup 2023-07-27 10:10:31 -03:00
André Guilherme ea5849095e Update README.MD 2023-07-25 23:25:28 -03:00
Sandro Sobczyński e2790d93b6 Merge pull request #158 from freebytego/master
Fix music going too fast for first few seconds
2023-07-25 21:21:58 +02:00
freebytego 7401926202 Fix music going too fast for first few seconds 2023-07-25 08:51:43 +06:00
Wellinator 200a68e219 fix: accelerated audio 2023-07-24 14:43:21 -03:00
Wolf3s 699e5f0ff5 misc cleanup 2023-06-04 09:36:57 -03:00
Sandro Sobczyński e63ae14792 Merge pull request #154 from GuidoDQR/sprite-offset
* Added offset to 2D sprite (Guido Diego Quispe Robles)
* Added tutorial with font and texture atlas (Guido Diego Quispe Robles)
2023-05-29 18:59:48 +02:00
h4570 87b983153a change tyra version 2023-05-29 18:53:30 +02:00
h4570 cab934763f minor adjustments 2023-05-28 22:55:42 +02:00
Guido Diego Quispe Robles 20d2291a88 Update Tyra copyright 2023-05-28 16:46:32 -03:00
Guido Diego Quispe Robles 4f6e55c0b0 new Tutorial
tutorial with sprite offset, sprite sheet and texture filtering
2023-05-28 13:47:48 -03:00
Guido Diego Quispe Robles fbcb38d37a tutorial 10 2023-05-26 18:04:23 -03:00
Sandro Sobczyński a25594b95c Merge pull request #153 from nicholas477/master
Updated tyra install directions to include downloading assets
2023-04-22 23:38:26 +02:00
Nicholas 86c0ab74f1 Updated tyra install directions to include downloading assets 2023-04-14 12:52:42 -04:00
Wellinator 17d2d93d45 fix: irx loading order 2023-01-23 14:54:20 -03:00
Wellinator f546604ba3 fix: redefinition of ret 2023-01-23 10:27:55 -03:00
Wellinator d196290a3f fix: extern variables names 2023-01-23 10:24:24 -03:00
Wellinator 481ccd0cf9 feat: load fileXio and iomanX iop drivers 2023-01-23 10:19:18 -03:00
Declan Hopkins e3726600fd fix memory leak (#150) 2022-12-23 23:20:09 +01:00
Sandro Sobczyński 8b8500a1c9 Update README.MD 2022-09-05 00:08:38 +02:00
Sandro Sobczyński 789c795c14 Update README.MD 2022-09-04 22:59:11 +02:00
h4570 a0be9022ff Merge branch 'master' of https://github.com/h4570/tyra 2022-09-02 17:44:24 +02:00
h4570 77c6702f80 remove duplicated comments 2022-09-02 17:44:15 +02:00
Sandro Sobczyński d54cba9e58 Update README.MD 2022-09-02 11:21:56 +02:00
Wolf3s 958ddb4ab7 add some missing links on credits (#142) 2022-09-01 08:54:12 +02:00
Sandro Sobczyński edff3a85d5 Update README.MD 2022-08-31 09:37:42 +02:00
Sandro Sobczyński 165cc4221e Update README.MD 2022-08-31 09:36:42 +02:00
Wolf3s cc42bbf56b Update readme (#139) 2022-08-31 09:32:12 +02:00
Wolf3s a340540d55 Fix version (#138) 2022-08-30 22:40:04 +02:00
Sandro Sobczyński d790349ab9 Update README.MD 2022-08-30 11:26:12 +02:00
Wolf3s 0cecbf0a7d add ci cpp-check and clang format on tutorial_08.hpp (#137)
* Create check-format.yml

* Fix
2022-08-29 23:13:23 +02:00
Sandro Sobczyński f46b058ecf Update README.MD 2022-08-29 20:24:27 +02:00
Sandro Sobczyński c833f93db2 Update README.MD 2022-08-29 19:19:40 +02:00
Sandro Sobczyński 6dc73982f9 Update README.MD 2022-08-29 19:19:29 +02:00
Sandro Sobczyński 1fe12962b8 Merge pull request #136 from h4570/135-obj-get-texture-names-from-mtl-file-instead-of-material-name
Fix for obj loader and dynamic pipeline
2022-08-29 19:06:22 +02:00
h4570 e359bcbe2b patch 1 2022-08-29 19:00:47 +02:00
Sandro Sobczyński 13f4b5e626 Update README.MD 2022-08-29 17:16:45 +02:00
Sandro Sobczyński 2ae1ccd761 Update README.MD 2022-08-28 18:48:59 +02:00
h4570 d7013f302b Merge branch 'master' of https://github.com/h4570/tyra 2022-08-28 17:45:55 +02:00
h4570 b3fe92c996 Merge branch 'master' of https://github.com/h4570/tyra 2022-08-28 17:21:13 +02:00
h4570 822663f95e true fix 2022-08-28 17:21:10 +02:00
h4570 3f9bb33177 rename game setting 2022-08-28 17:11:12 +02:00
Sandro Sobczyński fa173f1e87 Update README.MD 2022-08-28 16:51:46 +02:00
h4570 f08da7b358 update extensions.json 2022-08-28 15:31:18 +02:00
h4570 945b9c462b fix template includes 2022-08-28 15:15:24 +02:00
h4570 c9535412a7 info about tutorials 2022-08-28 15:07:58 +02:00
Sandro Sobczyński 2c41930cb2 Update README.MD 2022-08-28 14:26:09 +02:00
h4570 2a4e2a2109 Merge branch 'master' of https://github.com/h4570/tyra 2022-08-28 13:50:34 +02:00
h4570 286b9e43a7 fix far plane 2022-08-28 13:50:32 +02:00
Sandro Sobczyński f62eaff37b Update README.MD 2022-08-27 15:37:32 +02:00
Sandro Sobczyński 48fa642cef Update README.MD 2022-08-25 00:03:34 +02:00
Sandro Sobczyński cad720a399 Update README.MD 2022-08-25 00:01:56 +02:00
Sandro Sobczyński cf3f5b3443 Update README.MD 2022-08-25 00:00:04 +02:00
Sandro Sobczyński 48a0eec86b Update README.MD 2022-08-24 23:42:02 +02:00
Sandro Sobczyński 6a9f3c6683 Update README.MD 2022-08-24 23:40:23 +02:00
Sandro Sobczyński 325fea1a8b Update README.MD 2022-08-24 23:36:00 +02:00
Sandro Sobczyński ce00f58b89 Update README.MD 2022-08-24 23:21:02 +02:00
h4570 5d4d2b0f06 remove roadmap text file 2022-08-24 23:20:16 +02:00
Sandro Sobczyński ca25a6de03 Update README.MD 2022-08-24 23:14:37 +02:00
97 changed files with 1600 additions and 356 deletions
+69
View File
@@ -0,0 +1,69 @@
name: Official build
on:
push:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
container: h4570/tyra
steps:
- name: Install dependencies
run: |
apt-get update
apt install -y git make wget
- name: Set git safe directory
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Checkout
uses: actions/checkout@v3
- name: Compile engine
run: |
make clean all -C engine
- name: Compile tutorials
run: |
make clean all -C tutorials/01-hello
make clean all -C tutorials/02-sprite
make clean all -C tutorials/03-minecraft
make clean all -C tutorials/04-de_dust2
make clean all -C tutorials/05-animation
make clean all -C tutorials/06-audio
make clean all -C tutorials/07-lighting
make clean all -C tutorials/08-skybox-debug
make clean all -C tutorials/09-manual-mode
make clean all -C tutorials/10-sprite-sheet
- name: Compile demo
run: |
make clean all -C demo
- name: Upload tutorials
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: tutorials-elf
path: |
tutorials/01-hello/bin
tutorials/02-sprite/bin
tutorials/03-minecraft/bin
tutorials/04-de_dust2/bin
tutorials/05-animation/bin
tutorials/06-audio/bin
tutorials/07-lighting/bin
tutorials/08-skybox-debug/bin
tutorials/09-manual-mode/bin
tutorials/10-sprite-sheet/bin
- name: Upload demo
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: demo-elf
path: |
demo/bin
+73
View File
@@ -0,0 +1,73 @@
name: PR build check
on:
pull_request:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
container: h4570/tyra
steps:
- name: Install dependencies
run: |
apt-get update
apt install -y git make wget
- name: Set git safe directory
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Checkout
uses: actions/checkout@v3
- name: Compile engine
run: |
make clean all -C engine
- name: Compile tutorials
run: |
make clean all -C tutorials/01-hello
make clean all -C tutorials/02-sprite
make clean all -C tutorials/03-minecraft
make clean all -C tutorials/04-de_dust2
make clean all -C tutorials/05-animation
make clean all -C tutorials/06-audio
make clean all -C tutorials/07-lighting
make clean all -C tutorials/08-skybox-debug
make clean all -C tutorials/09-manual-mode
make clean all -C tutorials/10-sprite-sheet
- name: Compile demo
run: |
make clean all -C demo
- name: Get short SHA
id: slug
run: |
echo "SHA8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_ENV
- name: Get branch
id: branch
run: |
BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed 's/refs\///g' | sed 's/\//_/g')
echo "BRANCH=${BRANCH_NAME}" >> $GITHUB_ENV
- name: Upload build artifacts
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: binaries-${{ env.SHA8 }}-${{ env.BRANCH }}
path: |
tutorials/01-hello/bin
tutorials/02-sprite/bin
tutorials/03-minecraft/bin
tutorials/04-de_dust2/bin
tutorials/05-animation/bin
tutorials/06-audio/bin
tutorials/07-lighting/bin
tutorials/08-skybox-debug/bin
tutorials/09-manual-mode/bin
tutorials/10-sprite-sheet/bin
demo/bin
+36
View File
@@ -0,0 +1,36 @@
#This is a modified version of the clang format check used on Open-PS2-Loader
name: PR C++ format check
on:
push:
paths:
- '**.hpp'
- '**.cpp'
- '**.'
- '**.h'
- './engine/inc/tyra'
- '.github/workflows/check-format.yml'
- '.clang-format'
pull_request:
paths:
- '**.hpp'
- '**.cpp'
- '**.'
- '**.h'
- './engine/inc/tyra'
- '.github/workflows/check-format.yml'
- '.clang-format'
jobs:
check-format:
name: Check clang format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: DoozyX/clang-format-lint-action@v0.12
with:
source: '.'
extensions: 'hpp, cpp, h'
clangFormatVersion: 12
inplace: False
+1
View File
@@ -4,3 +4,4 @@
/c_cpp_properties.json /c_cpp_properties.json
/tasks.json /tasks.json
/settings.json /settings.json
/ps2dev-intellisense
+3 -3
View File
@@ -42,7 +42,7 @@
"options": { "options": {
"cwd": "${config:buildDirectory}" "cwd": "${config:buildDirectory}"
}, },
"command": "./run.ps1" "command": "Start-Job { ./run.ps1 } | Receive-Job -Wait"
}, },
{ {
"type": "shell", "type": "shell",
@@ -60,12 +60,12 @@
{ {
"type": "shell", "type": "shell",
"label": "Send to PS2", "label": "Send to PS2",
"command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'" "command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || $true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
}, },
{ {
"type": "shell", "type": "shell",
"label": "Open PS2 output logger", "label": "Open PS2 output logger",
"command": "docker stop ps2-logs || true && docker run -t --rm --name=ps2-logs -p ${input:local2Ip}:18194:18194/udp h4570/tyra sh -c 'ps2client -h ${input:ps2Ip} listen'", "command": "docker stop ps2-logs || $true && docker run -t --rm --name=ps2-logs -p ${input:local2Ip}:18194:18194/udp h4570/tyra sh -c 'ps2client -h ${input:ps2Ip} listen'",
"runOptions": { "runOptions": {
"instanceLimit": 1 "instanceLimit": 1
}, },
+2 -1
View File
@@ -3,6 +3,7 @@
"ms-vscode.cpptools-extension-pack", "ms-vscode.cpptools-extension-pack",
"ryzngard.vscode-header-source", "ryzngard.vscode-header-source",
"maziac.asm-code-lens", "maziac.asm-code-lens",
"dmnsgn.vscode-wavefront" "dmnsgn.vscode-wavefront",
"spmeesseman.vscode-taskexplorer"
] ]
} }
+1 -1
View File
@@ -16,7 +16,7 @@ IRXEMBEDDEDEXT := irx-em
CFLAGS += -D_EE -Wall -O3 CFLAGS += -D_EE -Wall -O3
LINKFLAGS += -O3 -Wl,-zmax-page-size=128 LINKFLAGS += -O3 -Wl,-zmax-page-size=128
ASFLAGS += -O3 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 INC += -I$(PS2DEV)/ps2sdk/ee/include -I$(PS2DEV)/ps2sdk/common/include -I$(PS2DEV)/ps2sdk/ports/include
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
+46 -48
View File
@@ -1,3 +1,4 @@
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/b81ab27f1c774f839729829c9f772b1a)](https://www.codacy.com/gh/h4570/tyra/dashboard?utm_source=github.com&utm_medium=referral&utm_content=h4570/tyra&utm_campaign=Badge_Grade)
[![Contributors][contributors-shield]][contributors-url] [![Contributors][contributors-shield]][contributors-url]
[![MIT License][license-shield]][license-url] [![MIT License][license-shield]][license-url]
[![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5) [![Discord](https://img.shields.io/badge/discord-Tyra-brightgreen?logo=discord)](https://discord.gg/NhhTmg3Gm5)
@@ -6,14 +7,16 @@
<br /> <br />
<p align="center"> <p align="center">
<a href="https://github.com/h4570/tyra"> <a href="https://github.com/h4570/tyra">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash.png" alt="Logo" width="100%" height="auto"> <img src="https://raw.githubusercontent.com/h4570/tyra/master/assets/github-splash.png" alt="Logo" width="100%" height="auto">
</a> </a>
<h3 align="center">Tyra - 2.0.0</h3> <h3 align="center">Tyra</h3>
<p align="center"> <p align="center">
Open source game engine for PlayStation 2™ Open source game engine for PlayStation 2™
<br /> <br />
<a href="https://www.youtube.com/watch?v=DGR4vWDjkmc"><strong>Showcase video »</strong></a>
&nbsp;
<a href="https://youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH"><strong>YouTube tutorials »</strong></a> <a href="https://youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH"><strong>YouTube tutorials »</strong></a>
&nbsp; &nbsp;
<br /> <br />
@@ -24,51 +27,48 @@
</p> </p>
</p> </p>
[![Stargazers repo roster for h4570/tyra](https://reporoster.com/stars/h4570/tyra)](https://github.com/h4570/tyra/stargazers)
## Table of Contents ## Table of Contents
* [About the project](#about-the-project) * [About the project](#about-the-project)
* [Description](#description) * [Description](#description)
* [Tutorials](#tutorials) * [Tutorials](#tutorials)
* [Features](#features) * [Features](#features)
* [Branches](#branches)
* [Contributing](#contributing) * [Contributing](#contributing)
* [Games](#games)
* [License](#license) * [License](#license)
* [Built With](#built-with) * [Built With](#built-with)
* [Acronyms](#acronyms) * [Acronyms](#acronyms)
* [Thanks](#thanks) * [Credits](#credits)
<br />
## About the Project ## About the Project
<p align="center"> <p align="center">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/tyra_code.gif" alt="Sample code" width="500" height="auto"> <img src="https://raw.githubusercontent.com/h4570/tyra/master/assets/tyra_code.gif" alt="Sample code" width="500" height="auto">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/showcase.gif " alt="Sample game" width="500" height="auto"> <img src="https://raw.githubusercontent.com/h4570/tyra/master/assets/showcase.gif " alt="Sample game" width="500" height="auto">
</p> </p>
--- ---
### Description ### Description
Tyra is a project that allows you to easily create games for the PlayStation 2 console. Tyra is a project that allows you to easily create games for the PlayStation 2 console.
When I tried to make a game for PS2 a few years ago, I realized how many things had to be done to tame this exotic console architecture. When I tried to make a game for PS2 a few years ago, I realized how many things had to be done to tame this exotic console architecture.
Decision was simple - I need to create an engine which will handle 3D file loading, 2D/3D rendering, animation, audio, handling between PS2 CPUs, synchronization and it should be simple as possible - so people with no experience can create a simple game in a few hours. Decision was simple - I need to create an engine which will handle 3D file loading, 2D/3D rendering, animation, audio, handling between PS2 CPUs, synchronization.. It should be simple as possible - so people with no experience can create a simple game in a few hours.
**And that's what Tyra is all about.** **And that's what Tyra is all about.**
### Tutorials ### Tutorials
* Setup environment - [Text tutorial](https://github.com/h4570/tyra/tree/master/docs/install) or [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) * 01 - Setup environment - [Text tutorial](https://github.com/h4570/tyra/tree/master/docs/install) or [Video](https://www.youtube.com/watch?v=9IXOU1SPdzc)
* Cook game assets - [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) * 02 - Cooking game assets - [Video](https://www.youtube.com/watch?v=hpVDeTTLyjI)
* Create game from template - [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) * 03 - Create a game repository - [Video](https://www.youtube.com/watch?v=DKfIKar3GUM)
* 04 - Run game from USB in PS2 - [Video](https://www.youtube.com/watch?v=ZX8fTQqiNho)
--- ---
* 01 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/01-hello), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Hello world * 01 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/01-hello) - Hello world
* 02 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/02-sprite), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 2D rendering * 02 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/02-sprite) - 2D rendering
* 03 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/03-minecraft), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 3D minecraft blocks * 03 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/03-minecraft) - 3D minecraft blocks
* 04 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/04-de_dust2), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - `de_dust2.obj` rendering * 04 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/04-de_dust2) - `de_dust2.obj` rendering
* 05 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/05-animation), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 3D animation * 05 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/05-animation) - 3D animation
* 06 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/06-audio), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Background music and sound effects * 06 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/06-audio) - Background music and sound effects
* 07 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/07-lighting), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Static lightmap and dynamic directional lights * 07 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/07-lighting) - Static lightmap and dynamic directional lights
* 08 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/08-skybox-debug), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Skybox and debug rendering * 08 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/08-skybox-debug) - Skybox and debug rendering
* 09 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/09-manual-mode), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Manual rendering (a'la OpenGL) * 09 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/09-manual-mode) - Manual rendering (a'la OpenGL)
* Demo game - [Code](https://github.com/h4570/tyra/tree/master/demo)
--- ---
### Features ### Features
@@ -85,25 +85,21 @@ Decision was simple - I need to create an engine which will handle 3D file loadi
* Precise - culling only visible parts of mesh * Precise - culling only visible parts of mesh
* Clipping: * Clipping:
* Standard "fake", but fast PS2 clipping done in `VU1` * Standard "fake", but fast PS2 clipping done in `VU1`
* Software triangle done in `EE Core` * Software clipping done in `EE Core`
* Optimized math functions via `VU0` coprocessor * Optimized math functions via `VU0` coprocessor
* Background music and sound effects support * Background music and sound effects support
* Pad support * Pad support
* USB support
* Memory card support
* `.wav` Audio file support * `.wav` Audio file support
* `.obj` 3D file support * `.obj` 3D file support
* `.md2` 3D file support * `.md2` 3D file support
* `.png` Texture file support * `.png` Texture file support
### Branches ## Contributing
* `master` - stable releases - tested on PS2 & PCSX2.
* `develop` - daily builds.
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues). See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
<br />
## Contributing
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
1. Fork the Project 1. Fork the Project
@@ -112,22 +108,26 @@ Contributions are what make the open source community such an amazing place to b
4. Push to the Branch (`git push origin feature/amazing-feature`) 4. Push to the Branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request 5. Open a Pull Request
<br /> ## Games
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)
## License ## License
Distributed under the Apache License 2.0 License. See `LICENSE` for more information. Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
<br />
## Built With ## Built With
* [PS2DEV](https://github.com/ps2dev/ps2dev) * [PS2DEV](https://github.com/ps2dev/ps2dev)
* [VCLPP](https://github.com/glampert/vclpp) * [VCLPP](https://github.com/glampert/vclpp)
* Sony VCL * Sony VCL
<br />
## Acronyms ## Acronyms
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2 * EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
* EE Core - main PS2 CPU (c++ done here) * EE Core - main PS2 CPU (c++ done here)
@@ -136,19 +136,17 @@ Distributed under the Apache License 2.0 License. See `LICENSE` for more informa
* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA. * VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
* IOP - I/O processor which enables access to peripheral devices, such the game controller * IOP - I/O processor which enables access to peripheral devices, such the game controller
<br />
## Credits ## Credits
Without these guys, Tyra would not happen: Without these guys, Tyra would not happen:
* Dr Henry Fortuna - for code sources, PS2 academy tutorials * [Dr Henry Fortuna](http://ps2-edu.tensioncore.com/index.html) - for code sources, PS2 academy tutorials
* Rick Gaiser, fjtrujy - for maintaining PS2DEV * Whole [PS2DEV](https://github.com/ps2dev) team, and specially to [Rick Gaiser](https://github.com/rickgaiser), [fjtrujy](https://github.com/fjtrujy) - for a lot of good tips!
* Wellington Carvalho - for testing, contributing to Tyra and sharing cool ideas! * [Wellington Carvalho](https://github.com/Wellinator), [André Guilheme](https://github.com/Wolf3s), [Matías Israelson](https://github.com/israpps) - for testing, contributing to Tyra and sharing cool ideas!
* Lukasz D.K. - for huge archive of PS2 stuff * [Leonardo Ono](https://github.com/leonardo-ono) - for software renderer example (with clipping!)
* Guilherme Lampert - for code sources * [Lukasz D.K.](https://github.com/lukaszdk) - for huge archive of PS2 stuff
* Jesper Svennevid, Daniel Collin - for openvcl's code samples * [Guilherme Lampert](https://github.com/glampert) - for code sources
* Whole PS2DEV team * [Jesper Svennevid](https://github.com/jsvennevid), [Daniel Collin](https://github.com/emoon) - for openvcl's code samples
* Manieq - for nice splash screens! * [Manieq](https://www.facebook.com/mvnieq) - for nice splash screens!
* And so many other guys. Thanks! * And so many other guys. Thanks!
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra) Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
@@ -157,7 +155,7 @@ Sandro Sobczyński - sandro.sobczynski@gmail.com
<br /> <br />
<a href="https://github.com/h4570/tyra"> <a href="https://github.com/h4570/tyra">
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/github-splash2.png" alt="Logo" width="100%" height="auto"> <img src="https://raw.githubusercontent.com/h4570/tyra/master/assets/github-splash2.png" alt="Logo" width="100%" height="auto">
</a> </a>
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square [contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
-23
View File
@@ -1,23 +0,0 @@
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
- [General] Readme Credits: clipping, obj loader
- [Video] How to setup environment
- [Video] How to work with Tyra
- [Video] How to create own game
- [Video] How to cook assets (audio, textures, obj)
- [Video] Tutorial videos
- [Video] How to run game from USB
------------ Github issues for Tyra v2 ------------
- [Demo] BBox constructors
- [General] Add cpp lint checker in GitHub / static code analysis
- [General] Smart pointers and std::array instead of raw pointers
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
- [renderer] fog
- [General] CI in Github via docker image
- [MD2] Refactor
- [2D] Add zbuffer support (z-index)
- [3DUtility] Add zbuffer support (z-index), cupMesh->translation.translateZ(10.0F) - wylaczyc zeby widziec problem
- [2D] Fixed font support
- [File] Async file loading
- [tyrdat] Custom 3D data file with precalculated bboxes with support of async loading
- [Renderer] Interlacing, and then 640x448 resolution
Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
View File
Binary file not shown.
+1 -1
View File
@@ -12,6 +12,6 @@
namespace Demo { namespace Demo {
const bool IS_REAL_PS2 = false; const bool IS_REAL_PS2_VIA_USB = false;
} // namespace Demo } // namespace Demo
+1 -1
View File
@@ -15,7 +15,7 @@
int main() { int main() {
Tyra::EngineOptions options; Tyra::EngineOptions options;
if (Demo::IS_REAL_PS2) { if (Demo::IS_REAL_PS2_VIA_USB) {
options.writeLogsToFile = true; options.writeLogsToFile = true;
options.loadUsbDriver = true; options.loadUsbDriver = true;
} }
+2 -2
View File
@@ -30,7 +30,7 @@ EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
auto data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"), auto data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"),
objOptions); objOptions);
data->normalsEnabled = false; data->loadNormals = false;
motherMesh = new DynamicMesh(data.get()); motherMesh = new DynamicMesh(data.get());
bodyTexture = textureRepo->add( bodyTexture = textureRepo->add(
@@ -45,7 +45,7 @@ EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
auto* death = engine->audio.adpcm.load( auto* death = engine->audio.adpcm.load(
FileUtils::fromCwd("game/models/zombie/death.adpcm")); FileUtils::fromCwd("game/models/zombie/death.adpcm"));
const int enemyCount = IS_REAL_PS2 ? 8 : 12; const int enemyCount = IS_REAL_PS2_VIA_USB ? 8 : 12;
for (int i = 0; i < enemyCount; i++) { for (int i = 0; i < enemyCount; i++) {
EnemyInfo info; EnemyInfo info;
info.adpcmChannel = 9 + i; info.adpcmChannel = 9 + i;
+1 -1
View File
@@ -45,7 +45,7 @@ void GameState::onStart() {
engine->audio.song.setVolume(85); engine->audio.song.setVolume(85);
if (IS_REAL_PS2) engine->renderer.setFrameLimit(false); if (IS_REAL_PS2_VIA_USB) engine->renderer.setFrameLimit(false);
initialized = true; initialized = true;
} }
+1 -1
View File
@@ -28,7 +28,7 @@ Weapon::Weapon(Engine* engine) {
auto* repo = &engine->renderer.core.texture.repository; auto* repo = &engine->renderer.core.texture.repository;
auto data = auto data =
loader.load(FileUtils::fromCwd("game/models/ak47/ak47.obj"), objOptions); loader.load(FileUtils::fromCwd("game/models/ak47/ak47.obj"), objOptions);
data->normalsEnabled = false; data->loadNormals = false;
mesh = new StaticMesh(data.get()); mesh = new StaticMesh(data.get());
mesh->translation.translateX(2.85F); mesh->translation.translateX(2.85F);
+1 -1
View File
@@ -25,7 +25,7 @@ Skybox::Skybox(TextureRepository* repo) {
auto data = loader.load(FileUtils::fromCwd("game/models/skybox/skybox.obj"), auto data = loader.load(FileUtils::fromCwd("game/models/skybox/skybox.obj"),
objOptions); objOptions);
data->normalsEnabled = false; data->loadNormals = false;
mesh = new StaticMesh(data.get()); mesh = new StaticMesh(data.get());
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/skybox/"), "png"); repo->addByMesh(mesh, FileUtils::fromCwd("game/models/skybox/"), "png");
+1 -1
View File
@@ -29,7 +29,7 @@ Terrain::Terrain(TextureRepository* repo)
auto data = loader.load(FileUtils::fromCwd("game/models/terrain/terrain.obj"), auto data = loader.load(FileUtils::fromCwd("game/models/terrain/terrain.obj"),
objOptions); objOptions);
data->normalsEnabled = false; data->loadNormals = false;
mesh = new StaticMesh(data.get()); mesh = new StaticMesh(data.get());
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/terrain/"), "png"); repo->addByMesh(mesh, FileUtils::fromCwd("game/models/terrain/"), "png");
+7 -6
View File
@@ -17,9 +17,10 @@
docker pull h4570/tyra docker pull h4570/tyra
git clone https://github.com/h4570/tyra.git git clone https://github.com/h4570/tyra.git
``` ```
3. Open `VSCode` and open previously cloned directory. 3. Download the [assets.zip](https://github.com/h4570/tyra/releases) file and unzip it into the tyra directory
4. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/` 4. Open `VSCode` and open previously cloned directory.
5. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2. 5. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/`
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) 6. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2.
7. Click `CTRL+SHIFT+P`, type `Tasks: Run build task` 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. 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` 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`
+23 -14
View File
@@ -20,6 +20,7 @@
#else // IF Debug #else // IF Debug
#include <stdio.h> #include <stdio.h>
#include <debug.h>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
@@ -48,9 +49,7 @@ class TyraDebug {
(void)expander{0, (void(ss << std::forward<Args>(args)), 0)...}; (void)expander{0, (void(ss << std::forward<Args>(args)), 0)...};
if (Tyra::Info::writeLogsToFile) { if (Tyra::Info::writeLogsToFile) {
auto* logFile = getLogFile(); writeInLogFile(&ss);
*logFile << ss.str();
logFile->flush();
} else { } else {
printf("%s", ss.str().c_str()); printf("%s", ss.str().c_str());
} }
@@ -65,9 +64,7 @@ class TyraDebug {
ss1 << "|\n"; ss1 << "|\n";
if (Tyra::Info::writeLogsToFile) { if (Tyra::Info::writeLogsToFile) {
auto* logFile = getLogFile(); writeInLogFile(&ss1);
*logFile << ss1.str();
logFile->flush();
} else { } else {
printf("%s", ss1.str().c_str()); printf("%s", ss1.str().c_str());
} }
@@ -80,20 +77,22 @@ class TyraDebug {
ss2 << "====================================\n\n"; ss2 << "====================================\n\n";
if (Tyra::Info::writeLogsToFile) { if (Tyra::Info::writeLogsToFile) {
auto* logFile = getLogFile(); writeInLogFile(&ss2);
*logFile << ss2.str();
logFile->flush();
} else { } else {
printf("%s", ss2.str().c_str()); printf("%s", ss2.str().c_str());
} }
init_scr();
for (;;) { for (;;) {
scr_setXY(20, 10);
scr_printf(ss1.str().c_str());
writeAssertLinesInScreen(args...);
scr_printf(ss2.str().c_str());
} }
} }
private: private:
static std::unique_ptr<std::ofstream> logFile; static void writeInLogFile(std::stringstream* ss);
static std::ofstream* getLogFile();
template <typename Arg, typename... Args> template <typename Arg, typename... Args>
static void writeAssertLines(Arg&& arg, Args&&... args) { static void writeAssertLines(Arg&& arg, Args&&... args) {
@@ -105,13 +104,23 @@ class TyraDebug {
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...}; 0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
if (Tyra::Info::writeLogsToFile) { if (Tyra::Info::writeLogsToFile) {
auto* logfile = getLogFile(); writeInLogFile(&ss);
*logfile << ss.str();
logFile->flush();
} else { } else {
printf("%s", ss.str().c_str()); printf("%s", ss.str().c_str());
} }
} }
template <typename Arg, typename... Args>
static void writeAssertLinesInScreen(Arg&& arg, Args&&... args) {
std::stringstream ss;
ss << "| " << std::forward<Arg>(arg) << "\n";
using expander = int[];
(void)expander{
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
scr_printf(ss.str().c_str());
}
}; };
#endif // NDEBUG #endif // NDEBUG
+10 -3
View File
@@ -11,6 +11,8 @@
#pragma once #pragma once
#include <string> #include <string>
#include <limits.h>
#include <syslimits.h>
namespace Tyra { namespace Tyra {
@@ -32,14 +34,19 @@ class FileUtils {
static std::string fromCwd(const std::string& relativePath); static std::string fromCwd(const std::string& relativePath);
static std::string fromCwd(const char* relativePath); static std::string fromCwd(const char* relativePath);
static std::string getFilenameFromPath(const std::string& path);
static std::string getPathFromFilename(const std::string& path);
static std::string getFilenameWithoutExtension(const std::string& filename);
static std::string getExtensionOfFilename(const std::string& filename);
const char* getElfName() const { return elfName; }; const char* getElfName() const { return elfName; };
const char* getElfPath() const { return elfPath; }; const char* getElfPath() const { return elfPath; };
private: private:
// Argv name+path & just path // Argv name+path & just path
char cwd[255]; char cwd[NAME_MAX];
char elfName[255]; char elfName[NAME_MAX];
char elfPath[255 - 14]; char elfPath[NAME_MAX - 14];
void setPathInfo(const char* path); void setPathInfo(const char* path);
}; };
+1 -1
View File
@@ -21,7 +21,7 @@ class Version {
~Version() {} ~Version() {}
static const u8 major = 2; static const u8 major = 2;
static const u8 minor = 0; static const u8 minor = 2;
static const u8 patch = 0; static const u8 patch = 0;
static std::string toString() { static std::string toString() {
+1
View File
@@ -27,6 +27,7 @@ class IrxLoader {
void loadSio2man(const bool& verbose); void loadSio2man(const bool& verbose);
void loadPadman(const bool& verbose); void loadPadman(const bool& verbose);
void loadLibsd(const bool& verbose); void loadLibsd(const bool& verbose);
void loadIO(const bool& verbose);
void loadUsbModules(const bool& verbose); void loadUsbModules(const bool& verbose);
void loadAudsrv(const bool& verbose); void loadAudsrv(const bool& verbose);
@@ -28,7 +28,7 @@ class MeshBuilderData {
std::vector<MeshBuilderMaterialData*> materials; std::vector<MeshBuilderMaterialData*> materials;
bool textureCoordsEnabled, normalsEnabled, lightMapEnabled; bool loadNormals, loadLightmap;
}; };
} // namespace Tyra } // namespace Tyra
@@ -13,6 +13,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <optional>
#include "./mesh_builder_material_frame_data.hpp" #include "./mesh_builder_material_frame_data.hpp"
#include "renderer/models/color.hpp" #include "renderer/models/color.hpp"
@@ -25,6 +26,7 @@ class MeshBuilderMaterialData {
std::vector<MeshBuilderMaterialFrameData*> frames; std::vector<MeshBuilderMaterialFrameData*> frames;
std::string name; std::string name;
std::optional<std::string> texturePath;
Color ambient; Color ambient;
}; };
@@ -10,7 +10,6 @@
#pragma once #pragma once
#include "../../loader.hpp"
#include "../builder/mesh_builder_data.hpp" #include "../builder/mesh_builder_data.hpp"
#include <string> #include <string>
#include <memory> #include <memory>
@@ -23,7 +22,7 @@ struct MD2LoaderOptions {
}; };
/** Class responsible for loading & parsing Quake's II ".md2" 3D files */ /** Class responsible for loading & parsing Quake's II ".md2" 3D files */
class MD2Loader : public Loader { class MD2Loader {
public: public:
static std::unique_ptr<MeshBuilderData> load(const char* fullpath); static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
static std::unique_ptr<MeshBuilderData> load(const char* fullpath, static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
@@ -10,12 +10,12 @@
#pragma once #pragma once
#include "../../loader.hpp"
#include "../builder/mesh_builder_data.hpp" #include "../builder/mesh_builder_data.hpp"
#include <string> #include <string>
#include "renderer/models/color.hpp" #include "renderer/models/color.hpp"
#include "loaders/3d/obj_loader/tiny_obj_loader.hpp" #include "loaders/3d/obj_loader/tiny_obj_loader.hpp"
#include <memory.h> #include <memory.h>
#include <optional>
namespace Tyra { namespace Tyra {
@@ -36,7 +36,7 @@ struct MaterialVertexCount {
}; };
/** Class responsible for loading & parsing obj files */ /** Class responsible for loading & parsing obj files */
class ObjLoader : public Loader { class ObjLoader {
public: public:
static std::unique_ptr<MeshBuilderData> load(const char* fullpath); static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
static std::unique_ptr<MeshBuilderData> load(const char* fullpath, static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
-25
View File
@@ -1,25 +0,0 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#pragma once
#include <string>
namespace Tyra {
class Loader {
protected:
static std::string getFilenameFromPath(const std::string& path);
static std::string getPathFromFilename(const std::string& path);
static std::string getFilenameWithoutExtension(const std::string& filename);
static std::string getExtensionOfFilename(const std::string& filename);
};
} // namespace Tyra
@@ -10,13 +10,12 @@
#pragma once #pragma once
#include "loaders/loader.hpp"
#include "loaders/texture/builder/texture_builder_data.hpp" #include "loaders/texture/builder/texture_builder_data.hpp"
#include "renderer/core/texture/models/texture_bpp.hpp" #include "renderer/core/texture/models/texture_bpp.hpp"
#include <string> #include <string>
namespace Tyra { namespace Tyra {
class TextureLoader : public Loader { class TextureLoader {
public: public:
/** /**
* @brief Loads texture data from file. * @brief Loads texture data from file.
@@ -33,4 +33,5 @@ class TextureBuilderData {
TextureBpp clutBpp; TextureBpp clutBpp;
unsigned char clutGsComponents; unsigned char clutGsComponents;
}; };
} // namespace Tyra } // namespace Tyra
-3
View File
@@ -36,9 +36,6 @@ class Math {
static int randomi(const int& min, const int& max); static int randomi(const int& min, const int& max);
static bool equalf(const float& a, const float& b, static bool equalf(const float& a, const float& b,
const float& epsilon = 0.00001F); const float& epsilon = 0.00001F);
private:
Math();
}; };
} // namespace Tyra } // namespace Tyra
@@ -13,6 +13,7 @@
#include "debug/debug.hpp" #include "debug/debug.hpp"
#include "./mesh_material_frame.hpp" #include "./mesh_material_frame.hpp"
#include "loaders/3d/builder/mesh_builder_data.hpp" #include "loaders/3d/builder/mesh_builder_data.hpp"
#include <optional>
namespace Tyra { namespace Tyra {
@@ -23,11 +24,9 @@ class MeshMaterial {
~MeshMaterial(); ~MeshMaterial();
bool isMother, lightmapFlag; bool isMother, lightmapFlag;
u32 id; u32 id;
std::string name; std::string name;
std::optional<std::string> textureName;
Color ambient; Color ambient;
std::vector<MeshMaterialFrame*> frames; std::vector<MeshMaterialFrame*> frames;
@@ -44,8 +44,7 @@ class DynPipRenderer {
void uploadPrograms(); void uploadPrograms();
void setDoubleBuffer(); void setDoubleBuffer();
void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag** bags, void addBufferDataToPacket(DynPipBag** bags, const u32& count);
const u32& count);
void sendPacket(); void sendPacket();
prim_t* prim; prim_t* prim;
@@ -59,7 +59,7 @@ class DynamicPipeline : public Renderer3DPipeline {
void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex); void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex);
void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex); void sendRestOfBuffers(DynPipBag* buffers, const u16& bufferIndex);
void addVertices(const MeshMaterialFrame* materialFrameFrom, void addVertices(const MeshMaterialFrame* materialFrameFrom,
const MeshMaterialFrame* materialFrameTo, DynPipBag* bag, const MeshMaterialFrame* materialFrameTo, DynPipBag* bag,
@@ -13,6 +13,7 @@
#include "debug/debug.hpp" #include "debug/debug.hpp"
#include "renderer/core/2d/sprite/sprite.hpp" #include "renderer/core/2d/sprite/sprite.hpp"
#include "renderer/core/texture/renderer_core_texture_buffers.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/core/texture/models/texture.hpp"
#include "renderer/renderer_settings.hpp" #include "renderer/renderer_settings.hpp"
#include <packet2_utils.h> #include <packet2_utils.h>
@@ -30,6 +31,9 @@ class RendererCore2D {
void render(const Sprite& sprite, void render(const Sprite& sprite,
const RendererCoreTextureBuffers& texBuffers, Texture* texture); const RendererCoreTextureBuffers& texBuffers, Texture* texture);
void setTextureMappingType(
const PipelineTextureMappingType textureMappingType);
private: private:
void setPrim(); void setPrim();
void setLod(); void setLod();
@@ -24,7 +24,7 @@ class Sprite {
~Sprite(); ~Sprite();
u32 id; u32 id;
Vec2 position, size; Vec2 position, size, offset;
float scale; float scale;
Color color; Color color;
SpriteMode mode; SpriteMode mode;
@@ -62,7 +62,8 @@ class Texture {
/** Set texture wrapping */ /** Set texture wrapping */
void setWrapSettings(const TextureWrap t_horizontal, void setWrapSettings(const TextureWrap t_horizontal,
const TextureWrap t_vertical); const TextureWrap t_vertical, int minu = 0, int minv = 0,
int maxu = 0, int maxv = 0);
// ---- // ----
// Other // Other
@@ -96,9 +97,10 @@ class Texture {
void print(const std::string& name) const { print(name.c_str()); } void print(const std::string& name) const { print(name.c_str()); }
std::string getPrint(const char* name = nullptr) const; std::string getPrint(const char* name = nullptr) const;
void setDefaultWrapSettings();
private: private:
void setPsm(); void setPsm();
void setDefaultWrapSettings();
texwrap_t wrap; texwrap_t wrap;
}; };
@@ -29,6 +29,12 @@ class RendererCoreTexture {
RendererCoreTextureBuffers useTexture(const Texture* t_tex); RendererCoreTextureBuffers useTexture(const Texture* t_tex);
/**
* Called by user after changing texture wrap settings
* Updates texture packet without reallocate it
*/
RendererCoreTextureBuffers updateTextureInfo(const Texture* t_tex);
/** Called by renderer during initialization */ /** Called by renderer during initialization */
void init(RendererCoreGS* gs, Path3* path3); void init(RendererCoreGS* gs, Path3* path3);
@@ -16,6 +16,7 @@
#include "./models/texture.hpp" #include "./models/texture.hpp"
#include "renderer/3d/mesh/mesh.hpp" #include "renderer/3d/mesh/mesh.hpp"
#include "renderer/core/2d/sprite/sprite.hpp" #include "renderer/core/2d/sprite/sprite.hpp"
#include "./renderer_core_texture_buffers.hpp"
#include "loaders/texture/base/texture_loader_selector.hpp" #include "loaders/texture/base/texture_loader_selector.hpp"
#include <string> #include <string>
@@ -25,6 +26,8 @@ class TextureRepository {
TextureRepository(); TextureRepository();
~TextureRepository(); ~TextureRepository();
void init(std::vector<RendererCoreTextureBuffers>* textureBuffers);
/** Returns all repository textures. */ /** Returns all repository textures. */
std::vector<Texture*>* getAll() { return &textures; } std::vector<Texture*>* getAll() { return &textures; }
@@ -99,6 +102,13 @@ class TextureRepository {
void freeByMesh(const Mesh& mesh); void freeByMesh(const Mesh& mesh);
void freeByMesh(const Mesh* mesh); void freeByMesh(const Mesh* mesh);
/**
* remove texture buffer id if exist.
* Texture buffer is NOT destructed.
* easy way to create another texture buffer.
*/
int removeBufferId(const u32& t_texId);
/** /**
* Remove texture from repository. * Remove texture from repository.
* Texture is NOT destructed. * Texture is NOT destructed.
@@ -110,6 +120,7 @@ class TextureRepository {
void removeByIndex(const u32& t_index); void removeByIndex(const u32& t_index);
std::vector<Texture*> textures; std::vector<Texture*> textures;
std::vector<RendererCoreTextureBuffers>* textureBuffers;
TextureLoaderSelector texLoaderSelector; TextureLoaderSelector texLoaderSelector;
}; };
} // namespace Tyra } // namespace Tyra
+1 -1
View File
@@ -22,7 +22,7 @@ class RendererSettings {
height(448.0F), height(448.0F),
interlacedHeightF(height / 2), interlacedHeightF(height / 2),
near(0.1F), near(0.1F),
far(8192.0F), far(51200.0F),
projectionScale(4096.0F), projectionScale(4096.0F),
aspectRatio(width / height), aspectRatio(width / height),
interlacedHeightUI(static_cast<unsigned int>(interlacedHeightF)) {} interlacedHeightUI(static_cast<unsigned int>(interlacedHeightF)) {}
-1
View File
@@ -6,7 +6,6 @@
# Copyright 2022, tyra - https://github.com/h4570/tyra # Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0 # Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#include "audio/audio.hpp" #include "audio/audio.hpp"
-1
View File
@@ -6,7 +6,6 @@
# Copyright 2022, tyra - https://github.com/h4570/tyra # Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0 # Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#include "audio/audio_adpcm.hpp" #include "audio/audio_adpcm.hpp"
+1 -1
View File
@@ -6,7 +6,6 @@
# Copyright 2022, tyra - https://github.com/h4570/tyra # Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0 # Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com> # Sandro Sobczyński <sandro.sobczynski@gmail.com>
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/ */
#include "audio/audio_song.hpp" #include "audio/audio_song.hpp"
@@ -149,6 +148,7 @@ void AudioSong::work() {
if (chunkReadStatus > 0) { if (chunkReadStatus > 0) {
WaitSema(fillbufferSema); // wait until previous chunk wasn't finished WaitSema(fillbufferSema); // wait until previous chunk wasn't finished
audsrv_wait_audio(chunkReadStatus);
audsrv_play_audio(chunk, chunkReadStatus); audsrv_play_audio(chunk, chunkReadStatus);
for (u32 i = 0; i < getListenersCount(); i++) for (u32 i = 0; i < getListenersCount(); i++)
songListeners[i]->listener->onAudioTick(); songListeners[i]->listener->onAudioTick();
+8 -13
View File
@@ -10,16 +10,11 @@
#include "debug/debug.hpp" #include "debug/debug.hpp"
std::unique_ptr<std::ofstream> TyraDebug::logFile; void TyraDebug::writeInLogFile(std::stringstream* ss) {
std::ofstream logFile;
std::ofstream* TyraDebug::getLogFile() { logFile.open(Tyra::FileUtils::fromCwd("log.txt"),
if (logFile) { std::ofstream::out | std::ofstream::app);
return logFile.get(); logFile << ss->str();
} else { logFile.flush();
logFile = std::make_unique<std::ofstream>(); // logFile.close();
logFile->open(Tyra::FileUtils::fromCwd("log.txt"), }
std::ofstream::out | std::ofstream::app);
return logFile.get();
}
} // namespace Tyra
+29 -2
View File
@@ -12,8 +12,7 @@
#include <tamtypes.h> #include <tamtypes.h>
#include <cstdio> #include <cstdio>
#include <kernel.h> #include <kernel.h>
#include <limits.h>
#include <syslimits.h>
#include <unistd.h> #include <unistd.h>
#include <cstring> #include <cstring>
#include "file/file_utils.hpp" #include "file/file_utils.hpp"
@@ -64,4 +63,32 @@ std::string FileUtils::fromCwd(const char* file) {
auto cwd = getCwd(); auto cwd = getCwd();
return cwd + file; return cwd + file;
} }
std::string FileUtils::getFilenameFromPath(const std::string& path) {
std::string filename = path.substr(path.find_last_of("/\\") + 1);
if (filename.size() == path.size()) {
filename = path.substr(path.find_last_of(":\\") + 1);
}
return filename;
}
std::string FileUtils::getPathFromFilename(const std::string& path) {
std::string basepath = path.substr(0, path.find_last_of("/\\"));
if (basepath.size() == path.size()) {
basepath = path.substr(0, path.find_last_of(":\\"));
}
return basepath;
}
std::string FileUtils::getFilenameWithoutExtension(
const std::string& filename) {
auto lastindex = filename.find_last_of(".");
return filename.substr(0, lastindex);
}
std::string FileUtils::getExtensionOfFilename(const std::string& filename) {
auto lastindex = filename.find_last_of(".");
return filename.substr(lastindex + 1);
}
} // namespace Tyra } // namespace Tyra
+2
View File
@@ -0,0 +1,2 @@
$PS2SDK/iop/irx/fileXio.irx
fileXio_irx
+2
View File
@@ -0,0 +1,2 @@
$PS2SDK/iop/irx/iomanX.irx
iomanX_irx
+32 -23
View File
@@ -20,30 +20,20 @@
#include "file/file_utils.hpp" #include "file/file_utils.hpp"
// external IRX modules // external IRX modules
#define EXTERN_IRX(_irx) \
extern u8 _irx[]; \
extern int size_##_irx
extern u8 sio2man_irx[]; EXTERN_IRX(sio2man_irx);
extern int size_sio2man_irx; EXTERN_IRX(padman_irx);
EXTERN_IRX(audsrv_irx);
extern u8 padman_irx[]; EXTERN_IRX(libsd_irx);
extern int size_padman_irx; EXTERN_IRX(fileXio_irx);
EXTERN_IRX(iomanX_irx);
extern u8 audsrv_irx[]; EXTERN_IRX(bdm_irx);
extern int size_audsrv_irx; EXTERN_IRX(bdmfs_fatfs_irx);
EXTERN_IRX(usbd_irx);
extern u8 libsd_irx[]; EXTERN_IRX(usbmass_bd_irx);
extern int size_libsd_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;
namespace Tyra { namespace Tyra {
@@ -70,6 +60,7 @@ void IrxLoader::loadAll(const bool& withUsb, const bool& isLoggingToFile) {
return; return;
} }
loadIO(!isLoggingToFile);
loadSio2man(!isLoggingToFile); loadSio2man(!isLoggingToFile);
loadPadman(!isLoggingToFile); loadPadman(!isLoggingToFile);
loadLibsd(!isLoggingToFile); loadLibsd(!isLoggingToFile);
@@ -116,6 +107,24 @@ void IrxLoader::loadLibsd(const bool& verbose) {
if (verbose) TYRA_LOG("IRX: Libsd loaded!"); if (verbose) TYRA_LOG("IRX: Libsd loaded!");
} }
void IrxLoader::loadIO(const bool& verbose) {
int ret;
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) { void IrxLoader::loadUsbModules(const bool& verbose) {
if (verbose) TYRA_LOG("IRX: Loading usb modules..."); if (verbose) TYRA_LOG("IRX: Loading usb modules...");
@@ -14,9 +14,8 @@
namespace Tyra { namespace Tyra {
MeshBuilderData::MeshBuilderData() { MeshBuilderData::MeshBuilderData() {
textureCoordsEnabled = false; loadNormals = false;
normalsEnabled = false; loadLightmap = false;
lightMapEnabled = false;
} }
MeshBuilderData::~MeshBuilderData() { MeshBuilderData::~MeshBuilderData() {
@@ -13,7 +13,7 @@
#include <string> #include <string>
#include "debug/debug.hpp" #include "debug/debug.hpp"
#include "loaders/3d/md2_loader/anorms.hpp" #include "loaders/3d/md2_loader/anorms.hpp"
#include "loaders/loader.hpp" #include "file/file_utils.hpp"
namespace Tyra { namespace Tyra {
@@ -88,7 +88,7 @@ std::unique_ptr<MeshBuilderData> MD2Loader::load(const char* fullpath,
std::string path = fullpath; std::string path = fullpath;
TYRA_ASSERT(!path.empty(), "Provided path is empty!"); TYRA_ASSERT(!path.empty(), "Provided path is empty!");
auto filename = getFilenameFromPath(path); auto filename = FileUtils::getFilenameFromPath(path);
FILE* file = fopen(fullpath, "rb"); FILE* file = fopen(fullpath, "rb");
TYRA_ASSERT(file != nullptr, "Failed to load: ", filename); TYRA_ASSERT(file != nullptr, "Failed to load: ", filename);
@@ -122,12 +122,13 @@ std::unique_ptr<MeshBuilderData> MD2Loader::load(const char* fullpath,
auto result = std::make_unique<MeshBuilderData>(); auto result = std::make_unique<MeshBuilderData>();
auto* material = new MeshBuilderMaterialData(); auto* material = new MeshBuilderMaterialData();
material->name = getFilenameWithoutExtension(filename); material->name = FileUtils::getFilenameWithoutExtension(filename);
material->texturePath = material->name;
material->texturePath.value().append(".png");
result->materials.push_back(material); result->materials.push_back(material);
result->normalsEnabled = true; result->loadNormals = true;
result->textureCoordsEnabled = true; result->loadLightmap = false;
result->lightMapEnabled = false;
Vec4** tempVertices = new Vec4*[framesCount]; Vec4** tempVertices = new Vec4*[framesCount];
Vec4** tempNormals = new Vec4*[framesCount]; Vec4** tempNormals = new Vec4*[framesCount];
+41 -17
View File
@@ -10,13 +10,13 @@
#include <cstring> #include <cstring>
#include <stdio.h> #include <stdio.h>
#include <string>
#include <vector> #include <vector>
#include "math/vec2.hpp" #include "math/vec2.hpp"
#include "math/vec4.hpp" #include "math/vec4.hpp"
#include "renderer/models/color.hpp" #include "renderer/models/color.hpp"
#include "debug/debug.hpp" #include "debug/debug.hpp"
#include "loaders/3d/obj_loader/obj_loader.hpp" #include "loaders/3d/obj_loader/obj_loader.hpp"
#include "file/file_utils.hpp"
#define TINYOBJLOADER_USE_MAPBOX_EARCUT #define TINYOBJLOADER_USE_MAPBOX_EARCUT
#define TINYOBJLOADER_IMPLEMENTATION #define TINYOBJLOADER_IMPLEMENTATION
@@ -40,12 +40,12 @@ std::unique_ptr<MeshBuilderData> ObjLoader::load(
std::unique_ptr<MeshBuilderData> ObjLoader::load( std::unique_ptr<MeshBuilderData> ObjLoader::load(
const char* fullpath, const ObjLoaderOptions& options) { const char* fullpath, const ObjLoaderOptions& options) {
std::string path = fullpath; std::string path = fullpath;
std::string basePath = getPathFromFilename(path); std::string basePath = FileUtils::getPathFromFilename(path);
TYRA_ASSERT(!path.empty(), "Provided path is empty!"); TYRA_ASSERT(!path.empty(), "Provided path is empty!");
auto rawFilename = getFilenameWithoutExtension(path); auto rawFilename = FileUtils::getFilenameWithoutExtension(path);
auto extension = getExtensionOfFilename(path); auto extension = FileUtils::getExtensionOfFilename(path);
auto result = std::make_unique<MeshBuilderData>(); auto result = std::make_unique<MeshBuilderData>();
tinyobj::ObjReaderConfig readerConfig; tinyobj::ObjReaderConfig readerConfig;
@@ -131,9 +131,7 @@ void ObjLoader::addOutputMaterialsAndFrames(
const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::shape_t>& shapes,
const std::vector<tinyobj::material_t>& materials, const u16& framesCount, const std::vector<tinyobj::material_t>& materials, const u16& framesCount,
std::vector<MaterialVertexCount>& materialVertexCounts) { std::vector<MaterialVertexCount>& materialVertexCounts) {
if (attrib.texcoords.size()) output->textureCoordsEnabled = true; if (attrib.normals.size()) output->loadNormals = true;
if (attrib.normals.size()) output->normalsEnabled = true;
TYRA_ASSERT(materials.size() > 0, TYRA_ASSERT(materials.size() > 0,
"No material data found! Please add .mtl " "No material data found! Please add .mtl "
@@ -145,6 +143,10 @@ void ObjLoader::addOutputMaterialsAndFrames(
material->name = materials[i].name; material->name = materials[i].name;
if (!materials[i].diffuse_texname.empty()) {
material->texturePath = materials[i].diffuse_texname;
}
material->ambient.set(materials[i].diffuse[0] * 128.0F, material->ambient.set(materials[i].diffuse[0] * 128.0F,
materials[i].diffuse[1] * 128.0F, materials[i].diffuse[1] * 128.0F,
materials[i].diffuse[2] * 128.0F, 128.0F); materials[i].diffuse[2] * 128.0F, 128.0F);
@@ -157,10 +159,11 @@ void ObjLoader::addOutputMaterialsAndFrames(
frame->count = counter.count; frame->count = counter.count;
frame->vertices = new Vec4[counter.count]; frame->vertices = new Vec4[counter.count];
if (output->textureCoordsEnabled) if (material->texturePath.has_value()) {
frame->textureCoords = new Vec4[counter.count]; frame->textureCoords = new Vec4[counter.count];
}
if (output->normalsEnabled) frame->normals = new Vec4[counter.count]; if (output->loadNormals) frame->normals = new Vec4[counter.count];
material->frames.push_back(frame); material->frames.push_back(frame);
} }
@@ -186,6 +189,8 @@ void ObjLoader::importFrame(MeshBuilderData* output,
materialInsertControls.push_back(control); materialInsertControls.push_back(control);
} }
std::vector<u32> materialIdsWithTextureWarning;
// Loop over shapes // Loop over shapes
for (size_t s = 0; s < shapes.size(); s++) { for (size_t s = 0; s < shapes.size(); s++) {
const auto& mesh = shapes[s].mesh; const auto& mesh = shapes[s].mesh;
@@ -197,7 +202,8 @@ void ObjLoader::importFrame(MeshBuilderData* output,
auto& materialInsertControl = materialInsertControls[materialId]; auto& materialInsertControl = materialInsertControls[materialId];
size_t vertCountPerFace = size_t(mesh.num_face_vertices[f]); size_t vertCountPerFace = size_t(mesh.num_face_vertices[f]);
auto* outFrame = output->materials[materialId]->frames[frameIndex]; auto* outMaterial = output->materials[materialId];
auto* outFrame = outMaterial->frames[frameIndex];
TYRA_ASSERT(count == 1 || vertCountPerFace == 3, TYRA_ASSERT(count == 1 || vertCountPerFace == 3,
"Please triangulate obj files if you are animating!", "Please triangulate obj files if you are animating!",
@@ -232,14 +238,32 @@ void ObjLoader::importFrame(MeshBuilderData* output,
// Check if `texcoord_index` is zero or positive. negative = // Check if `texcoord_index` is zero or positive. negative =
// notexcoord data // notexcoord data
if (idx.texcoord_index >= 0) { if (idx.texcoord_index >= 0) {
tinyobj::real_t tx = if (outMaterial->texturePath.has_value()) {
attrib.texcoords[2 * size_t(idx.texcoord_index) + 0]; tinyobj::real_t tx =
tinyobj::real_t ty = attrib.texcoords[2 * size_t(idx.texcoord_index) + 0];
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1]; tinyobj::real_t ty =
attrib.texcoords[2 * size_t(idx.texcoord_index) + 1];
auto finalY = invertY ? 1.0F - ty : ty; auto finalY = invertY ? 1.0F - ty : ty;
outFrame->textureCoords[materialInsertControl.inserted].set( outFrame->textureCoords[materialInsertControl.inserted].set(
tx, finalY, 1.0F, 0.0F); tx, finalY, 1.0F, 0.0F);
} else {
auto warningWasNotPrinted =
std::find(materialIdsWithTextureWarning.begin(),
materialIdsWithTextureWarning.end(),
materialId) == materialIdsWithTextureWarning.end();
if (frameIndex == 0 && warningWasNotPrinted) {
materialIdsWithTextureWarning.push_back(materialId);
TYRA_WARN(
"Material \"", outMaterial->name,
"\" has texture coordinates, but texture path was not found "
"in .mtl file! ",
"Please consider adding texture path to map_Kd field in .mtl "
"file!");
}
}
} }
materialInsertControl.inserted++; materialInsertControl.inserted++;
-42
View File
@@ -1,42 +0,0 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "loaders/loader.hpp"
namespace Tyra {
std::string Loader::getFilenameFromPath(const std::string& path) {
std::string filename = path.substr(path.find_last_of("/\\") + 1);
if (filename.size() == path.size()) {
filename = path.substr(path.find_last_of(":\\") + 1);
}
return filename;
}
std::string Loader::getPathFromFilename(const std::string& path) {
std::string basepath = path.substr(0, path.find_last_of("/\\"));
if (basepath.size() == path.size()) {
basepath = path.substr(0, path.find_last_of(":\\"));
}
return basepath;
}
std::string Loader::getFilenameWithoutExtension(const std::string& filename) {
auto lastindex = filename.find_last_of(".");
return filename.substr(0, lastindex);
}
std::string Loader::getExtensionOfFilename(const std::string& filename) {
auto lastindex = filename.find_last_of(".");
return filename.substr(lastindex + 1);
}
} // namespace Tyra
+2 -9
View File
@@ -16,6 +16,7 @@
#include <string> #include <string>
#include <draw_buffers.h> #include <draw_buffers.h>
#include "loaders/texture/png_loader.hpp" #include "loaders/texture/png_loader.hpp"
#include "file/file_utils.hpp"
namespace Tyra { namespace Tyra {
@@ -32,7 +33,7 @@ TextureBuilderData* PngLoader::load(const char* fullPath) {
std::string path = fullPath; std::string path = fullPath;
TYRA_ASSERT(!path.empty(), "Provided path is empty!"); TYRA_ASSERT(!path.empty(), "Provided path is empty!");
auto filename = getFilenameFromPath(path); auto filename = FileUtils::getFilenameFromPath(path);
FILE* file = fopen(fullPath, "rb"); FILE* file = fopen(fullPath, "rb");
TYRA_ASSERT(file != nullptr, "Failed to load ", fullPath); TYRA_ASSERT(file != nullptr, "Failed to load ", fullPath);
@@ -210,10 +211,6 @@ void PngLoader::handle8bppPalletized(TextureBuilderData* result,
auto* pixel = static_cast<unsigned char*>(result->data); auto* pixel = static_cast<unsigned char*>(result->data);
struct PngClut* clut = (struct PngClut*)result->clut; struct PngClut* clut = (struct PngClut*)result->clut;
for (int i = numPallete; i < 256; i++) {
memset(&clut[i], 0, sizeof(clut[i]));
}
for (int i = 0; i < numPallete; i++) { for (int i = 0; i < numPallete; i++) {
clut[i].r = palette[i].red; clut[i].r = palette[i].red;
clut[i].g = palette[i].green; clut[i].g = palette[i].green;
@@ -272,10 +269,6 @@ void PngLoader::handle4bppPalletized(TextureBuilderData* result,
auto* pixel = static_cast<unsigned char*>(result->data); auto* pixel = static_cast<unsigned char*>(result->data);
struct PngClut* clut = (struct PngClut*)result->clut; struct PngClut* clut = (struct PngClut*)result->clut;
for (int i = numPallete; i < 16; i++) {
memset(&clut[i], 0, sizeof(clut[i]));
}
for (int i = 0; i < numPallete; i++) { for (int i = 0; i < numPallete; i++) {
clut[i].r = palette[i].red; clut[i].r = palette[i].red;
clut[i].g = palette[i].green; clut[i].g = palette[i].green;
+18 -5
View File
@@ -14,6 +14,7 @@
#include <cstdlib> #include <cstdlib>
#include <iomanip> #include <iomanip>
#include "renderer/3d/mesh/mesh_material.hpp" #include "renderer/3d/mesh/mesh_material.hpp"
#include "file/file_utils.hpp"
namespace Tyra { namespace Tyra {
@@ -29,7 +30,7 @@ MeshMaterial::MeshMaterial(const MeshBuilderData& data,
id = rand() % 1000000; id = rand() % 1000000;
if (data.lightMapEnabled) { if (data.loadLightmap) {
lightmapFlag = true; lightmapFlag = true;
TYRA_ASSERT(material->frames[0]->colors != nullptr, TYRA_ASSERT(material->frames[0]->colors != nullptr,
"Colors faces are required"); "Colors faces are required");
@@ -38,8 +39,15 @@ MeshMaterial::MeshMaterial(const MeshBuilderData& data,
} }
ambient.set(material->ambient); ambient.set(material->ambient);
name = material->name; name = material->name;
if (material->texturePath.has_value()) {
auto textureFilename =
FileUtils::getFilenameFromPath(material->texturePath.value());
textureName = FileUtils::getFilenameWithoutExtension(textureFilename);
}
TYRA_ASSERT(name.length() > 0, "MeshMaterial name cannot be empty"); TYRA_ASSERT(name.length() > 0, "MeshMaterial name cannot be empty");
u32 lastVertexCount = 0; u32 lastVertexCount = 0;
@@ -71,7 +79,7 @@ MeshMaterial::MeshMaterial(const MeshMaterial& mesh) {
lightmapFlag = mesh.lightmapFlag; lightmapFlag = mesh.lightmapFlag;
name = mesh.name; name = mesh.name;
textureName = mesh.textureName;
ambient.set(128.0F, 128.0F, 128.0F, 128.0F); ambient.set(128.0F, 128.0F, 128.0F, 128.0F);
for (u32 i = 0; i < mesh.frames.size(); i++) { for (u32 i = 0; i < mesh.frames.size(); i++) {
@@ -112,9 +120,14 @@ std::string MeshMaterial::getPrint(const char* name) const {
res << std::endl; res << std::endl;
res << std::fixed << std::setprecision(2); res << std::fixed << std::setprecision(2);
res << "Id: " << id << ", " << std::endl; res << "Id: " << id << ", " << std::endl;
res << "Name: " << name << ", " << std::endl; res << "Name: " << this->name << ", " << std::endl;
if (textureName.has_value()) {
res << "Texture path: " << textureName.value() << ", " << std::endl;
}
res << "Frames count: " << frames.size() << ", " << std::endl; res << "Frames count: " << frames.size() << ", " << std::endl;
res << "Single color?: " << static_cast<u32>(lightmapFlag) << std::endl; res << "Lightmap?: " << static_cast<u32>(lightmapFlag) << std::endl;
res << ")"; res << ")";
return res.str(); return res.str();
@@ -36,11 +36,12 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
TYRA_ASSERT(frame->count > 0, "Vertex count must be greater than 0", TYRA_ASSERT(frame->count > 0, "Vertex count must be greater than 0",
"Material name: ", material->name); "Material name: ", material->name);
TYRA_ASSERT(frame->vertices != nullptr, "Vertex array can't be null"); TYRA_ASSERT(frame->vertices != nullptr, "Vertex array can't be null");
TYRA_ASSERT(!data.normalsEnabled || frame->normals != nullptr, TYRA_ASSERT(!data.loadNormals || frame->normals != nullptr,
"Normal array can't be null"); "Normal array can't be null");
TYRA_ASSERT(!data.textureCoordsEnabled || frame->textureCoords != nullptr, TYRA_ASSERT(
"Texture coordinate array can't be null"); !material->texturePath.has_value() || frame->textureCoords != nullptr,
TYRA_ASSERT(!data.lightMapEnabled || frame->colors != nullptr, "Texture coordinate array can't be null");
TYRA_ASSERT(!data.loadLightmap || frame->colors != nullptr,
"Color array can't be null"); "Color array can't be null");
bbox = new BBox(frame->vertices, frame->count); bbox = new BBox(frame->vertices, frame->count);
@@ -48,7 +49,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
count = frame->count; count = frame->count;
vertices = frame->vertices; vertices = frame->vertices;
if (data.normalsEnabled) { if (data.loadNormals) {
normals = frame->normals; normals = frame->normals;
} else { } else {
if (frame->normals != nullptr) delete[] frame->normals; if (frame->normals != nullptr) delete[] frame->normals;
@@ -56,7 +57,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
normals = nullptr; normals = nullptr;
} }
if (data.textureCoordsEnabled) { if (material->texturePath.has_value()) {
textureCoords = frame->textureCoords; textureCoords = frame->textureCoords;
} else { } else {
if (frame->textureCoords != nullptr) delete[] frame->textureCoords; if (frame->textureCoords != nullptr) delete[] frame->textureCoords;
@@ -64,7 +65,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
textureCoords = nullptr; textureCoords = nullptr;
} }
if (data.lightMapEnabled) { if (data.loadLightmap) {
colors = frame->colors; colors = frame->colors;
} else { } else {
if (frame->colors != nullptr) delete[] frame->colors; if (frame->colors != nullptr) delete[] frame->colors;
@@ -160,19 +160,19 @@ void DynPipRenderer::sendObjectData(
void DynPipRenderer::render(DynPipBag** bags, const u32& count) { void DynPipRenderer::render(DynPipBag** bags, const u32& count) {
if (count <= 0) return; if (count <= 0) return;
auto* program = programsRepo->getProgramByBag(bags[0]); addBufferDataToPacket(bags, count);
addBufferDataToPacket(program, bags, count);
sendPacket(); sendPacket();
} }
void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program, void DynPipRenderer::addBufferDataToPacket(DynPipBag** bags, const u32& count) {
DynPipBag** bags, const u32& count) {
currentPacket = packets[context]; currentPacket = packets[context];
packet2_reset(currentPacket, false); packet2_reset(currentPacket, false);
for (u32 i = 0; i < count; i++) { for (u32 i = 0; i < count; i++) {
if (bags[i]->count <= 0) continue; if (bags[i]->count <= 0) continue;
auto* program = programsRepo->getProgramByBag(bags[i]);
program->addBufferDataToPacket(currentPacket, bags[i], prim); program->addBufferDataToPacket(currentPacket, bags[i], prim);
if (lastProgramName != program->getName()) { if (lastProgramName != program->getName()) {
@@ -35,6 +35,11 @@ void DynamicPipeline::onUse() {
buffers = new DynPipBag[buffersCount]; buffers = new DynPipBag[buffersCount];
for (u32 i = 0; i < buffersCount; i++) {
buffers[i].texture = nullptr;
buffers[i].lighting = nullptr;
}
auto packetSize = auto packetSize =
buffersCount * 5.1F; // 5.1 = packet2_get_qw_count / buffersCount buffersCount * 5.1F; // 5.1 = packet2_get_qw_count / buffersCount
@@ -96,11 +101,12 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
for (u32 i = 0; i < mesh->materials.size(); i++) { for (u32 i = 0; i < mesh->materials.size(); i++) {
auto* material = mesh->materials[i]; auto* material = mesh->materials[i];
auto* frameFrom = material->frames[mesh->animation.getState().currentFrame]; auto* frameFrom = material->frames[mesh->animation.getState().currentFrame];
auto* frameTo = material->frames[mesh->animation.getState().nextFrame]; auto* frameTo = material->frames[mesh->animation.getState().nextFrame];
auto partSize = core.getMaxVertCountByParams( auto partSize = core.getMaxVertCountByParams(
options && options->lighting, material->frames[0]->textureCoords); options && options->lighting, material->textureName.has_value());
u32 partsCount = ceil(frameFrom->count / static_cast<float>(partSize)); u32 partsCount = ceil(frameFrom->count / static_cast<float>(partSize));
@@ -109,13 +115,17 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
setBuffersColorBag(buffers, colorBag); setBuffersColorBag(buffers, colorBag);
u8 isPartInitialized = false; u8 isPartInitialized = false;
auto* texture = Texture* texture = nullptr;
rendererCore->texture.repository.getByMeshMaterialId(material->id);
TYRA_ASSERT(texture, "Texture for material: ", material->name, if (material->textureName.has_value()) {
"Id: ", material->id, texture =
"Was not found in texture repository! Did you forget to add " rendererCore->texture.repository.getByMeshMaterialId(material->id);
"texture or disable texture coords loading in mesh?");
TYRA_ASSERT(texture, "Texture for material: ", material->name,
"Id: ", material->id,
"Was not found in texture repository! Did you forget to add "
"texture or disable texture coords loading in mesh?");
}
for (u32 k = 0; k < partsCount; k++) { for (u32 k = 0; k < partsCount; k++) {
auto& buffer = buffers[bufferIndex]; auto& buffer = buffers[bufferIndex];
@@ -127,6 +137,7 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
u32 startIndex = k * partSize; u32 startIndex = k * partSize;
addVertices(frameFrom, frameTo, &buffer, startIndex); addVertices(frameFrom, frameTo, &buffer, startIndex);
buffer.texture = getTextureBag(texture, frameFrom, frameTo, startIndex); buffer.texture = getTextureBag(texture, frameFrom, frameTo, startIndex);
buffer.lighting = getLightingBag(frameFrom, frameTo, &model, options, buffer.lighting = getLightingBag(frameFrom, frameTo, &model, options,
dirLights, startIndex); dirLights, startIndex);
@@ -139,11 +150,13 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
setBuffer(buffers, &buffer, &bufferIndex); setBuffer(buffers, &buffer, &bufferIndex);
} }
sendRestOfBuffers(buffers, bufferIndex);
bufferIndex = 0;
core.begin(infoBag);
delete colorBag; delete colorBag;
} }
sendRestOfBuffers(buffers, &bufferIndex);
if (dirLights) { if (dirLights) {
delete dirLights; delete dirLights;
} }
@@ -177,11 +190,12 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
*bufferIndex += 1; *bufferIndex += 1;
} }
void DynamicPipeline::sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex) { void DynamicPipeline::sendRestOfBuffers(DynPipBag* buffers,
auto isEndOf1stDBuffer = *bufferIndex <= halfBuffersCount - 1; const u16& bufferIndex) {
auto isEndOf1stDBuffer = bufferIndex <= halfBuffersCount - 1;
u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount; u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount;
u32 size = *bufferIndex - offset; u32 size = bufferIndex - offset;
if (size <= 0) return; if (size <= 0) return;
@@ -258,7 +272,7 @@ DynPipColorBag* DynamicPipeline::getColorBag(
DynPipTextureBag* DynamicPipeline::getTextureBag( DynPipTextureBag* DynamicPipeline::getTextureBag(
Texture* texture, const MeshMaterialFrame* materialFrameFrom, Texture* texture, const MeshMaterialFrame* materialFrameFrom,
const MeshMaterialFrame* materialFrameTo, const u32& startIndex) { const MeshMaterialFrame* materialFrameTo, const u32& startIndex) {
if (!materialFrameFrom->textureCoords) return nullptr; if (!materialFrameFrom->textureCoords || texture == nullptr) return nullptr;
auto* result = new DynPipTextureBag(); auto* result = new DynPipTextureBag();
@@ -65,6 +65,7 @@ void StaticPipeline::render(const StaticMesh* mesh,
!(options->frustumCulling != PipelineFrustumCulling_Precise && !(options->frustumCulling != PipelineFrustumCulling_Precise &&
infoBag->fullClipChecks == true), infoBag->fullClipChecks == true),
"Full clip checks are only supported with frustum culling == Precise!"); "Full clip checks are only supported with frustum culling == Precise!");
TYRA_ASSERT(options->transformationType == TyraMVP || TYRA_ASSERT(options->transformationType == TyraMVP ||
(!options->fullClipChecks && (!options->fullClipChecks &&
options->frustumCulling == PipelineFrustumCulling_None), options->frustumCulling == PipelineFrustumCulling_None),
@@ -76,6 +77,10 @@ void StaticPipeline::render(const StaticMesh* mesh,
if (frame->bbox->frustumCheck( if (frame->bbox->frustumCheck(
rendererCore->renderer3D.frustumPlanes.getAll(), model) == rendererCore->renderer3D.frustumPlanes.getAll(), model) ==
CoreBBoxFrustum::OUTSIDE_FRUSTUM) { CoreBBoxFrustum::OUTSIDE_FRUSTUM) {
if (options && optionsManuallyAllocated) {
delete options;
}
delete infoBag;
return; return;
} }
} }
@@ -146,7 +151,8 @@ StaPipColorBag* StaticPipeline::getColorBag(
StaPipTextureBag* StaticPipeline::getTextureBag( StaPipTextureBag* StaticPipeline::getTextureBag(
const MeshMaterial* material, const MeshMaterialFrame* materialFrame) { const MeshMaterial* material, const MeshMaterialFrame* materialFrame) {
if (!materialFrame->textureCoords) return nullptr; if (!materialFrame->textureCoords || !material->textureName.has_value())
return nullptr;
auto* result = new StaPipTextureBag(); auto* result = new StaPipTextureBag();
@@ -84,10 +84,12 @@ void RendererCore2D::render(const Sprite& sprite,
else if (sizeY > sizeX) else if (sizeY > sizeX)
texS = texMax / (sizeY / sizeX); texS = texMax / (sizeY / sizeX);
rect->t0.s = sprite.flipHorizontal ? texS : 0.0F; rect->t0.s =
rect->t0.t = sprite.flipVertical ? texT : 0.0F; sprite.flipHorizontal ? (texS + sprite.offset.x) : sprite.offset.x;
rect->t1.s = sprite.flipHorizontal ? 0.0F : texS; rect->t0.t = sprite.flipVertical ? (texT + sprite.offset.y) : sprite.offset.y;
rect->t1.t = sprite.flipVertical ? 0.0F : texT; 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.r = sprite.color.r;
rect->color.g = sprite.color.g; rect->color.g = sprite.color.g;
@@ -131,4 +133,10 @@ void RendererCore2D::render(const Sprite& sprite,
context = !context; context = !context;
} }
void RendererCore2D::setTextureMappingType(
const PipelineTextureMappingType textureMappingType) {
lod.mag_filter = textureMappingType;
lod.min_filter = textureMappingType;
}
} // namespace Tyra } // namespace Tyra
@@ -18,6 +18,7 @@ Sprite::Sprite() {
flipVertical = false; flipVertical = false;
size.set(32.0F, 32.0F); size.set(32.0F, 32.0F);
position.set(100.0F, 100.0F); position.set(100.0F, 100.0F);
offset.set(0.0F, 0.0F);
scale = 1.0F; scale = 1.0F;
mode = MODE_REPEAT; mode = MODE_REPEAT;
setDefaultColor(); setDefaultColor();
+11 -11
View File
@@ -65,20 +65,20 @@ void Path3::sendTexture(const Texture* texture,
const RendererCoreTextureBuffers& texBuffers) { const RendererCoreTextureBuffers& texBuffers) {
packet2_reset(texturePacket, false); packet2_reset(texturePacket, false);
int coreWidth = texBuffers.core->width <= 64 ? 64 : texBuffers.core->width; packet2_update(
packet2_update(texturePacket, texturePacket,
draw_texture_transfer(texturePacket->base, texture->core->data, draw_texture_transfer(texturePacket->base, texture->core->data,
texture->getWidth(), texture->getWidth(), texture->getHeight(),
texture->getHeight(), texture->core->psm, texture->core->psm, texBuffers.core->address,
texBuffers.core->address, coreWidth)); texBuffers.core->width));
if (texBuffers.clut != nullptr) { if (texBuffers.clut != nullptr) {
auto* clut = texture->clut; auto* clut = texture->clut;
int clutWidth = texBuffers.clut->width <= 64 ? 64 : texBuffers.clut->width; packet2_update(
packet2_update(texturePacket, texturePacket,
draw_texture_transfer(texturePacket->next, clut->data, draw_texture_transfer(texturePacket->next, clut->data, clut->width,
clut->width, clut->height, clut->psm, clut->height, clut->psm, texBuffers.clut->address,
texBuffers.clut->address, clutWidth)); texBuffers.clut->width));
} }
packet2_chain_open_cnt(texturePacket, 0, 0, 0); packet2_chain_open_cnt(texturePacket, 0, 0, 0);
@@ -19,8 +19,18 @@
namespace Tyra { namespace Tyra {
namespace TyraTexture {
u32 textureCounter = 1;
std::vector<u32> deletedIDs;
} // namespace TyraTexture
Texture::Texture(TextureBuilderData* t_data) { Texture::Texture(TextureBuilderData* t_data) {
id = rand() % 1000000; if (TyraTexture::deletedIDs.empty() == false) {
id = TyraTexture::deletedIDs.front();
TyraTexture::deletedIDs.erase(TyraTexture::deletedIDs.begin());
} else {
id = TyraTexture::textureCounter++;
}
name = t_data->name; name = t_data->name;
@@ -50,6 +60,7 @@ Texture::Texture(TextureBuilderData* t_data) {
} }
Texture::~Texture() { Texture::~Texture() {
TyraTexture::deletedIDs.push_back(id);
if (links.size() > 0) links.clear(); if (links.size() > 0) links.clear();
if (core) delete core; if (core) delete core;
if (clut) delete clut; if (clut) delete clut;
@@ -167,9 +178,14 @@ void Texture::setDefaultWrapSettings() {
} }
void Texture::setWrapSettings(const TextureWrap t_horizontal, void Texture::setWrapSettings(const TextureWrap t_horizontal,
const TextureWrap t_vertical) { const TextureWrap t_vertical, int minu, int minv,
int maxu, int maxv) {
wrap.horizontal = t_horizontal; wrap.horizontal = t_horizontal;
wrap.vertical = t_vertical; wrap.vertical = t_vertical;
wrap.minu = minu;
wrap.minv = minv;
wrap.maxu = maxu;
wrap.maxv = maxv;
} }
void Texture::addLink(const u32& t_id) { void Texture::addLink(const u32& t_id) {
@@ -19,6 +19,7 @@ RendererCoreTexture::~RendererCoreTexture() {}
void RendererCoreTexture::init(RendererCoreGS* t_gs, Path3* t_path3) { void RendererCoreTexture::init(RendererCoreGS* t_gs, Path3* t_path3) {
gs = t_gs; gs = t_gs;
sender.init(t_path3, t_gs); sender.init(t_path3, t_gs);
repository.init(&currentAllocations);
path3 = t_path3; path3 = t_path3;
initClut(); initClut();
} }
@@ -56,6 +57,17 @@ RendererCoreTextureBuffers RendererCoreTexture::useTexture(
return newTexBuffer; return newTexBuffer;
} }
RendererCoreTextureBuffers RendererCoreTexture::updateTextureInfo(
const Texture* t_tex) {
TYRA_ASSERT(t_tex != nullptr, "Provided nullptr texture!");
auto allocated = getAllocatedBuffersByTextureId(t_tex->id);
TYRA_ASSERT(allocated.id != 0, "Can't update an unallocated texture!");
path3->sendTexture(t_tex, allocated);
return allocated;
}
RendererCoreTextureBuffers RendererCoreTexture::getAllocatedBuffersByTextureId( RendererCoreTextureBuffers RendererCoreTexture::getAllocatedBuffersByTextureId(
const u32& t_id) { const u32& t_id) {
for (u32 i = 0; i < currentAllocations.size(); i++) for (u32 i = 0; i < currentAllocations.size(); i++)
@@ -58,7 +58,9 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureCore(
auto* result = new texbuffer_t; auto* result = new texbuffer_t;
const auto* core = t_texture->core; const auto* core = t_texture->core;
result->width = t_texture->getWidth(); int coreWidth = core->width <= 64 ? 64 : core->width;
result->width = coreWidth;
result->psm = core->psm; result->psm = core->psm;
result->info.components = core->components; result->info.components = core->components;
@@ -77,7 +79,9 @@ texbuffer_t* RendererCoreTextureSender::allocateTextureClut(
auto* result = new texbuffer_t; auto* result = new texbuffer_t;
const auto* clut = t_texture->clut; const auto* clut = t_texture->clut;
result->width = clut->width; int clutWidth = clut->width <= 64 ? 64 : clut->width;
result->width = clutWidth;
result->psm = clut->psm; result->psm = clut->psm;
result->info.components = clut->components; result->info.components = clut->components;
@@ -22,6 +22,11 @@ TextureRepository::~TextureRepository() {
} }
} }
void TextureRepository::init(
std::vector<RendererCoreTextureBuffers>* t_textureBuffers) {
textureBuffers = t_textureBuffers;
}
Texture* TextureRepository::getBySpriteId(const u32& t_id) const { Texture* TextureRepository::getBySpriteId(const u32& t_id) const {
for (u32 i = 0; i < textures.size(); i++) { for (u32 i = 0; i < textures.size(); i++) {
if (textures[i]->isLinkedWith(t_id)) return textures[i]; if (textures[i]->isLinkedWith(t_id)) return textures[i];
@@ -57,10 +62,20 @@ void TextureRepository::removeByIndex(const u32& t_index) {
textures.erase(textures.begin() + t_index); textures.erase(textures.begin() + t_index);
} }
int TextureRepository::removeBufferId(const u32& t_texId) {
for (u32 i = 0; i < textureBuffers->size(); i++)
if ((*textureBuffers)[i].id == t_texId) {
(*textureBuffers)[i].id = -1;
return 0;
}
return -1;
}
void TextureRepository::removeById(const u32& t_texId) { void TextureRepository::removeById(const u32& t_texId) {
s32 index = getIndexOf(t_texId); s32 index = getIndexOf(t_texId);
TYRA_ASSERT(index != -1, "Cant remove texture, because it was not found!"); TYRA_ASSERT(index != -1, "Cant remove texture, because it was not found!");
removeByIndex(index); removeByIndex(index);
removeBufferId(t_texId);
} }
void TextureRepository::freeByMesh(const Mesh& mesh) { void TextureRepository::freeByMesh(const Mesh& mesh) {
@@ -93,6 +108,7 @@ void TextureRepository::free(const u32& t_texId) {
TYRA_ASSERT(index != -1, "Cant remove texture, because it was not found!"); TYRA_ASSERT(index != -1, "Cant remove texture, because it was not found!");
removeByIndex(index); removeByIndex(index);
removeBufferId(t_texId);
delete tex; delete tex;
} }
@@ -116,8 +132,12 @@ void TextureRepository::addByMesh(const Mesh* mesh, const char* directory,
if (dirFixed.back() != '/' && dirFixed.back() != ':') dirFixed += "/"; if (dirFixed.back() != '/' && dirFixed.back() != ':') dirFixed += "/";
for (u32 i = 0; i < mesh->materials.size(); i++) { for (u32 i = 0; i < mesh->materials.size(); i++) {
if (!mesh->materials[i]->textureName.has_value()) {
continue;
}
std::string fullPath = std::string fullPath =
dirFixed + mesh->materials[i]->name + "." + extension; dirFixed + mesh->materials[i]->textureName.value() + "." + extension;
auto* data = loader.load(fullPath.c_str()); auto* data = loader.load(fullPath.c_str());
Texture* texture = new Texture(data); Texture* texture = new Texture(data);
+3 -3
View File
@@ -18,7 +18,7 @@
{ {
"type": "shell", "type": "shell",
"label": "1. Copy source code to docker volume", "label": "1. Copy source code to docker volume",
"command": "docker exec -t tyra-game-compiler sh -c 'rsync -ac --delete --exclude \".git\" --exclude \".vscode\" --exclude \"*obj*/**\" --exclude \"*bin*/**\" /host/ /src/'" "command": "docker exec -t tyra-game-compiler sh -c 'rsync -ac --delete --exclude=\".git\" --exclude=\".vscode\" --exclude=\"*obj*/**\" --exclude=\"*bin*/**\" /host/ /src/'"
}, },
{ {
"type": "shell", "type": "shell",
@@ -34,7 +34,7 @@
{ {
"type": "shell", "type": "shell",
"label": "3. Copy binaries to host", "label": "3. Copy binaries to host",
"command": "docker exec -t tyra-game-compiler sh -c 'rsync -zac --include=\"*/\" --include=\"*bin*/**\" --exclude=\"*\" /src/ /host/'", "command": "docker exec -t tyra-game-compiler sh -c 'rsync -zac --include=\"*/\" --include=\"*bin*/**\" --exclude=\"*\" /src/ /host/'"
}, },
{ {
"type": "shell", "type": "shell",
@@ -65,7 +65,7 @@
{ {
"type": "shell", "type": "shell",
"label": "Send to PS2", "label": "Send to PS2",
"command": "docker exec -t tyra-game-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'" "command": "docker exec -t tyra-game-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || $true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
}, },
{ {
"type": "shell", "type": "shell",
+3 -1
View File
@@ -2,6 +2,8 @@
"recommendations": [ "recommendations": [
"ms-vscode.cpptools-extension-pack", "ms-vscode.cpptools-extension-pack",
"ryzngard.vscode-header-source", "ryzngard.vscode-header-source",
"maziac.asm-code-lens" "maziac.asm-code-lens",
"dmnsgn.vscode-wavefront",
"spmeesseman.vscode-taskexplorer"
] ]
} }
+1 -2
View File
@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <engine.hpp> #include <tyra>
#include <game.hpp>
namespace Racer { namespace Racer {
+1 -1
View File
@@ -1,4 +1,4 @@
#include "engine.hpp" #include <tyra>
#include "racer_game.hpp" #include "racer_game.hpp"
int main() { int main() {
+70 -6
View File
@@ -1,12 +1,76 @@
$PCSX2_PATH = "${Env:ProgramFiles(x86)}/PCSX2" # =======================
$PCSX2_EXE = 'pcsx2.exe' $CUSTOM_PCSX2_PATH = "" # "D:/My/Path/To/PCSX2"
# =======================
function GetTargetELFName { function GetTargetELFName {
return (Select-String -Path './Makefile' -Pattern "[^ ]*.elf").Matches.Value return (Select-String -Path './Makefile' -Pattern "[^ ]*.elf").Matches.Value
} }
function RunPCSX2 { function FindPCSX2Directory {
$PCSX2_EXE_WITHOUT_EXT = (Split-Path $PCSX2_EXE -Leaf).Split('.')[0] if (-not [string]::IsNullOrEmpty($CUSTOM_PCSX2_PATH)) {
Stop-Process -Name $PCSX2_EXE_WITHOUT_EXT -ErrorAction 'SilentlyContinue' return $CUSTOM_PCSX2_PATH
Start-Process -FilePath "$PCSX2_PATH/$PCSX2_EXE" -ArgumentList "--elf=$PWD/bin/$(GetTargetELFName)" }
else {
# Try to find in program files
$pcsx2Path = "${Env:ProgramFiles}/PCSX2"
$pcsx2Pathx86 = "${Env:ProgramFiles(x86)}/PCSX2"
if (Test-Path -Path $pcsx2Path) {
return $pcsx2Path
}
elseif (Test-Path -Path $pcsx2Pathx86) {
return $pcsx2Pathx86
}
else {
throw "PCSX2 directory not found!"
return $null
}
}
} }
function IsNewQtVersionOfPCSX2 {
param (
[string]$path
)
return Test-Path -Path "$path/qt.conf"
}
function FindPCSX2Executable {
param (
[string]$directory
)
$pcsx2ExePath = Join-Path -Path $directory -ChildPath 'pcsx2.exe'
$pcsx2QtExePath = Join-Path -Path $directory -ChildPath 'pcsx2-qt.exe'
if (Test-Path -Path $pcsx2ExePath) {
return 'pcsx2.exe'
}
elseif (Test-Path -Path $pcsx2QtExePath) {
return 'pcsx2-qt.exe'
}
else {
throw "PCSX2 executable not found in: $directory!"
return $null
}
}
function RunPCSX2 {
$dirPath = FindPCSX2Directory
$isNewVersion = IsNewQtVersionOfPCSX2 -path $dirPath
$executableName = FindPCSX2Executable -directory $dirPath
$executableNameWithoutExt = (Split-Path $executableName -Leaf).Split('.')[0]
$targetFileName = "$PWD/bin/$(GetTargetELFName)"
Stop-Process -Name $executableNameWithoutExt -ErrorAction 'SilentlyContinue'
if ($isNewVersion) {
Start-Process -FilePath "$dirPath/$executableName" -ArgumentList "-elf", $targetFileName
}
else { # Old version of PCSX2
Start-Process -FilePath "$dirPath/$executableName" -ArgumentList "--elf=$targetFileName"
}
}
RunPCSX2
+6 -6
View File
@@ -37,9 +37,8 @@ void Tutorial04::loop() {
/** /**
* Render de_dust2. * Render de_dust2.
* *
* As you see there are clipping issues (visual glitches). * If you see clipping issues (visual glitches),
* If you want to know how to fix it, please * You can check how to fix them in #02 YT tutorial.
* watch video tutorial.
*/ */
stapip.render(mesh.get(), renderOptions); stapip.render(mesh.get(), renderOptions);
} }
@@ -52,7 +51,7 @@ void Tutorial04::loadMesh() {
/** /**
* Load mesh data * Load mesh data
* Texture names are the material names "usemtl <material name>" * Texture file names are loaded from .mtl file (map_Kd field).
*/ */
auto data = auto data =
ObjLoader::load(FileUtils::fromCwd("de_dust2/de_dust2.obj"), options); ObjLoader::load(FileUtils::fromCwd("de_dust2/de_dust2.obj"), options);
@@ -68,8 +67,9 @@ void Tutorial04::loadMesh() {
renderOptions.frustumCulling = Tyra::PipelineFrustumCulling_None; renderOptions.frustumCulling = Tyra::PipelineFrustumCulling_None;
/** /**
* Function which load all textures into texture repository, * Function which load all textures into texture repository.
* based on material names. * It will automatically extract filename from path (map_Kd) and add
* proper extension.
*/ */
engine->renderer.getTextureRepository().addByMesh( engine->renderer.getTextureRepository().addByMesh(
mesh.get(), FileUtils::fromCwd("de_dust2/"), "png"); mesh.get(), FileUtils::fromCwd("de_dust2/"), "png");
+3 -1
View File
@@ -21,6 +21,8 @@ Tutorial05::~Tutorial05() {
} }
void Tutorial05::init() { void Tutorial05::init() {
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
dynpip.setRenderer(&engine->renderer.core); dynpip.setRenderer(&engine->renderer.core);
cameraPosition = Vec4(0.0F, 0.0F, -10.0F); cameraPosition = Vec4(0.0F, 0.0F, -10.0F);
@@ -55,7 +57,7 @@ void Tutorial05::loadZombieMesh() {
/** Starting file suffix index. It means that 1 will start from _000001.obj */ /** Starting file suffix index. It means that 1 will start from _000001.obj */
options.animation.startingIndex = 1; options.animation.startingIndex = 1;
/** If you want to know how to cook this file, please watch tutorial video */ /** If you want to know how to cook this file, please watch #02 YT tutorial */
auto data = ObjLoader::load(FileUtils::fromCwd("zombie/zombie.obj"), options); auto data = ObjLoader::load(FileUtils::fromCwd("zombie/zombie.obj"), options);
zombieMesh = std::make_unique<DynamicMesh>(data.get()); zombieMesh = std::make_unique<DynamicMesh>(data.get());
+3 -6
View File
@@ -76,12 +76,9 @@ void Tutorial07::loadMeshWithLightmap() {
auto data = ObjLoader::load(FileUtils::fromCwd("cup.obj"), options); auto data = ObjLoader::load(FileUtils::fromCwd("cup.obj"), options);
/** /**
* We don't want to load texture coordinates, * This model has no texture (it was exported without UV data),
* because this obj file has no texture. * but you can use lighting with textures as well.
*
* Anyways you can use texture as well.
*/ */
data->textureCoordsEnabled = false;
/** Lets add lightmap manually */ /** Lets add lightmap manually */
setLightmap(data.get()); setLightmap(data.get());
@@ -120,7 +117,7 @@ void Tutorial07::setDirectionalLightsOptions() {
void Tutorial07::setLightmap(MeshBuilderData* data) { void Tutorial07::setLightmap(MeshBuilderData* data) {
/** Information for mesh, that data has lightmap */ /** Information for mesh, that data has lightmap */
data->lightMapEnabled = true; data->loadLightmap = true;
/** This object file has only 1 material */ /** This object file has only 1 material */
auto* material = data->materials[0]; auto* material = data->materials[0];
@@ -26,10 +26,10 @@ class Tutorial08 : public Game {
void loadCupMesh(); void loadCupMesh();
void loadSkyboxMesh(); void loadSkyboxMesh();
Vec4 cameraPosition, cameraLookAt; Vec4 cameraPosition;
Vec4 cameraLookAt;
Engine* engine; Engine* engine;
u8 fpsCounter; u8 fpsCounter;
StaticPipeline stapip; StaticPipeline stapip;
@@ -92,7 +92,6 @@ void Tutorial08::loadCupMesh() {
options.scale = 3.0F; options.scale = 3.0F;
auto data = ObjLoader::load(FileUtils::fromCwd("cup/cup.obj"), options); auto data = ObjLoader::load(FileUtils::fromCwd("cup/cup.obj"), options);
data->textureCoordsEnabled = false;
cupMesh = std::make_unique<StaticMesh>(data.get()); cupMesh = std::make_unique<StaticMesh>(data.get());
+24
View File
@@ -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
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -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 <tyra>
#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<Sprite, FONT_CHAR_SIZE> font;
};
} // namespace Tyra
@@ -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 <tyra>
#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
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
+4
View File
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
+4
View File
@@ -0,0 +1,4 @@
$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1'
. $ConfigFile
RunPCSX2
@@ -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
+26
View File
@@ -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;
}
@@ -0,0 +1,290 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Guido Diego Quispe Robles
*/
#include <tyra>
#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
@@ -0,0 +1,24 @@
TARGET := tutorial_11.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
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -0,0 +1,58 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2024, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#pragma once
#include <tyra>
#include <memory>
namespace Tyra {
class Tutorial11 : public Game {
public:
explicit Tutorial11(Engine* engine);
~Tutorial11();
void init();
void loop();
private:
void setDrawData();
void loadBags();
void setTextureRegionRepeat();
void setTextureDefaultWrap();
const u8 MAX_TILES = 4;
u8 TILE_COL = 0;
u8 TILE_ROW = 0;
u8 shouldFlipTextureSettings = false;
float limitTimeToFlip = 2.00f;
float elapsedTime = 0;
Engine* engine;
Vec4 cameraPosition, cameraLookAt;
M4x4 translation, rotation, scale, model;
Texture* UVCheckerTex;
std::array<Vec4, 6> vertices;
std::array<Color, 6> colors;
std::array<Vec4, 6> uvMap;
StaticPipeline stapip;
std::unique_ptr<StaPipBag> bag;
std::unique_ptr<StaPipInfoBag> infoBag;
std::unique_ptr<StaPipColorBag> colorBag;
std::unique_ptr<StaPipTextureBag> texBag;
};
} // namespace Tyra
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -0,0 +1,4 @@
$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1'
. $ConfigFile
RunPCSX2
@@ -0,0 +1,24 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2024, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include "engine.hpp"
#include "tutorial_11.hpp"
/**
* In this tutorial we will learn:
* - How to use texture in repeate mode of GS
*/
int main() {
Tyra::Engine engine;
Tyra::Tutorial11 game(&engine);
engine.run(&game);
return 0;
}
@@ -0,0 +1,178 @@
/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2024, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include <tyra>
#include "tutorial_11.hpp"
namespace Tyra {
Tutorial11::Tutorial11(Engine* t_engine) : engine(t_engine) {
translation = M4x4::Identity;
rotation = M4x4::Identity;
scale = M4x4::Identity;
model = M4x4::Identity;
rotation.rotateY(Math::PI);
}
Tutorial11::~Tutorial11() {}
void Tutorial11::init() {
stapip.setRenderer(&engine->renderer.core);
cameraPosition = Vec4(0.0F, 0.0F, -10.0F);
cameraLookAt.unit();
UVCheckerTex = engine->renderer.getTextureRepository().add(
FileUtils::fromCwd("uv_checker.png"));
setDrawData();
loadBags();
}
void Tutorial11::loop() {
const auto deltaTime =
std::min(1.0f / static_cast<float>(engine->info.getFps()),
static_cast<float>(1.0 / 60.0f));
elapsedTime += deltaTime;
if (elapsedTime > limitTimeToFlip) {
elapsedTime -= limitTimeToFlip;
shouldFlipTextureSettings = !shouldFlipTextureSettings;
shouldFlipTextureSettings ? setTextureRegionRepeat()
: setTextureDefaultWrap();
// Update texture packet info after change wrap settings
engine->renderer.core.texture.updateTextureInfo(UVCheckerTex);
}
model = translation * rotation * scale;
engine->renderer.beginFrame(CameraInfo3D(&cameraPosition, &cameraLookAt));
{
engine->renderer.renderer3D.usePipeline(stapip);
/**
* Lets draw manually via "bags".
* You can do the same thing with dynamic pipeline.
*/
stapip.core.render(bag.get());
}
engine->renderer.endFrame();
}
void Tutorial11::setDrawData() {
vertices = {
// Tri 1
Vec4(-3.0F, -3.0F, 0.0F),
Vec4(3.0F, -3.0F, 0.0F),
Vec4(-3.0F, 3.0F, 0.0F),
// Tri 2
Vec4(3.0F, -3.0F, 0.0F),
Vec4(-3.0F, 3.0F, 0.0F),
Vec4(3.0F, 3.0F, 0.0F),
};
colors = {
Color(128.0F, 128.0F, 128.0F), Color(128.0F, 128.0F, 128.0F),
Color(128.0F, 128.0F, 128.0F), Color(128.0F, 128.0F, 128.0F),
Color(128.0F, 128.0F, 128.0F), Color(128.0F, 128.0F, 128.0F),
};
setTextureDefaultWrap();
}
void Tutorial11::setTextureDefaultWrap() {
uvMap = {Vec4(0.0f, 1.0F, 1.0F, 0.0f), Vec4(0.0f + 1, 1.0F, 1.0F, 0.0f),
Vec4(0.0f, 0.0f, 1.0F, 0.0f),
Vec4(0.0f + 1, 1.0F, 1.0F, 0.0f), Vec4(0.0f, 0.0f, 1.0F, 0.0f),
Vec4(0.0f + 1.0F, 0.0f, 1.0F, 0.0f)};
TYRA_LOG("Reseting texture wrap settings");
UVCheckerTex->setDefaultWrapSettings();
}
void Tutorial11::setTextureRegionRepeat() {
const float _scale = 1.0f / (float)MAX_TILES;
const Vec4 scale =
Vec4(MAX_TILES > 0 ? _scale * MAX_TILES : _scale,
MAX_TILES > 0 ? _scale * MAX_TILES : _scale, 1.0f, 0.0f);
uvMap = {
Vec4(TILE_COL, TILE_ROW + 1.0F, 1.0F, 0.0f) * scale,
Vec4(TILE_COL + 1, TILE_ROW + 1.0F, 1.0F, 0.0f) * scale,
Vec4(TILE_COL, TILE_ROW, 1.0F, 0.0f) * scale,
Vec4(TILE_COL + 1, TILE_ROW + 1.0F, 1.0F, 0.0f) * scale,
Vec4(TILE_COL, TILE_ROW, 1.0F, 0.0f) * scale,
Vec4(TILE_COL + 1.0F, TILE_ROW, 1.0F, 0.0f) * scale,
};
const auto tileW = (UVCheckerTex->getWidth() * _scale) - 1;
const auto tileH = (UVCheckerTex->getHeight() * _scale) - 1;
const auto tileU = TILE_COL * tileW + TILE_COL;
const auto tileV = TILE_ROW * tileH + TILE_ROW;
int minu = tileW;
int minv = tileH;
int maxu = tileU;
int maxv = tileV;
TYRA_LOG("Changing the texture wraping...");
UVCheckerTex->setWrapSettings(TextureWrap::RegionRepeat,
TextureWrap::RegionRepeat, minu, minv, maxu,
maxv);
TILE_COL++;
if (TILE_COL >= MAX_TILES) {
TILE_COL %= MAX_TILES;
TILE_ROW = (TILE_ROW + 1) % MAX_TILES;
}
}
void Tutorial11::loadBags() {
/**
* Create info bag and fill it with model matrix and shading type.
* Keep rest of the options as default.
*/
infoBag = std::make_unique<StaPipInfoBag>();
infoBag->model = &model;
infoBag->shadingType = TyraShadingGouraud;
infoBag->textureMappingType = TyraNearest;
/** Create colors bag and set data pointer */
colorBag = std::make_unique<StaPipColorBag>();
colorBag->many = colors.begin();
texBag = std::make_unique<StaPipTextureBag>();
texBag.get()->texture = UVCheckerTex;
texBag.get()->coordinates = uvMap.data();
/**
* Create main bag and set:
* - vertices data
* - vertices count
* - pointers to other bags
*
* You can add here lighting and texture bag as well.
* If you want to have deeper look of this feature, please
* read static_pipeline.cpp code file.
*/
bag = std::make_unique<StaPipBag>();
bag->color = colorBag.get();
bag->texture = texBag.get();
bag->info = infoBag.get();
bag->vertices = vertices.begin();
bag->count = vertices.size();
}
} // namespace Tyra
+70 -6
View File
@@ -1,12 +1,76 @@
$PCSX2_PATH = "${Env:ProgramFiles(x86)}/PCSX2" # =======================
$PCSX2_EXE = 'pcsx2.exe' $CUSTOM_PCSX2_PATH = "" # "D:/My/Path/To/PCSX2"
# =======================
function GetTargetELFName { function GetTargetELFName {
return (Select-String -Path './Makefile' -Pattern "[^ ]*.elf").Matches.Value return (Select-String -Path './Makefile' -Pattern "[^ ]*.elf").Matches.Value
} }
function RunPCSX2 { function FindPCSX2Directory {
$PCSX2_EXE_WITHOUT_EXT = (Split-Path $PCSX2_EXE -Leaf).Split('.')[0] if (-not [string]::IsNullOrEmpty($CUSTOM_PCSX2_PATH)) {
Stop-Process -Name $PCSX2_EXE_WITHOUT_EXT -ErrorAction 'SilentlyContinue' return $CUSTOM_PCSX2_PATH
Start-Process -FilePath "$PCSX2_PATH/$PCSX2_EXE" -ArgumentList "--elf=$PWD/bin/$(GetTargetELFName)" }
else {
# Try to find in program files
$pcsx2Path = "${Env:ProgramFiles}/PCSX2"
$pcsx2Pathx86 = "${Env:ProgramFiles(x86)}/PCSX2"
if (Test-Path -Path $pcsx2Path) {
return $pcsx2Path
}
elseif (Test-Path -Path $pcsx2Pathx86) {
return $pcsx2Pathx86
}
else {
throw "PCSX2 directory not found!"
return $null
}
}
} }
function IsNewQtVersionOfPCSX2 {
param (
[string]$path
)
return Test-Path -Path "$path/qt.conf"
}
function FindPCSX2Executable {
param (
[string]$directory
)
$pcsx2ExePath = Join-Path -Path $directory -ChildPath 'pcsx2.exe'
$pcsx2QtExePath = Join-Path -Path $directory -ChildPath 'pcsx2-qt.exe'
if (Test-Path -Path $pcsx2ExePath) {
return 'pcsx2.exe'
}
elseif (Test-Path -Path $pcsx2QtExePath) {
return 'pcsx2-qt.exe'
}
else {
throw "PCSX2 executable not found in: $directory!"
return $null
}
}
function RunPCSX2 {
$dirPath = FindPCSX2Directory
$isNewVersion = IsNewQtVersionOfPCSX2 -path $dirPath
$executableName = FindPCSX2Executable -directory $dirPath
$executableNameWithoutExt = (Split-Path $executableName -Leaf).Split('.')[0]
$targetFileName = "$PWD/bin/$(GetTargetELFName)"
Stop-Process -Name $executableNameWithoutExt -ErrorAction 'SilentlyContinue'
if ($isNewVersion) {
Start-Process -FilePath "$dirPath/$executableName" -ArgumentList "-elf", $targetFileName
}
else { # Old version of PCSX2
Start-Process -FilePath "$dirPath/$executableName" -ArgumentList "--elf=$targetFileName"
}
}
RunPCSX2