Initial commit : v3d_16 and m3d_16 classes and some FP (Q8.8 and Q16.16) operations (sqrt/sine/cosine)

This commit is contained in:
Sylvain PILLOT 2024-01-20 22:35:00 +01:00
commit 8bddc5b083
28 changed files with 1239 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# Build files
/build-fx
/build-cg
/build-cg-push
/*.g1a
/*.g3a
# Python bytecode
__pycache__/
# Common IDE files
*.sublime-project
*.sublime-workspace
.vscode

46
CMakeLists.txt Normal file
View File

@ -0,0 +1,46 @@
# Configure with [fxsdk build-fx] or [fxsdk build-cg], which provide the
# toolchain file and module path of the fxSDK
cmake_minimum_required(VERSION 3.15)
project(3Dengine VERSION 1.0 LANGUAGES CXX C ASM)
include(GenerateG3A)
include(Fxconv)
find_package(Gint 2.10 REQUIRED)
find_package(LibProf 2.4 REQUIRED)
set(SOURCES
src/main.cpp
src/utilities/extrakeyboard.cpp
src/utilities/utilities.cpp
src/3dengine/fastmath_num.cpp
src/3dengine/vector3D_num16.cpp
src/3dengine/matrix3D_num16.cpp
# ...
)
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
set(ASSETS
# ...
)
set(ASSETS_fx
assets-fx/example.png
# ...
)
set(ASSETS_cg
assets-cg/example.png
# ...
)
fxconv_declare_assets(${ASSETS_cg} WITH_METADATA)
add_executable(3Dengine ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}})
target_compile_options(3Dengine PRIVATE -Wall -Wextra -Wattributes -O3 -std=c++20)
target_link_options(3Dengine PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage -fno-use-cxa-atexit -fpermissive)
target_link_libraries(3Dengine -lnum LibProf::LibProf Gint::Gint -lstdc++)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
generate_g3a(TARGET 3Dengine OUTPUT "3DEngine.g3a"
NAME "3D Engine" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png)
endif()

3
README.md Normal file
View File

@ -0,0 +1,3 @@
#3D Engine
This is an attempt to create a decent 3D game engine and check how far we can go with 3D rendering on a fx-CG50.

BIN
assets-cg/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,3 @@
example.png:
type: bopti-image
name: img_example

BIN
assets-cg/icon-cg.xcf Normal file

Binary file not shown.

BIN
assets-cg/icon-sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
assets-cg/icon-uns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets-fx/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,3 @@
example.png:
type: bopti-image
name: img_example

BIN
assets-fx/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

1
build Executable file
View File

@ -0,0 +1 @@
fxsdk build-cg VERBOSE=1

1
capture Executable file
View File

@ -0,0 +1 @@
fxlink -iw

4
clean Executable file
View File

@ -0,0 +1,4 @@
rm -r build-cg/
rm -r build-cg-push/
rm -r build-fx/
rm *.g3a

3
rebuild Executable file
View File

@ -0,0 +1,3 @@
rm -r build-cg
rm *.g3a
fxsdk build-cg VERBOSE=1

1
send Executable file
View File

@ -0,0 +1 @@
fxlink -sw *.g3a

View File

@ -0,0 +1,104 @@
#include "fastmath_num.h"
#include <num/num.h>
libnum::num16 fp_sqrt16(libnum::num16 x) {
uint16_t b = 1 << 14, q = 0, r = x.v;
while (b > r)
b >>= 2;
while (b > 0) {
uint16_t t = q + b;
q >>= 1;
if (r >= t) {
r -= t;
q += b;
}
b >>= 2;
}
libnum::num16 ret;
ret.v = q << 4;
return ret;
}
libnum::num16 fp_cos16(libnum::num16 a) {
if (a < 0)
a = -a;
a = a % libnum::num16(6.28319);
if (a > libnum::num16(3.14159))
a -= libnum::num16(6.28319);
libnum::num16 u = 1.0;
int p = 7;
for (p = 2 * p - 1; p >= 1; p -= 2)
u = libnum::num16(1) - a * a / (p * p + p) * u;
return u;
}
libnum::num16 fp_sin16(libnum::num16 a) {
return fp_cos16(a - libnum::num16(1.57080));
}
libnum::num16 fp_tan16(libnum::num16 a) {
libnum::num16 sine = fp_sin16(a);
libnum::num16 cosine = fp_cos16(a);
libnum::num16 ret;
if (sine == 0 && cosine == libnum::num16(-1))
ret.v = 0x8000;
else if (sine == 0 && cosine == libnum::num16(1))
ret.v = 0x7FFF;
else
ret = sine / cosine;
return ret;
}
libnum::num32 fp_sqrt32(libnum::num32 x) {
uint32_t b = 1 << 30, q = 0, r = x.v;
while (b > r)
b >>= 2;
while (b > 0) {
uint32_t t = q + b;
q >>= 1;
if (r >= t) {
r -= t;
q += b;
}
b >>= 2;
}
libnum::num32 ret;
ret.v = q << 8;
return ret;
}
libnum::num32 fp_cos32(libnum::num32 a) {
if (a < 0)
a = -a;
a = a % libnum::num32(6.28319);
if (a > libnum::num32(3.14159))
a -= libnum::num32(6.28319);
libnum::num32 u = 1.0;
int p = 7;
for (p = 2 * p - 1; p >= 1; p -= 2)
u = libnum::num32(1) - a * a / (p * p + p) * u;
return u;
}
libnum::num32 fp_sin32(libnum::num32 a) {
return fp_cos32(a - libnum::num32(1.57080));
}
libnum::num32 fp_tan32(libnum::num32 a) {
libnum::num32 sine = fp_sin32(a);
libnum::num32 cosine = fp_cos32(a);
libnum::num32 ret;
if (sine == 0 && cosine == libnum::num32(-1))
ret.v = 0x80000000;
else if (sine == 0 && cosine == libnum::num32(1))
ret.v = 0x7FFFFFFF;
else
ret = sine / cosine;
return ret;
}

View File

@ -0,0 +1,24 @@
#ifndef FASTMATH_NUM
#define FASTMATH_NUM
#include <num/num.h>
/* take x as a num16 and calcutate its square root as a num16 */
libnum::num16 fp_sqrt16(libnum::num16 x);
/* take x in radians as a num16 and calcutate its cosine value as a num16 */
libnum::num16 fp_cos16(libnum::num16 x);
/* take x in radians as a num16 and calcutate its sine value as a num16 */
libnum::num16 fp_sin16(libnum::num16 x);
/* take x in radians as a num16 and calcutate its tangent value as a num16 */
libnum::num16 fp_tan16(libnum::num16 x);
/* take x as a num32 and calcutate its square root as a num32 */
libnum::num32 fp_sqrt32(libnum::num32 x);
/* take x in radians as a num32 and calcutate its c0sine value as a num32 */
libnum::num32 fp_cos32(libnum::num32 x);
/* take x in radians as a num32 and calcutate its sine value as a num32 */
libnum::num32 fp_sin32(libnum::num32 x);
/* take x in radians as a num32 and calcutate its tangent value as a num32 */
libnum::num32 fp_tan32(libnum::num32 x);
#endif

View File

@ -0,0 +1,93 @@
#include "matrix3D_num16.h"
#include "fastmath_num.h"
#include "vector3D_num16.h"
#include <num/num.h>
#include <stdint.h>
v3d_16 Multiply(m3d_16 m, v3d_16 i) {
v3d_16 ret;
ret.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + i.w * m.m[3][0];
ret.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + i.w * m.m[3][1];
ret.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + i.w * m.m[3][2];
ret.w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + i.w * m.m[3][3];
return ret;
}
v3d_16 Multiply(m3d_16 &m, v3d_16 &i) {
v3d_16 ret;
ret.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + i.w * m.m[3][0];
ret.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + i.w * m.m[3][1];
ret.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + i.w * m.m[3][2];
ret.w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + i.w * m.m[3][3];
return ret;
}
m3d_16 Multiply(m3d_16 m1, m3d_16 m2) {
m3d_16 ret;
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
ret.m[r][c] = m1.m[r][0] * m2.m[0][c] + m1.m[r][1] * m2.m[1][c] +
m1.m[r][2] * m2.m[2][c] + m1.m[r][3] * m2.m[3][c];
return ret;
}
m3d_16 Multiply(m3d_16 &m1, m3d_16 &m2) {
m3d_16 ret;
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
ret.m[r][c] = m1.m[r][0] * m2.m[0][c] + m1.m[r][1] * m2.m[1][c] +
m1.m[r][2] * m2.m[2][c] + m1.m[r][3] * m2.m[3][c];
return ret;
}
m3d_16 QuickInverse(m3d_16 m) {
m3d_16 ret;
ret.m[0][0] = m.m[0][0];
ret.m[0][1] = m.m[1][0];
ret.m[0][2] = m.m[2][0];
ret.m[0][3] = libnum::num16(0);
ret.m[1][0] = m.m[0][1];
ret.m[1][1] = m.m[1][1];
ret.m[1][2] = m.m[2][1];
ret.m[1][3] = libnum::num16(0);
ret.m[2][0] = m.m[0][2];
ret.m[2][1] = m.m[1][2];
ret.m[2][2] = m.m[2][2];
ret.m[2][3] = libnum::num16(0);
ret.m[3][0] = -(m.m[3][0] * ret.m[0][0] + m.m[3][1] * ret.m[1][0] +
m.m[3][2] * ret.m[2][0]);
ret.m[3][1] = -(m.m[3][0] * ret.m[0][1] + m.m[3][1] * ret.m[1][1] +
m.m[3][2] * ret.m[2][1]);
ret.m[3][2] = -(m.m[3][0] * ret.m[0][2] + m.m[3][1] * ret.m[1][2] +
m.m[3][2] * ret.m[2][2]);
ret.m[3][3] = libnum::num16(1);
return ret;
}
m3d_16 QuickInverse(m3d_16 &m) {
m3d_16 ret;
ret.m[0][0] = m.m[0][0];
ret.m[0][1] = m.m[1][0];
ret.m[0][2] = m.m[2][0];
ret.m[0][3] = libnum::num16(0);
ret.m[1][0] = m.m[0][1];
ret.m[1][1] = m.m[1][1];
ret.m[1][2] = m.m[2][1];
ret.m[1][3] = libnum::num16(0);
ret.m[2][0] = m.m[0][2];
ret.m[2][1] = m.m[1][2];
ret.m[2][2] = m.m[2][2];
ret.m[2][3] = libnum::num16(0);
ret.m[3][0] = -(m.m[3][0] * ret.m[0][0] + m.m[3][1] * ret.m[1][0] +
m.m[3][2] * ret.m[2][0]);
ret.m[3][1] = -(m.m[3][0] * ret.m[0][1] + m.m[3][1] * ret.m[1][1] +
m.m[3][2] * ret.m[2][1]);
ret.m[3][2] = -(m.m[3][0] * ret.m[0][2] + m.m[3][1] * ret.m[1][2] +
m.m[3][2] * ret.m[2][2]);
ret.m[3][3] = libnum::num16(1);
return ret;
}

View File

@ -0,0 +1,96 @@
#ifndef MATRIX3D_NUM16
#define MATRIX3D_NUM16
#include "fastmath_num.h"
#include "vector3D_num16.h"
#include <num/num.h>
#include <stdint.h>
class m3d_16 {
public:
void MakeIdentity(void) {
m[0][0] = libnum::num16(1);
m[1][1] = libnum::num16(1);
m[2][2] = libnum::num16(1);
m[3][3] = libnum::num16(1);
}
void MakeRotationX(libnum::num16 angle) {
libnum::num16 cosine = fp_cos16(angle);
libnum::num16 sine = fp_sin16(angle);
m[0][0] = libnum::num16(1);
m[1][1] = cosine;
m[1][2] = sine;
m[2][1] = -sine;
m[2][2] = cosine;
m[3][3] = libnum::num16(1);
}
void MakeRotationY(libnum::num16 angle) {
libnum::num16 cosine = fp_cos16(angle);
libnum::num16 sine = fp_sin16(angle);
m[0][0] = cosine;
m[0][2] = sine;
m[2][0] = -sine;
m[1][1] = libnum::num16(1);
m[2][2] = cosine;
m[3][3] = libnum::num16(1);
}
void MakeRotationZ(libnum::num16 angle) {
libnum::num16 cosine = fp_cos16(angle);
libnum::num16 sine = fp_sin16(angle);
m[0][0] = cosine;
m[0][1] = sine;
m[1][0] = -sine;
m[1][1] = cosine;
m[2][2] = libnum::num16(1);
m[3][3] = libnum::num16(1);
}
void MakeTranslation(v3d_16 vecT) {
m[0][0] = libnum::num16(1);
m[1][1] = libnum::num16(1);
m[2][2] = libnum::num16(1);
m[3][3] = libnum::num16(1);
m[3][0] = vecT.x;
m[3][1] = vecT.y;
m[3][2] = vecT.z;
}
void MakeProjection(libnum::num16 fov_degree, libnum::num16 aspect_ratio,
libnum::num16 near_distance, libnum::num16 far_distance) {
libnum::num16 fov_rad =
libnum::num16(1) /
fp_tan16(fov_degree * libnum::num16(0.5f) / libnum::num16(180) *
libnum::num16(3.14159f));
m[0][0] = aspect_ratio * fov_rad;
m[1][1] = fov_rad;
m[2][2] = far_distance / (far_distance - near_distance);
m[3][2] = (-far_distance * near_distance) / (far_distance - near_distance);
m[2][3] = libnum::num16(1);
m[3][3] = libnum::num16(0);
}
void MakeScale(libnum::num16 scaleX, libnum::num16 scaleY,
libnum::num16 scaleZ) {
m[0][0] = scaleX;
m[1][1] = scaleY;
m[2][2] = scaleZ;
m[3][3] = libnum::num16(1);
}
libnum::num16 m[4][4] = {0};
};
v3d_16 Multiply(m3d_16 m, v3d_16 i);
v3d_16 Multiply(m3d_16 &m, v3d_16 &i);
m3d_16 Multiply(m3d_16 m1, m3d_16 m2);
m3d_16 Multiply(m3d_16 &m1, m3d_16 &m2);
m3d_16 QuickInverse(m3d_16 m);
m3d_16 QuickInverse(m3d_16 &m);
#endif

View File

@ -0,0 +1,117 @@
#include "vector3D_num16.h"
#include "fastmath_num.h"
v3d_16::v3d_16() {
this->x = libnum::num16(0);
this->y = libnum::num16(0);
this->z = libnum::num16(0);
this->w = libnum::num16(1);
}
v3d_16::v3d_16(int x, int y, int z) {
this->x = libnum::num16(x);
this->y = libnum::num16(y);
this->z = libnum::num16(z);
this->w = libnum::num16(1);
}
v3d_16::v3d_16(float x, float y, float z) {
this->x = libnum::num16(x);
this->y = libnum::num16(y);
this->z = libnum::num16(z);
this->w = libnum::num16(1);
}
v3d_16::v3d_16(libnum::num16 x, libnum::num16 y, libnum::num16 z) {
this->x = x;
this->y = y;
this->z = z;
this->w = libnum::num16(1);
}
v3d_16::v3d_16(const v3d_16 &v) {
this->x = v.x;
this->y = v.y;
this->z = v.z;
this->w = libnum::num16(1);
}
v3d_16::~v3d_16() {}
void v3d_16::Set(v3d_16 v) {
this->x = v.x;
this->y = v.y;
this->z = v.z;
this->w = libnum::num16(1);
}
void v3d_16::Normalise(void) {
libnum::num16 len = this->Length();
this->x /= len;
this->y /= len;
this->z /= len;
}
v3d_16 v3d_16::Clone(void) {
v3d_16 NewVector(this->x, this->y, this->z);
return NewVector;
}
v3d_16 v3d_16::MakeVector(v3d_16 A, v3d_16 B) {
v3d_16 NewVector(B.x - A.x, B.y - A.y, B.z - A.z);
return NewVector;
}
void v3d_16::AddVectors(v3d_16 a, v3d_16 b) {
this->x = a.x + b.x;
this->y = a.y + b.y;
this->z = a.z + b.z;
}
void v3d_16::Add(v3d_16 v, libnum::num16 scale) {
this->x += v.x * scale;
this->y += v.y * scale;
this->z += v.z * scale;
}
void v3d_16::SubtractVectors(v3d_16 a, v3d_16 b) {
this->x = a.x - b.x;
this->y = a.y - b.y;
this->z = a.z - b.z;
}
void v3d_16::Subtract(v3d_16 v, libnum::num16 scale) {
this->x -= v.x * scale;
this->y -= v.y * scale;
this->z -= v.y * scale;
}
libnum::num16 v3d_16::Length(void) {
return fp_sqrt16(this->x * this->x + this->y * this->y + this->z * this->z);
}
void v3d_16::Scale(libnum::num16 scale) {
this->x *= scale;
this->y *= scale;
this->z *= scale;
}
libnum::num16 v3d_16::Dot(v3d_16 v) {
return (this->x * v.x + this->y * v.y + this->z * v.z);
}
v3d_16 CrossProduct(v3d_16 v1, v3d_16 v2) {
v3d_16 vret;
vret.x = v1.y * v2.z - v1.z * v2.y;
vret.y = v1.z * v2.x - v1.x * v2.z;
vret.z = v1.x * v2.y - v1.y * v2.x;
return vret;
}
v3d_16 CrossProduct(v3d_16 &v1, v3d_16 &v2) {
v3d_16 vret;
vret.x = v1.y * v2.z - v1.z * v2.y;
vret.y = v1.z * v2.x - v1.x * v2.z;
vret.z = v1.x * v2.y - v1.y * v2.x;
return vret;
}

View File

@ -0,0 +1,120 @@
#ifndef VECTOR3D_NUM16
#define VECTOR3D_NUM16
#include <num/num.h>
#include <stdint.h>
class v3d_16 {
public:
v3d_16();
v3d_16(float x, float y, float z);
v3d_16(int x, int y, int z);
v3d_16(libnum::num16 x, libnum::num16 y, libnum::num16 z);
v3d_16(const v3d_16 &v);
~v3d_16();
void Set(v3d_16 v);
void Normalise(void);
v3d_16 Clone(void);
v3d_16 MakeVector(v3d_16 A, v3d_16 B);
void AddVectors(v3d_16 a, v3d_16 b);
void Add(v3d_16 v, libnum::num16 scale);
void SubtractVectors(v3d_16 a, v3d_16 b);
void Subtract(v3d_16 v, libnum::num16 scale);
libnum::num16 Length(void);
void Scale(libnum::num16 scale);
libnum::num16 Dot(v3d_16 v);
/* overloading of most interesting operators */
libnum::num16 operator[](uint8_t pos) {
return pos == 0 ? x : pos == 1 ? y : pos == 2 ? z : w;
}
v3d_16 &operator=(const v3d_16 &v) {
this->x = v.x;
this->y = v.y;
this->z = v.z;
this->w = v.w;
return *this;
}
v3d_16 operator+(const v3d_16 &v) const {
return v3d_16(x + v.x, y + v.y, z + v.z);
}
v3d_16 operator-(const v3d_16 &v) const {
return v3d_16(x - v.x, y - v.y, z - v.z);
}
v3d_16 &operator+=(v3d_16 const &other) {
this->x += other.x;
this->y += other.y;
this->z += other.z;
return *this;
}
v3d_16 operator-() const { return (v3d_16(-x, -y, -z)); }
v3d_16 operator+() const { return *this; }
v3d_16 &operator-=(v3d_16 const &other) {
this->x -= other.x;
this->y -= other.y;
this->z -= other.z;
return *this;
}
v3d_16 &operator*=(libnum::num16 scale) {
this->x *= scale;
this->y *= scale;
this->z *= scale;
return *this;
}
v3d_16 &operator/=(libnum::num16 scale) {
this->x /= scale;
this->y /= scale;
this->z /= scale;
return *this;
}
friend v3d_16 operator*(libnum::num16 scale, v3d_16 const &v) {
v3d_16 r;
r.x = v.x * scale;
r.y = v.y * scale;
r.z = v.z * scale;
return r;
}
friend v3d_16 operator*(v3d_16 const &v, libnum::num16 scale) {
v3d_16 r;
r.x = v.x * scale;
r.y = v.y * scale;
r.z = v.z * scale;
return r;
}
friend v3d_16 operator/(v3d_16 const &v, libnum::num16 scale) {
v3d_16 r;
r.x = v.x / scale;
r.y = v.y / scale;
r.z = v.z / scale;
return r;
}
/* usual (x,y,z) coordinates */
libnum::num16 x = libnum::num16(0);
libnum::num16 y = libnum::num16(0);
libnum::num16 z = libnum::num16(0);
/* w is used for mat4_4 calculations that can be used to treat translations */
libnum::num16 w = libnum::num16(1);
};
v3d_16 CrossProduct(v3d_16 v1, v3d_16 v2);
v3d_16 CrossProduct(v3d_16 &v1, v3d_16 &v2);
#endif

35
src/config.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef CONFIG_H
#define CONFIG_H
#define MAXHEIGHT 224
#define MORE_RAM 1
/* usual colors*/
#define RGB565_BLACK 0x0000
#define RGB565_RED 0xF800
#define RGB565_GREEN 0x07E0
#define RGB565_BLUE 0x001F
#define RGB565_YELLOW 0xFFE0
#define RGB565_PURPLE 0xF81F
#define RGB565_CYAN 0x07FF
#define RGB565_WHITE 0xFFFF
/* advanced palette */
#define RGB565_DARKORANGE 0xF280
#define RGB565_ORANGE 0xF4A0
#define RGB565_LIGHORANGE 0xF5C0
#define RGB565_LEMONYELLOW 0xF7C6
#define RGB565_APPLEGREEN 0xCF25
#define RGB565_LEAFGREEN 0x6566
#define RGB565_OCEANBLUE 0x0479
#define RGB565_AZURBLUE 0x023E
#define RGB565_DEEPBLUE 0x3813
#define RGB565_DEEPPURPLE 0x8015
#define RGB565_CHERRYRED 0xA0C9
#define RGB565_BLOODYRED 0xF122
#endif

282
src/main.cpp Normal file
View File

@ -0,0 +1,282 @@
#include <cstdint>
#include <gint/clock.h>
#include <gint/display.h>
#include <gint/dma.h>
#include <gint/image.h>
#include <gint/keyboard.h>
#include <gint/rtc.h>
#include <fxlibc/printf.h>
#include "config.h"
#include <gint/kmalloc.h>
#include <libprof.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "utilities/extrakeyboard.h"
#include "utilities/utilities.h"
#include <string>
#if (MORE_RAM)
kmalloc_arena_t extended_ram = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, 0, 0, 0};
kmalloc_arena_t *_uram;
kmalloc_gint_stats_t *_uram_stats;
kmalloc_gint_stats_t *extram_stats;
#else
kmalloc_arena_t *_uram;
kmalloc_gint_stats_t *_uram_stats;
#endif
bool exitToOS = false;
bool screenshot = false;
bool record = false;
bool showFPS = true;
bool showDebug = true;
bool canWeAllocateMoreRam = false;
KeyboardExtra Keyboard;
float elapsedTime = 0.0f;
uint32_t time_update = 0, time_render = 0;
prof_t perf_update, perf_render;
extern font_t font_matrix;
extern font_t font_label;
bopti_image_t *screen;
void Initialise(void);
void Update(void);
void Render(void);
void Close(void);
bool AddMoreRAM(void) {
#if (MORE_RAM && !CALCEMU)
/* allow more RAM */
char const *osv = (char *)0x80020020;
if ((!strncmp(osv, "03.", 3) && osv[3] <= '8') &&
gint[HWCALC] == HWCALC_FXCG50) // CG-50
{
extended_ram.name = "extram";
extended_ram.is_default = true;
extended_ram.start = (void *)0x8c200000;
extended_ram.end = (void *)0x8c4e0000;
kmalloc_init_arena(&extended_ram, true);
kmalloc_add_arena(&extended_ram);
return true;
} else if (gint[HWCALC] == HWCALC_PRIZM) // CG-10/20
{
extended_ram.name = "extram";
extended_ram.is_default = true;
uint16_t *vram1, *vram2;
dgetvram(&vram1, &vram2);
dsetvram(vram1, vram1);
extended_ram.start = vram2;
extended_ram.end = (char *)vram2 + 396 * 224 * 2;
kmalloc_init_arena(&extended_ram, true);
kmalloc_add_arena(&extended_ram);
return false;
} else if (gint[HWCALC] == HWCALC_FXCG_MANAGER) // CG-50 EMULATOR
{
extended_ram.name = "extram";
extended_ram.is_default = true;
extended_ram.start = (void *)0x88200000;
extended_ram.end = (void *)0x884e0000;
kmalloc_init_arena(&extended_ram, true);
kmalloc_add_arena(&extended_ram);
return true;
}
#elif (MORE_RAM && CALCEMU)
extended_ram.name = "extram";
extended_ram.is_default = true;
extended_ram.start = (void *)0x8c200000;
extended_ram.end = (void *)0x8c4e0000;
kmalloc_init_arena(&extended_ram, true);
kmalloc_add_arena(&extended_ram);
return true;
#else
return false;
#endif
return false;
}
void FreeMoreRAM(void) {
#if (MORE_RAM)
memset(extended_ram.start, 0,
(char *)extended_ram.end - (char *)extended_ram.start);
#endif
}
void GetInputs([[maybe_unused]] float dt) {
if (Keyboard.IsKeyPressed(MYKEY_EXIT)) {
exitToOS = true;
};
if (Keyboard.IsKeyPressedEvent(MYKEY_OPTN))
showFPS = !showFPS;
if (Keyboard.IsKeyPressedEvent(MYKEY_MENU))
showDebug = !showDebug;
}
void Initialise(void) {}
void Render(void) {
if (showFPS) {
// dfont( &font_label );
dprint(11, 6, C_RED, "Framerate : %.0f FPS",
(float)(1000000.0f / elapsedTime));
dprint(10, 5, C_WHITE, "Framerate : %.0f FPS",
(float)(1000000.0f / elapsedTime));
}
if (showDebug) {
// dfont( &font_label );
#if (MORE_RAM)
if (canWeAllocateMoreRam) {
dprint(261, 6, C_RED, "Mem Used : %d Kb",
(_uram_stats->used_memory + extram_stats->used_memory) / 1024);
dprint(260, 5, C_WHITE, "Mem Used : %d Kb",
(_uram_stats->used_memory + extram_stats->used_memory) / 1024);
dprint(261, 21, C_RED, "Mem Free : %d Kb",
(_uram_stats->free_memory + extram_stats->free_memory) / 1024);
dprint(260, 22, C_WHITE, "Mem Free : %d Kb",
(_uram_stats->free_memory + extram_stats->free_memory) / 1024);
dprint(261, 36, C_RED, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory + extram_stats->peak_used_memory) /
1024);
dprint(260, 35, C_WHITE, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory + extram_stats->peak_used_memory) /
1024);
} else {
dprint(261, 6, C_RED, "Mem Used : %d Kb",
(_uram_stats->used_memory) / 1024);
dprint(260, 5, C_WHITE, "Mem Used : %d Kb",
(_uram_stats->used_memory) / 1024);
dprint(261, 21, C_RED, "Mem Free : %d Kb",
(_uram_stats->free_memory) / 1024);
dprint(260, 20, C_WHITE, "Mem Free : %d Kb",
(_uram_stats->free_memory) / 1024);
dprint(261, 36, C_RED, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory) / 1024);
dprint(260, 35, C_WHITE, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory) / 1024);
}
#else
dprint(261, 6, C_RED, "Mem Used : %d Kb",
(_uram_stats->used_memory) / 1024);
dprint(260, 5, C_WHITE, "Mem Used : %d Kb",
(_uram_stats->used_memory) / 1024);
dprint(261, 21, C_RED, "Mem Free : %d Kb",
(_uram_stats->free_memory) / 1024);
dprint(260, 20, C_WHITE, "Mem Free : %d Kb",
(_uram_stats->free_memory) / 1024);
dprint(261, 36, C_RED, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory) / 1024);
dprint(260, 35, C_WHITE, "Mem Peak : %d Kb",
(_uram_stats->peak_used_memory) / 1024);
#endif
}
}
void Update([[maybe_unused]] float dt) {}
void Close(void) {}
int main(void) {
_uram = kmalloc_get_arena("_uram");
#if (MORE_RAM)
canWeAllocateMoreRam = AddMoreRAM();
#endif
int EntryClockLevel;
EntryClockLevel = clock_get_speed();
clock_set_speed(CLOCK_SPEED_F4);
srand(rtc_ticks());
exitToOS = false;
Initialise();
__printf_enable_fp();
__printf_enable_fixed();
prof_init();
do {
perf_update = prof_make();
prof_enter(perf_update);
{
// all the stuff to be update should be put here
Keyboard.Update();
// read inputs from the player
GetInputs(elapsedTime);
// update as per the time spend to do the loop
Update(elapsedTime);
// update the RAM consumption status
_uram_stats = kmalloc_get_gint_stats(_uram);
#if (MORE_RAM)
extram_stats = kmalloc_get_gint_stats(&extended_ram);
#endif
}
prof_leave(perf_update);
time_update = prof_time(perf_update);
perf_render = prof_make();
prof_enter(perf_render);
{
dclear(C_BLACK);
// Call the render functions
Render();
dupdate();
}
prof_leave(perf_render);
time_render = prof_time(perf_render);
elapsedTime = ((float)(time_update + time_render));
} while (exitToOS == false);
Close();
prof_quit();
clock_set_speed(EntryClockLevel);
#if (MORE_RAM)
if (canWeAllocateMoreRam)
FreeMoreRAM();
#endif
return 1;
}

View File

@ -0,0 +1,166 @@
#include "../config.h"
#include "extrakeyboard.h"
#include <gint/keyboard.h>
#include <gint/rtc.h>
#include <cstdint>
typedef struct
{
bool pressed;
uint32_t since = 0;
} keyinfo;
keyinfo MyKeyMapper[MYKEY_LASTENUM+1];
KeyboardExtra::KeyboardExtra()
{
uint32_t timer = rtc_ticks();
now = timer;
for(int i=0; i<=MYKEY_LASTENUM; i++) MyKeyMapper[i] = { .pressed = false, .since = timer };
}
KeyboardExtra::~KeyboardExtra()
{
}
void KeyboardExtra::Update( void )
{
this->Update( 0.0f );
}
void KeyboardExtra::Update( [[maybe_unused]] float dt )
{
uint32_t timer = rtc_ticks();
now = timer;
key_event_t ev;
int keycode = -1;
while((ev = pollevent()).type != KEYEV_NONE)
{
if (ev.key == KEY_F1) keycode = MYKEY_F1;
else if(ev.key == KEY_F2) keycode = MYKEY_F2;
else if(ev.key == KEY_F3) keycode = MYKEY_F3;
else if(ev.key == KEY_F4) keycode = MYKEY_F4;
else if(ev.key == KEY_F5) keycode = MYKEY_F5;
else if(ev.key == KEY_F6) keycode = MYKEY_F6;
else if(ev.key == KEY_SHIFT) keycode = MYKEY_SHIFT;
else if(ev.key == KEY_OPTN) keycode = MYKEY_OPTN;
else if(ev.key == KEY_VARS) keycode = MYKEY_VARS;
else if(ev.key == KEY_MENU) keycode = MYKEY_MENU;
else if(ev.key == KEY_LEFT) keycode = MYKEY_LEFT;
else if(ev.key == KEY_UP) keycode = MYKEY_UP;
else if(ev.key == KEY_ALPHA) keycode = MYKEY_ALPHA;
else if(ev.key == KEY_SQUARE) keycode = MYKEY_SQUARE;
else if(ev.key == KEY_POWER) keycode = MYKEY_POWER;
else if(ev.key == KEY_EXIT) keycode = MYKEY_EXIT;
else if(ev.key == KEY_DOWN) keycode = MYKEY_DOWN;
else if(ev.key == KEY_RIGHT) keycode = MYKEY_RIGHT;
else if(ev.key == KEY_XOT) keycode = MYKEY_XOT;
else if(ev.key == KEY_LOG) keycode = MYKEY_LOG;
else if(ev.key == KEY_LN) keycode = MYKEY_LN;
else if(ev.key == KEY_SIN) keycode = MYKEY_SIN;
else if(ev.key == KEY_COS) keycode = MYKEY_COS;
else if(ev.key == KEY_TAN) keycode = MYKEY_TAN;
else if(ev.key == KEY_FRAC) keycode = MYKEY_FRAC;
else if(ev.key == KEY_FD) keycode = MYKEY_FD;
else if(ev.key == KEY_LEFTP) keycode = MYKEY_LEFTP;
else if(ev.key == KEY_RIGHTP) keycode = MYKEY_RIGHTP;
else if(ev.key == KEY_COMMA) keycode = MYKEY_COMMA;
else if(ev.key == KEY_ARROW) keycode = MYKEY_ARROW;
else if(ev.key == KEY_7) keycode = MYKEY_7;
else if(ev.key == KEY_8) keycode = MYKEY_8;
else if(ev.key == KEY_9) keycode = MYKEY_9;
else if(ev.key == KEY_DEL) keycode = MYKEY_DEL;
else if(ev.key == KEY_4) keycode = MYKEY_4;
else if(ev.key == KEY_5) keycode = MYKEY_5;
else if(ev.key == KEY_6) keycode = MYKEY_6;
else if(ev.key == KEY_MUL) keycode = MYKEY_MUL;
else if(ev.key == KEY_DIV) keycode = MYKEY_DIV;
else if(ev.key == KEY_1) keycode = MYKEY_1;
else if(ev.key == KEY_2) keycode = MYKEY_2;
else if(ev.key == KEY_3) keycode = MYKEY_3;
else if(ev.key == KEY_ADD) keycode = MYKEY_ADD;
else if(ev.key == KEY_SUB) keycode = MYKEY_SUB;
else if(ev.key == KEY_0) keycode = MYKEY_0;
else if(ev.key == KEY_DOT) keycode = MYKEY_DOT;
else if(ev.key == KEY_EXP) keycode = MYKEY_EXP;
else if(ev.key == KEY_NEG) keycode = MYKEY_NEG;
else if(ev.key == KEY_EXE) keycode = MYKEY_EXE;
else if(ev.key == KEY_ACON) keycode = MYKEY_ACON;
if(keycode!=-1)
{
if (ev.type == KEYEV_DOWN) MyKeyMapper[keycode] = { .pressed = true, .since = timer };
else if (ev.type == KEYEV_UP) MyKeyMapper[keycode] = { .pressed = false, .since = timer };
else if (ev.type == KEYEV_HOLD) {}
}
else
{
// do nothing, just unstack the event from the events queue
};
}
}
bool KeyboardExtra::IsKeyPressedEvent( int key )
{
return (MyKeyMapper[key].pressed && MyKeyMapper[key].since == now);
}
bool KeyboardExtra::IsKeyReleasedEvent( int key )
{
return (!MyKeyMapper[key].pressed && MyKeyMapper[key].since == now);
}
bool KeyboardExtra::IsKeyPressed( int key )
{
return MyKeyMapper[key].pressed;
}
bool KeyboardExtra::IsKeyReleased( int key )
{
return (!MyKeyMapper[key].pressed);
}
uint32_t KeyboardExtra::IsKeyHoldPressed( int key )
{
if (MyKeyMapper[key].pressed && MyKeyMapper[key].since < now)
return (uint32_t) (now-MyKeyMapper[key].since);
else return 0;
}
uint32_t KeyboardExtra::IsKeyHoldReleased( int key )
{
if (!MyKeyMapper[key].pressed && MyKeyMapper[key].since < now)
return (uint32_t) (now-MyKeyMapper[key].since);
else return 0;
}
uint32_t KeyboardExtra::GetLastTickKeyEvent( int key )
{
return (uint32_t) MyKeyMapper[key].since;
}

View File

@ -0,0 +1,95 @@
#ifndef EXTRAKEYBOARD_H
#define EXTRAKEYBOARD_H
#include <cstdint>
enum
{
MYKEY_F1=0,
MYKEY_F2,
MYKEY_F3,
MYKEY_F4,
MYKEY_F5,
MYKEY_F6,
MYKEY_SHIFT,
MYKEY_OPTN,
MYKEY_VARS,
MYKEY_MENU,
MYKEY_LEFT,
MYKEY_UP,
MYKEY_ALPHA,
MYKEY_SQUARE,
MYKEY_POWER,
MYKEY_EXIT,
MYKEY_DOWN,
MYKEY_RIGHT,
MYKEY_XOT,
MYKEY_LOG,
MYKEY_LN,
MYKEY_SIN,
MYKEY_COS,
MYKEY_TAN,
MYKEY_FRAC,
MYKEY_FD,
MYKEY_LEFTP,
MYKEY_RIGHTP,
MYKEY_COMMA,
MYKEY_ARROW,
MYKEY_7,
MYKEY_8,
MYKEY_9,
MYKEY_DEL,
MYKEY_4,
MYKEY_5,
MYKEY_6,
MYKEY_MUL,
MYKEY_DIV,
MYKEY_1,
MYKEY_2,
MYKEY_3,
MYKEY_ADD,
MYKEY_SUB,
MYKEY_0,
MYKEY_DOT,
MYKEY_EXP,
MYKEY_NEG,
MYKEY_EXE,
MYKEY_ACON,
MYKEY_LASTENUM,
};
class KeyboardExtra
{
public:
KeyboardExtra();
~KeyboardExtra();
void Update( float dt );
void Update( void );
bool IsKeyPressedEvent( int key );
bool IsKeyReleasedEvent( int key );
bool IsKeyPressed( int key );
bool IsKeyReleased( int key );
uint32_t IsKeyHoldPressed( int key );
uint32_t IsKeyHoldReleased( int key );
uint32_t GetLastTickKeyEvent( int key );
private:
uint32_t now;
};
#endif

View File

@ -0,0 +1,16 @@
#include "../config.h"
#include <azur/azur.h>
#include <azur/gint/render.h>
#include "utilities.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fxlibc/printf.h>
#include <sys/types.h>
#include <num/num.h>
#include <algorithm>

12
src/utilities/utilities.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef UTILITIES_H
#define UTILITIES_H
#include <cstdint>
#define ABS(a) ((a) < 0 ? -(a) : (a))
#define FLOOR(a) ((a) < 0 ? (int)((a)-1.0) : (int)(a))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SGN(a) ((a) < 0 ? -1 : (a) > 0 ? 1 : 0)
#endif