irx, nullptr, threading patch
This commit is contained in:
+4
-3
@@ -38,7 +38,8 @@ VCL_SOURCES := $(shell find $(SRCDIR) -type f -name *.$(VCLPPEXT))
|
|||||||
VCL_OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(VCL_SOURCES:.$(VCLPPEXT)=.$(OBJEXT)))
|
VCL_OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(VCL_SOURCES:.$(VCLPPEXT)=.$(OBJEXT)))
|
||||||
|
|
||||||
#Default Make
|
#Default Make
|
||||||
all: resources irxcopy $(TARGET)
|
all: resources $(TARGET)
|
||||||
|
#all: resources irxcopy $(TARGET)
|
||||||
|
|
||||||
release:
|
release:
|
||||||
$(MAKE) CFLAGS="-DNDEBUG $(CFLAGS)"
|
$(MAKE) CFLAGS="-DNDEBUG $(CFLAGS)"
|
||||||
@@ -64,8 +65,8 @@ cleaner: clean
|
|||||||
@$(RM) -rf $(TARGETDIR)
|
@$(RM) -rf $(TARGETDIR)
|
||||||
@$(RM) -rf $(BUILDDIR)
|
@$(RM) -rf $(BUILDDIR)
|
||||||
|
|
||||||
irxcopy:
|
#irxcopy:
|
||||||
@cp $(PS2SDK)/iop/irx/audsrv.irx $(TARGETDIR)/audsrv.irx
|
# @cp $(PS2SDK)/iop/irx/audsrv.irx $(TARGETDIR)/audsrv.irx
|
||||||
|
|
||||||
#Pull in dependency info for *existing* .o files
|
#Pull in dependency info for *existing* .o files
|
||||||
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
||||||
|
|
||||||
- [General] USB test
|
|
||||||
- [General] CI in Github via docker image
|
- [General] CI in Github via docker image
|
||||||
|
|
||||||
- [Tutorials] 1. Hello world! - explain init(), loop() and what should be inside them (every tutorial should be well commented!)
|
- [Tutorials] 1. Hello world! - explain init(), loop() and what should be inside them (every tutorial should be well commented!)
|
||||||
@@ -39,6 +38,6 @@ because Mesh rendering uses only core.render()
|
|||||||
- [obj] Add multicolor support to obj
|
- [obj] Add multicolor support to obj
|
||||||
- [Obj] Improve obj importing for multiple usemtl with same names
|
- [Obj] Improve obj importing for multiple usemtl with same names
|
||||||
- [tyrdat] Custom 3D data file with precalculated bboxes with support of async loading
|
- [tyrdat] Custom 3D data file with precalculated bboxes with support of async loading
|
||||||
- [Renderer] Interlacing
|
- [Renderer] Interlacing, a potem resolution 640x448
|
||||||
- [General] Add cpp lint checker in GitHub
|
- [General] Add cpp lint checker in GitHub
|
||||||
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
|
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ DEPEXT := d
|
|||||||
OBJEXT := o
|
OBJEXT := o
|
||||||
|
|
||||||
#Flags, Libraries and Includes
|
#Flags, Libraries and Includes
|
||||||
CFLAGS :=
|
CFLAGS :=
|
||||||
LIB := -ltyra
|
LIB := -ltyra
|
||||||
LIBDIRS := -L$(ENGINEDIR)/bin
|
LIBDIRS := -L$(ENGINEDIR)/bin
|
||||||
INC := -I$(INCDIR) -I$(ENGINEDIR)/inc
|
INC := -I$(INCDIR) -I$(ENGINEDIR)/inc
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
# _____ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licensed under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Demo {
|
||||||
|
|
||||||
|
const bool IS_REAL_PS2 = false;
|
||||||
|
|
||||||
|
} // namespace Demo
|
||||||
+10
-1
@@ -10,9 +10,18 @@
|
|||||||
|
|
||||||
#include <tyra>
|
#include <tyra>
|
||||||
#include "demo_game.hpp"
|
#include "demo_game.hpp"
|
||||||
|
#include "game_settings.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Tyra::Engine engine;
|
Tyra::EngineOptions options;
|
||||||
|
|
||||||
|
if (Demo::IS_REAL_PS2) {
|
||||||
|
options.writeLogsToFile = true;
|
||||||
|
options.loadUsbDriver = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tyra::Engine engine(options);
|
||||||
|
|
||||||
Demo::DemoGame game(&engine);
|
Demo::DemoGame game(&engine);
|
||||||
engine.run(&game);
|
engine.run(&game);
|
||||||
SleepThread();
|
SleepThread();
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ Enemy::Enemy(Engine* engine, const EnemyInfo& t_info) {
|
|||||||
info.bodyTexture->addLink(bodyMaterial->id);
|
info.bodyTexture->addLink(bodyMaterial->id);
|
||||||
info.clothTexture->addLink(clothMaterial->id);
|
info.clothTexture->addLink(clothMaterial->id);
|
||||||
|
|
||||||
float r = Math::randomf(64.0F, 128.0F);
|
float r = Math::randomf(75.0F, 128.0F);
|
||||||
float g = Math::randomf(64.0F, 128.0F);
|
float g = Math::randomf(75.0F, 128.0F);
|
||||||
float b = Math::randomf(64.0F, 128.0F);
|
float b = Math::randomf(75.0F, 128.0F);
|
||||||
|
|
||||||
bodyMaterial->ambient.set(r, g, b);
|
bodyMaterial->ambient.set(r, g, b);
|
||||||
clothMaterial->ambient.set(r, g, b);
|
clothMaterial->ambient.set(r, g, b);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "states/game/enemy/enemy_manager.hpp"
|
#include "states/game/enemy/enemy_manager.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include "game_settings.hpp"
|
||||||
|
|
||||||
using Tyra::FileUtils;
|
using Tyra::FileUtils;
|
||||||
using Tyra::Math;
|
using Tyra::Math;
|
||||||
@@ -46,7 +47,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 = 10;
|
const int enemyCount = IS_REAL_PS2 ? 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;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "states/game/game_state.hpp"
|
#include "states/game/game_state.hpp"
|
||||||
|
#include "game_settings.hpp"
|
||||||
|
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
using Tyra::FileUtils;
|
using Tyra::FileUtils;
|
||||||
@@ -44,6 +45,8 @@ void GameState::onStart() {
|
|||||||
|
|
||||||
engine->audio.song.setVolume(85);
|
engine->audio.song.setVolume(85);
|
||||||
|
|
||||||
|
if (IS_REAL_PS2) engine->renderer.setFrameLimit(false);
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ void IntroPressKeyState::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateMap();
|
updateMap();
|
||||||
|
|
||||||
Threading::switchThread();
|
Threading::switchThread();
|
||||||
|
|
||||||
for (u8 i = 0; i < mapRows; i++)
|
for (u8 i = 0; i < mapRows; i++)
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ void IntroPs2DevState::onStart() {
|
|||||||
settings.getHeight() / 2 - sprite->size.y / 2);
|
settings.getHeight() / 2 - sprite->size.y / 2);
|
||||||
sprite->color.a = 0;
|
sprite->color.a = 0;
|
||||||
|
|
||||||
|
Threading::switchThread();
|
||||||
|
|
||||||
texture = engine->renderer.core.texture.repository.add(
|
texture = engine->renderer.core.texture.repository.add(
|
||||||
FileUtils::fromCwd("intro/ps2dev.png"));
|
FileUtils::fromCwd("intro/ps2dev.png"));
|
||||||
texture->addLink(sprite->id);
|
texture->addLink(sprite->id);
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ void IntroTyraState::onStart() {
|
|||||||
FileUtils::fromCwd("intro/tyra_bg.png"));
|
FileUtils::fromCwd("intro/tyra_bg.png"));
|
||||||
bgTexture->addLink(bgSprite->id);
|
bgTexture->addLink(bgSprite->id);
|
||||||
|
|
||||||
|
Threading::switchThread();
|
||||||
|
|
||||||
bg2Texture = engine->renderer.core.texture.repository.add(
|
bg2Texture = engine->renderer.core.texture.repository.add(
|
||||||
FileUtils::fromCwd("intro/tyra_bg2.png"));
|
FileUtils::fromCwd("intro/tyra_bg2.png"));
|
||||||
bg2Texture->addLink(bg2Sprite->id);
|
bg2Texture->addLink(bg2Sprite->id);
|
||||||
@@ -146,7 +148,6 @@ void IntroTyraState::update() {
|
|||||||
engine->renderer.renderer2D.render(bg2Sprite);
|
engine->renderer.renderer2D.render(bg2Sprite);
|
||||||
engine->renderer.renderer2D.render(tyraSprite);
|
engine->renderer.renderer2D.render(tyraSprite);
|
||||||
|
|
||||||
Threading::switchThread();
|
|
||||||
renderFillers();
|
renderFillers();
|
||||||
|
|
||||||
engine->renderer.endFrame();
|
engine->renderer.endFrame();
|
||||||
|
|||||||
+57
-16
@@ -22,17 +22,22 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#define TYRA_LOG(...) Debug::writeLines("LOG: ", ##__VA_ARGS__, "\n")
|
#include "file/file_utils.hpp"
|
||||||
#define TYRA_WARN(...) Debug::writeLines("==WARN: ", ##__VA_ARGS__, "\n")
|
#include "info/info.hpp"
|
||||||
#define TYRA_ERROR(...) Debug::writeLines("====ERR: ", ##__VA_ARGS__, "\n")
|
|
||||||
#define TYRA_TRAP(...) Debug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
#define TYRA_LOG(...) TyraDebug::writeLines("LOG: ", ##__VA_ARGS__, "\n")
|
||||||
#define TYRA_BREAKPOINT() Debug::trap(__FILE__, __LINE__, "Breakpoint")
|
#define TYRA_WARN(...) TyraDebug::writeLines("==WARN: ", ##__VA_ARGS__, "\n")
|
||||||
|
#define TYRA_ERROR(...) TyraDebug::writeLines("====ERR: ", ##__VA_ARGS__, "\n")
|
||||||
|
#define TYRA_TRAP(...) TyraDebug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
#define TYRA_BREAKPOINT() TyraDebug::trap(__FILE__, __LINE__, "Breakpoint")
|
||||||
#define TYRA_ASSERT(condition, ...) \
|
#define TYRA_ASSERT(condition, ...) \
|
||||||
if (!(condition)) Debug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
if (!(condition)) TyraDebug::trap(__FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
class Debug {
|
class TyraDebug {
|
||||||
public:
|
public:
|
||||||
template <typename Arg, typename... Args>
|
template <typename Arg, typename... Args>
|
||||||
static void writeLines(Arg&& arg, Args&&... args) {
|
static void writeLines(Arg&& arg, Args&&... args) {
|
||||||
@@ -42,24 +47,54 @@ class Debug {
|
|||||||
using expander = int[];
|
using expander = int[];
|
||||||
(void)expander{0, (void(ss << std::forward<Args>(args)), 0)...};
|
(void)expander{0, (void(ss << std::forward<Args>(args)), 0)...};
|
||||||
|
|
||||||
printf("%s", ss.str().c_str());
|
if (Tyra::Info::writeLogsToFile) {
|
||||||
|
auto* logFile = getLogFile();
|
||||||
|
*logFile << ss.str();
|
||||||
|
logFile->flush();
|
||||||
|
} else {
|
||||||
|
printf("%s", ss.str().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static void trap(const char* file, int line, Args... args) {
|
static void trap(const char* file, int line, Args... args) {
|
||||||
printf("\n");
|
std::stringstream ss1;
|
||||||
printf("============== TYRA ==============\n");
|
ss1 << "\n";
|
||||||
printf("| Assertion failed!\n");
|
ss1 << "============== TYRA ==============\n";
|
||||||
printf("|\n");
|
ss1 << "| Assertion failed!\n";
|
||||||
|
ss1 << "|\n";
|
||||||
|
|
||||||
|
if (Tyra::Info::writeLogsToFile) {
|
||||||
|
auto* logFile = getLogFile();
|
||||||
|
*logFile << ss1.str();
|
||||||
|
logFile->flush();
|
||||||
|
} else {
|
||||||
|
printf("%s", ss1.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
writeAssertLines(args...);
|
writeAssertLines(args...);
|
||||||
printf("|\n");
|
|
||||||
printf("| File : %s:%d\n", file, line);
|
std::stringstream ss2;
|
||||||
printf("====================================\n\n");
|
ss2 << "|\n";
|
||||||
|
ss2 << "| File : " << file << ":" << line << "\n";
|
||||||
|
ss2 << "====================================\n\n";
|
||||||
|
|
||||||
|
if (Tyra::Info::writeLogsToFile) {
|
||||||
|
auto* logFile = getLogFile();
|
||||||
|
*logFile << ss2.str();
|
||||||
|
logFile->flush();
|
||||||
|
} else {
|
||||||
|
printf("%s", ss2.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static std::unique_ptr<std::ofstream> logFile;
|
||||||
|
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) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@@ -69,7 +104,13 @@ class Debug {
|
|||||||
(void)expander{
|
(void)expander{
|
||||||
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
|
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
|
||||||
|
|
||||||
printf("%s", ss.str().c_str());
|
if (Tyra::Info::writeLogsToFile) {
|
||||||
|
auto* logfile = getLogFile();
|
||||||
|
*logfile << ss.str();
|
||||||
|
logFile->flush();
|
||||||
|
} else {
|
||||||
|
printf("%s", ss.str().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -20,24 +20,37 @@
|
|||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
|
struct EngineOptions {
|
||||||
|
/**
|
||||||
|
* True -> logs will be written to file.
|
||||||
|
* False -> logs will be displayed in console
|
||||||
|
*/
|
||||||
|
bool writeLogsToFile = false;
|
||||||
|
|
||||||
|
bool loadUsbDriver = false;
|
||||||
|
};
|
||||||
|
|
||||||
class Engine {
|
class Engine {
|
||||||
public:
|
public:
|
||||||
Engine();
|
Engine();
|
||||||
|
Engine(const EngineOptions& options);
|
||||||
~Engine();
|
~Engine();
|
||||||
|
|
||||||
Renderer renderer;
|
Renderer renderer;
|
||||||
Pad pad;
|
Pad pad;
|
||||||
Audio audio;
|
Audio audio;
|
||||||
IrxLoader irx;
|
|
||||||
Info info;
|
Info info;
|
||||||
|
|
||||||
void run(Game* t_game);
|
void run(Game* t_game);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IrxLoader irx;
|
||||||
|
|
||||||
Game* game;
|
Game* game;
|
||||||
Banner banner;
|
Banner banner;
|
||||||
|
|
||||||
void realLoop();
|
void realLoop();
|
||||||
|
void initAll(const bool& loadUsbDriver);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ class FileUtils {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Argv name+path & just path
|
// Argv name+path & just path
|
||||||
char cwd[NAME_MAX];
|
char cwd[255];
|
||||||
char elfName[NAME_MAX];
|
char elfName[255];
|
||||||
char elfPath[NAME_MAX - 14];
|
char elfPath[255 - 14];
|
||||||
|
|
||||||
void setPathInfo(const char* path);
|
void setPathInfo(const char* path);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ class Info {
|
|||||||
|
|
||||||
Version version;
|
Version version;
|
||||||
|
|
||||||
|
static bool writeLogsToFile;
|
||||||
|
|
||||||
/** Called by engine */
|
/** Called by engine */
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
|||||||
@@ -19,16 +19,18 @@ class IrxLoader {
|
|||||||
IrxLoader();
|
IrxLoader();
|
||||||
~IrxLoader();
|
~IrxLoader();
|
||||||
|
|
||||||
/** Load's audio and pad driver */
|
void loadAll(const bool& withUsb, const bool& isLoggingToFile);
|
||||||
void loadDefaultDrivers();
|
|
||||||
|
|
||||||
void loadUSBDriver();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static bool isLoaded;
|
||||||
|
|
||||||
|
void loadSio2man(const bool& verbose);
|
||||||
|
void loadPadman(const bool& verbose);
|
||||||
|
void loadLibsd(const bool& verbose);
|
||||||
|
void loadUsbModules(const bool& verbose);
|
||||||
|
void loadAudsrv(const bool& verbose);
|
||||||
|
|
||||||
int applyRpcPatches();
|
int applyRpcPatches();
|
||||||
int loadAudio();
|
|
||||||
int loadPad();
|
|
||||||
int loadUsb();
|
|
||||||
void waitUntilUsbDeviceIsReady();
|
void waitUntilUsbDeviceIsReady();
|
||||||
void delay(int count);
|
void delay(int count);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ class Color {
|
|||||||
explicit Color(const float* v) { copy(this, v); }
|
explicit Color(const float* v) { copy(this, v); }
|
||||||
|
|
||||||
void operator=(const Color& v);
|
void operator=(const Color& v);
|
||||||
|
void operator+=(const float& v);
|
||||||
|
void operator-=(const float& v);
|
||||||
void operator*=(const float& v);
|
void operator*=(const float& v);
|
||||||
void operator/=(const float& v);
|
void operator/=(const float& v);
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void AudioSong::init() {
|
|||||||
void AudioSong::load(const char* t_path) {
|
void AudioSong::load(const char* t_path) {
|
||||||
if (songLoaded) unloadSong();
|
if (songLoaded) unloadSong();
|
||||||
wav = fopen(t_path, "rb");
|
wav = fopen(t_path, "rb");
|
||||||
TYRA_ASSERT(wav != NULL, "Failed to open wav file!");
|
TYRA_ASSERT(wav != nullptr, "Failed to open wav file!");
|
||||||
rewindSongToStart();
|
rewindSongToStart();
|
||||||
songLoaded = true;
|
songLoaded = true;
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ void AudioSong::unloadSong() {
|
|||||||
|
|
||||||
/** Fseek on wav. */
|
/** Fseek on wav. */
|
||||||
void AudioSong::rewindSongToStart() {
|
void AudioSong::rewindSongToStart() {
|
||||||
if (wav != NULL) fseek(wav, 0x30, SEEK_SET);
|
if (wav != nullptr) fseek(wav, 0x30, SEEK_SET);
|
||||||
chunkReadStatus = 0;
|
chunkReadStatus = 0;
|
||||||
songFinished = false;
|
songFinished = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
# _____ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licensed under Apache License 2.0
|
||||||
|
# Wellington Carvalho <wellcoj@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "debug/debug.hpp"
|
||||||
|
|
||||||
|
std::unique_ptr<std::ofstream> TyraDebug::logFile;
|
||||||
|
|
||||||
|
std::ofstream* TyraDebug::getLogFile() {
|
||||||
|
if (logFile) {
|
||||||
|
return logFile.get();
|
||||||
|
} else {
|
||||||
|
logFile = std::make_unique<std::ofstream>();
|
||||||
|
logFile->open(Tyra::FileUtils::fromCwd("log.txt"),
|
||||||
|
std::ofstream::out | std::ofstream::app);
|
||||||
|
return logFile.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tyra
|
||||||
+14
-7
@@ -12,13 +12,11 @@
|
|||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
Engine::Engine() {
|
Engine::Engine() { initAll(false); }
|
||||||
srand(time(nullptr));
|
|
||||||
renderer.init();
|
Engine::Engine(const EngineOptions& options) {
|
||||||
banner.show(&renderer);
|
info.writeLogsToFile = options.writeLogsToFile;
|
||||||
irx.loadDefaultDrivers();
|
initAll(options.loadUsbDriver);
|
||||||
audio.init();
|
|
||||||
pad.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::~Engine() {}
|
Engine::~Engine() {}
|
||||||
@@ -37,4 +35,13 @@ void Engine::realLoop() {
|
|||||||
info.update();
|
info.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::initAll(const bool& loadUsbDriver) {
|
||||||
|
srand(time(nullptr));
|
||||||
|
irx.loadAll(loadUsbDriver, info.writeLogsToFile);
|
||||||
|
renderer.init();
|
||||||
|
banner.show(&renderer);
|
||||||
|
audio.init();
|
||||||
|
pad.init();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ void FileUtils::setPathInfo(const char* path) {
|
|||||||
strcpy(this->elfPath, path);
|
strcpy(this->elfPath, path);
|
||||||
|
|
||||||
ptr = strrchr(this->elfPath, '/');
|
ptr = strrchr(this->elfPath, '/');
|
||||||
if (ptr == NULL) {
|
if (ptr == nullptr) {
|
||||||
ptr = strrchr(this->elfPath, '\\');
|
ptr = strrchr(this->elfPath, '\\');
|
||||||
if (ptr == NULL) {
|
if (ptr == nullptr) {
|
||||||
ptr = strrchr(this->elfPath, ':');
|
ptr = strrchr(this->elfPath, ':');
|
||||||
if (ptr == NULL) {
|
if (ptr == nullptr) {
|
||||||
TYRA_TRAP("Did not find path! PATH: ", path);
|
TYRA_TRAP("Did not find path! PATH: ", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
|
bool Info::writeLogsToFile = false;
|
||||||
|
|
||||||
Info::Info() {
|
Info::Info() {
|
||||||
fps = 0;
|
fps = 0;
|
||||||
fpsDelayer = 0;
|
fpsDelayer = 0;
|
||||||
@@ -48,21 +50,21 @@ void* Info::allocateLargestFreeRAMBlock(size_t* Size) {
|
|||||||
|
|
||||||
s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
|
s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
|
||||||
|
|
||||||
while (s0 && (p = malloc(s0)) == NULL) s0 >>= 1;
|
while (s0 && (p = malloc(s0)) == nullptr) s0 >>= 1;
|
||||||
|
|
||||||
if (p) free(p);
|
if (p) free(p);
|
||||||
|
|
||||||
s1 = s0 >> 1;
|
s1 = s0 >> 1;
|
||||||
|
|
||||||
while (s1) {
|
while (s1) {
|
||||||
if ((p = malloc(s0 + s1)) != NULL) {
|
if ((p = malloc(s0 + s1)) != nullptr) {
|
||||||
s0 += s1;
|
s0 += s1;
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
s1 >>= 1;
|
s1 >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (s0 && (p = malloc(s0)) == NULL) s0 ^= s0 & -s0;
|
while (s0 && (p = malloc(s0)) == nullptr) s0 ^= s0 & -s0;
|
||||||
|
|
||||||
*Size = s0;
|
*Size = s0;
|
||||||
return p;
|
return p;
|
||||||
@@ -70,30 +72,30 @@ void* Info::allocateLargestFreeRAMBlock(size_t* Size) {
|
|||||||
|
|
||||||
size_t Info::getFreeRAMSize() {
|
size_t Info::getFreeRAMSize() {
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
void* pFirst = NULL;
|
void* pFirst = nullptr;
|
||||||
void* pLast = NULL;
|
void* pLast = nullptr;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t largest;
|
size_t largest;
|
||||||
void* p = allocateLargestFreeRAMBlock(&largest);
|
void* p = allocateLargestFreeRAMBlock(&largest);
|
||||||
|
|
||||||
if (largest < sizeof(void*)) {
|
if (largest < sizeof(void*)) {
|
||||||
if (p != NULL) free(p);
|
if (p != nullptr) free(p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(void**)p = NULL;
|
*(void**)p = nullptr;
|
||||||
|
|
||||||
total += largest;
|
total += largest;
|
||||||
|
|
||||||
if (pFirst == NULL) pFirst = p;
|
if (pFirst == nullptr) pFirst = p;
|
||||||
|
|
||||||
if (pLast != NULL) *(void**)pLast = p;
|
if (pLast != nullptr) *(void**)pLast = p;
|
||||||
|
|
||||||
pLast = p;
|
pLast = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (pFirst != NULL) {
|
while (pFirst != nullptr) {
|
||||||
void* p = *(void**)pFirst;
|
void* p = *(void**)pFirst;
|
||||||
free(pFirst);
|
free(pFirst);
|
||||||
pFirst = p;
|
pFirst = p;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
$PS2SDK/iop/irx/audsrv.irx
|
||||||
|
audsrv_irx
|
||||||
@@ -16,8 +16,23 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <sifrpc.h>
|
#include <sifrpc.h>
|
||||||
#include <sbv_patches.h>
|
#include <sbv_patches.h>
|
||||||
|
#include <iopcontrol.h>
|
||||||
|
#include "file/file_utils.hpp"
|
||||||
|
|
||||||
// external IRX modules
|
// external IRX modules
|
||||||
|
|
||||||
|
extern u8 sio2man_irx[];
|
||||||
|
extern int size_sio2man_irx;
|
||||||
|
|
||||||
|
extern u8 padman_irx[];
|
||||||
|
extern int size_padman_irx;
|
||||||
|
|
||||||
|
extern u8 audsrv_irx[];
|
||||||
|
extern int size_audsrv_irx;
|
||||||
|
|
||||||
|
extern u8 libsd_irx[];
|
||||||
|
extern int size_libsd_irx;
|
||||||
|
|
||||||
extern u8 bdm_irx[];
|
extern u8 bdm_irx[];
|
||||||
extern int size_bdm_irx;
|
extern int size_bdm_irx;
|
||||||
|
|
||||||
@@ -32,19 +47,41 @@ extern int size_usbmass_bd_irx;
|
|||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
|
bool IrxLoader::isLoaded = false;
|
||||||
|
|
||||||
IrxLoader::IrxLoader() {
|
IrxLoader::IrxLoader() {
|
||||||
SifInitRpc(0);
|
SifInitRpc(0);
|
||||||
|
|
||||||
|
while (!SifIopReset("", 0)) {
|
||||||
|
};
|
||||||
|
while (!SifIopSync()) {
|
||||||
|
};
|
||||||
|
|
||||||
|
SifInitRpc(0);
|
||||||
|
|
||||||
this->applyRpcPatches();
|
this->applyRpcPatches();
|
||||||
}
|
}
|
||||||
|
|
||||||
IrxLoader::~IrxLoader() {}
|
IrxLoader::~IrxLoader() {}
|
||||||
|
|
||||||
void IrxLoader::loadDefaultDrivers() {
|
void IrxLoader::loadAll(const bool& withUsb, const bool& isLoggingToFile) {
|
||||||
this->loadAudio();
|
if (isLoaded) {
|
||||||
this->loadPad();
|
TYRA_LOG("IRX modules already loaded!");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void IrxLoader::loadUSBDriver() { this->loadUsb(); }
|
loadSio2man(!isLoggingToFile);
|
||||||
|
loadPadman(!isLoggingToFile);
|
||||||
|
loadLibsd(!isLoggingToFile);
|
||||||
|
|
||||||
|
if (withUsb) {
|
||||||
|
loadUsbModules(!isLoggingToFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAudsrv(true);
|
||||||
|
|
||||||
|
isLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Apply the SBV LMB patch to allow modules to be loaded from a buffer in
|
* @brief Apply the SBV LMB patch to allow modules to be loaded from a buffer in
|
||||||
@@ -53,7 +90,6 @@ void IrxLoader::loadUSBDriver() { this->loadUsb(); }
|
|||||||
*/
|
*/
|
||||||
int IrxLoader::applyRpcPatches() {
|
int IrxLoader::applyRpcPatches() {
|
||||||
int ret;
|
int ret;
|
||||||
TYRA_LOG("Applying SBV Patches");
|
|
||||||
|
|
||||||
ret = sbv_patch_enable_lmb();
|
ret = sbv_patch_enable_lmb();
|
||||||
TYRA_ASSERT(ret >= 0,
|
TYRA_ASSERT(ret >= 0,
|
||||||
@@ -67,65 +103,69 @@ int IrxLoader::applyRpcPatches() {
|
|||||||
ret = sbv_patch_fileio();
|
ret = sbv_patch_fileio();
|
||||||
TYRA_ASSERT(ret >= 0, "Failed to load Applying SBV Patches sbv_patch_fileio");
|
TYRA_ASSERT(ret >= 0, "Failed to load Applying SBV Patches sbv_patch_fileio");
|
||||||
|
|
||||||
TYRA_LOG("SBV Patches applyed ");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IrxLoader::loadUsb() {
|
void IrxLoader::loadLibsd(const bool& verbose) {
|
||||||
|
if (verbose) TYRA_LOG("IRX: Loading libsd...");
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
TYRA_LOG("Loading USB modules");
|
SifExecModuleBuffer(&libsd_irx, size_libsd_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: libsd_irx");
|
||||||
|
|
||||||
// Load Block Device Manager (BDM)
|
if (verbose) TYRA_LOG("IRX: Libsd loaded!");
|
||||||
SifExecModuleBuffer(&bdm_irx, size_bdm_irx, 0, NULL, &ret);
|
|
||||||
TYRA_ASSERT(ret >= 0, "Failed to load module: usbhdfsd");
|
|
||||||
|
|
||||||
// Load FATFS (mass:) driver
|
|
||||||
SifExecModuleBuffer(&bdmfs_fatfs_irx, size_bdmfs_fatfs_irx, 0, NULL, &ret);
|
|
||||||
TYRA_ASSERT(ret >= 0, "Failed to load module: usbd");
|
|
||||||
|
|
||||||
// Load USB Block Device drivers
|
|
||||||
SifExecModuleBuffer(&usbd_irx, size_usbd_irx, 0, NULL, &ret);
|
|
||||||
TYRA_ASSERT(ret >= 0, "Failed to load module: usbd");
|
|
||||||
|
|
||||||
SifExecModuleBuffer(&usbmass_bd_irx, size_usbmass_bd_irx, 0, NULL, &ret);
|
|
||||||
TYRA_ASSERT(ret >= 0, "Failed to load module: usbhdfsd");
|
|
||||||
|
|
||||||
this->waitUntilUsbDeviceIsReady();
|
|
||||||
|
|
||||||
TYRA_LOG("USB/MASS modules loaded!");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int IrxLoader::loadAudio() {
|
void IrxLoader::loadUsbModules(const bool& verbose) {
|
||||||
|
if (verbose) TYRA_LOG("IRX: Loading usb modules...");
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
TYRA_LOG("Modules loading started (LIBSD, AUDSRV)");
|
SifExecModuleBuffer(&usbd_irx, size_usbd_irx, 0, nullptr, &ret);
|
||||||
ret = SifLoadModule("rom0:LIBSD", 0, NULL);
|
TYRA_ASSERT(ret >= 0, "Failed to load module: usbd_irx");
|
||||||
TYRA_ASSERT(ret != -203, "LIBSD loading failed!");
|
|
||||||
|
|
||||||
ret = SifLoadModule("host:audsrv.irx", 0, NULL);
|
SifExecModuleBuffer(&bdm_irx, size_bdm_irx, 0, nullptr, &ret);
|
||||||
TYRA_ASSERT(ret != -203, "audsrv.irx loading failed!");
|
TYRA_ASSERT(ret >= 0, "Failed to load module: bdm_irx");
|
||||||
TYRA_LOG("Audio modules loaded");
|
|
||||||
|
|
||||||
return ret;
|
SifExecModuleBuffer(&bdmfs_fatfs_irx, size_bdmfs_fatfs_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: bdmfs_fatfs");
|
||||||
|
|
||||||
|
SifExecModuleBuffer(&usbmass_bd_irx, size_usbmass_bd_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: usbmass");
|
||||||
|
|
||||||
|
waitUntilUsbDeviceIsReady();
|
||||||
|
|
||||||
|
if (verbose) TYRA_LOG("IRX: Usb modules loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int IrxLoader::loadPad() {
|
void IrxLoader::loadAudsrv(const bool& verbose) {
|
||||||
|
if (verbose) TYRA_LOG("IRX: Loading audsrv...");
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
SifExecModuleBuffer(&audsrv_irx, size_audsrv_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: audsrv_irx");
|
||||||
|
|
||||||
TYRA_LOG("PAD Modules loading started (SIO2MAN, PADMAN)");
|
if (verbose) TYRA_LOG("IRX: Audsrv loaded!");
|
||||||
|
}
|
||||||
|
|
||||||
ret = SifLoadModule("rom0:SIO2MAN", 0, NULL);
|
void IrxLoader::loadSio2man(const bool& verbose) {
|
||||||
TYRA_ASSERT(ret >= 0,
|
if (verbose) TYRA_LOG("IRX: Loading sio2man...");
|
||||||
"SifLoadModule (SIO2MAN) failed! Returned value: ", ret);
|
|
||||||
|
|
||||||
ret = SifLoadModule("rom0:PADMAN", 0, NULL);
|
int ret;
|
||||||
TYRA_ASSERT(ret >= 0, "SifLoadModule (PADMAN) failed! Returned value: ", ret);
|
SifExecModuleBuffer(&sio2man_irx, size_sio2man_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: sio2man_irx");
|
||||||
|
|
||||||
TYRA_LOG("Pad modules loaded!");
|
if (verbose) TYRA_LOG("IRX: Sio2man loaded!");
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
void IrxLoader::loadPadman(const bool& verbose) {
|
||||||
|
if (verbose) TYRA_LOG("IRX: Loading padman...");
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
SifExecModuleBuffer(&padman_irx, size_padman_irx, 0, nullptr, &ret);
|
||||||
|
TYRA_ASSERT(ret >= 0, "Failed to load module: padman_irx");
|
||||||
|
|
||||||
|
if (verbose) TYRA_LOG("IRX: Padman loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrxLoader::delay(int count) {
|
void IrxLoader::delay(int count) {
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
$PS2SDK/iop/irx/libsd.irx
|
||||||
|
libsd_irx
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
$PS2SDK/iop/irx/padman.irx
|
||||||
|
padman_irx
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
$PS2SDK/iop/irx/sio2man.irx
|
||||||
|
sio2man_irx
|
||||||
@@ -95,7 +95,7 @@ MeshBuilderData* MD2Loader::load(const char* fullpath,
|
|||||||
auto filename = getFilenameFromPath(path);
|
auto filename = getFilenameFromPath(path);
|
||||||
|
|
||||||
FILE* file = fopen(fullpath, "rb");
|
FILE* file = fopen(fullpath, "rb");
|
||||||
TYRA_ASSERT(file != NULL, "Failed to load: ", filename);
|
TYRA_ASSERT(file != nullptr, "Failed to load: ", filename);
|
||||||
md2_t header;
|
md2_t header;
|
||||||
|
|
||||||
fread(reinterpret_cast<char*>(&header), sizeof(md2_t), 1, file);
|
fread(reinterpret_cast<char*>(&header), sizeof(md2_t), 1, file);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ void DynPipRenderer::init(RendererCore* t_core,
|
|||||||
rendererCore = t_core;
|
rendererCore = t_core;
|
||||||
programsRepo = t_programRepo;
|
programsRepo = t_programRepo;
|
||||||
|
|
||||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
dma_channel_initialize(DMA_CHANNEL_VIF1, nullptr, 0);
|
||||||
|
|
||||||
setProgramsCache();
|
setProgramsCache();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ BlockizerProgramsManager::BlockizerProgramsManager() {
|
|||||||
context = 0;
|
context = 0;
|
||||||
vu1BlockData = BlockNotUploaded;
|
vu1BlockData = BlockNotUploaded;
|
||||||
|
|
||||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
dma_channel_initialize(DMA_CHANNEL_VIF1, nullptr, 0);
|
||||||
|
|
||||||
setProgramsCache();
|
setProgramsCache();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
// #define TYRA_RENDERER_VERBOSE_LOG 1
|
// #define TYRA_RENDERER_VERBOSE_LOG 1
|
||||||
|
|
||||||
#ifdef TYRA_RENDERER_VERBOSE_LOG
|
#ifdef TYRA_RENDERER_VERBOSE_LOG
|
||||||
#define Verbose(...) Debug::writeLines("VRB: ", ##__VA_ARGS__, "\n")
|
#define Verbose(...) TyraDebug::writeLines("VRB: ", ##__VA_ARGS__, "\n")
|
||||||
#else
|
#else
|
||||||
#define Verbose(...) ((void)0)
|
#define Verbose(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
// #define TYRA_QBUFF_RENDERER_VERBOSE_LOG 1
|
// #define TYRA_QBUFF_RENDERER_VERBOSE_LOG 1
|
||||||
|
|
||||||
#ifdef TYRA_QBUFF_RENDERER_VERBOSE_LOG
|
#ifdef TYRA_QBUFF_RENDERER_VERBOSE_LOG
|
||||||
#define Verbose(...) Debug::writeLines("VRB: ", ##__VA_ARGS__, "\n")
|
#define Verbose(...) TyraDebug::writeLines("VRB: ", ##__VA_ARGS__, "\n")
|
||||||
#else
|
#else
|
||||||
#define Verbose(...) ((void)0)
|
#define Verbose(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
@@ -98,7 +98,7 @@ void StaPipQBufferRenderer::init(RendererCore* t_core, prim_t* t_prim,
|
|||||||
prim = t_prim;
|
prim = t_prim;
|
||||||
lod = t_lod;
|
lod = t_lod;
|
||||||
|
|
||||||
dma_channel_initialize(DMA_CHANNEL_VIF1, NULL, 0);
|
dma_channel_initialize(DMA_CHANNEL_VIF1, nullptr, 0);
|
||||||
|
|
||||||
setProgramsCache();
|
setProgramsCache();
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void RendererCoreGS::init(RendererSettings* t_settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererCoreGS::initChannels() {
|
void RendererCoreGS::initChannels() {
|
||||||
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0);
|
dma_channel_initialize(DMA_CHANNEL_GIF, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCoreGS::allocateBuffers() {
|
void RendererCoreGS::allocateBuffers() {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Path3::~Path3() {
|
|||||||
void Path3::init(RendererSettings* t_settings) {
|
void Path3::init(RendererSettings* t_settings) {
|
||||||
settings = t_settings;
|
settings = t_settings;
|
||||||
|
|
||||||
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0);
|
dma_channel_initialize(DMA_CHANNEL_GIF, nullptr, 0);
|
||||||
|
|
||||||
TYRA_LOG("Path3 initialized");
|
TYRA_LOG("Path3 initialized");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,27 @@ void Color::copy(Color* out, const float* in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Color::operator=(const Color& v) { copy(this, v); }
|
void Color::operator=(const Color& v) { copy(this, v); }
|
||||||
|
|
||||||
|
void Color::operator+=(const float& v) {
|
||||||
|
r += v;
|
||||||
|
g += v;
|
||||||
|
b += v;
|
||||||
|
a += v;
|
||||||
|
}
|
||||||
|
void Color::operator-=(const float& v) {
|
||||||
|
r -= v;
|
||||||
|
g -= v;
|
||||||
|
b -= v;
|
||||||
|
a -= v;
|
||||||
|
}
|
||||||
|
|
||||||
void Color::operator*=(const float& v) {
|
void Color::operator*=(const float& v) {
|
||||||
r *= v;
|
r *= v;
|
||||||
g *= v;
|
g *= v;
|
||||||
b *= v;
|
b *= v;
|
||||||
a *= v;
|
a *= v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Color::operator/=(const float& v) {
|
void Color::operator/=(const float& v) {
|
||||||
r /= v;
|
r /= v;
|
||||||
g /= v;
|
g /= v;
|
||||||
|
|||||||
Reference in New Issue
Block a user