mirror of
https://github.com/h4zesec/OrbisTTY.git
synced 2026-10-06 07:00:20 +02:00
Add files via upload
This commit is contained in:
1 parent
8a6288580e
commit
f7092f48f6
11 files changed
+495
No files matched your search
@@ -0,0 +1,295 @@
|
||||
#include "OrbisTTY.h"
|
||||
|
||||
OrbisTTY_2D::OrbisTTY_2D(int pixel_depth) {
|
||||
this->depth = pixel_depth;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::update_resolution(void) {
|
||||
OrbisVideoOutResolutionStatus resolution_status;
|
||||
sceVideoOutGetResolutionStatus(this->video, &resolution_status);
|
||||
|
||||
this->resolution.x = resolution_status.width;
|
||||
this->resolution.y = resolution_status.height;
|
||||
|
||||
this->frame_buffer_size = this->resolution.x * this->resolution.y * this->depth;
|
||||
}
|
||||
|
||||
bool OrbisTTY_2D::init(size_t mem_size, int num_frame_buffers) {
|
||||
this->video = sceVideoOutOpen(ORBIS_VIDEO_USER_MAIN, ORBIS_VIDEO_OUT_BUS_MAIN, 0, 0);
|
||||
this->video_mem = NULL;
|
||||
|
||||
if (this->video < 0)
|
||||
return false;
|
||||
|
||||
if (sceSysmoduleLoadModule(ORBIS_SYSMODULE_FREETYPE_OL) < 0)
|
||||
return false;
|
||||
|
||||
if (FT_Init_FreeType(&this->freetype_lib) != 0)
|
||||
return false;
|
||||
|
||||
if (!this->init_flip_queue())
|
||||
return false;
|
||||
|
||||
this->update_resolution();
|
||||
|
||||
if (!this->alloc_video_mem(mem_size, 0x200000))
|
||||
return false;
|
||||
|
||||
if (!this->alloc_frame_buffers(num_frame_buffers))
|
||||
return false;
|
||||
|
||||
sceVideoOutSetFlipRate(this->video, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OrbisTTY_2D::init_flip_queue(void) {
|
||||
if (sceKernelCreateEqueue(&flip_queue, "orbistty flip queue") < 0)
|
||||
return false;
|
||||
|
||||
sceVideoOutAddFlipEvent(flip_queue, this->video, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OrbisTTY_2D::alloc_frame_buffers(int num) {
|
||||
this->frame_buffers = new char* [num];
|
||||
|
||||
for (int index = 0; index < num; index++)
|
||||
this->frame_buffers[index] = this->alloc_display_mem(frame_buffer_size);
|
||||
|
||||
sceVideoOutSetBufferAttribute(&this->attr, 0x80000000, 1, 0, this->resolution.x, this->resolution.y, this->resolution.x);
|
||||
|
||||
return (sceVideoOutRegisterBuffers(this->video, 0, reinterpret_cast<void**>(this->frame_buffers), num, &this->attr) == 0);
|
||||
}
|
||||
|
||||
char* OrbisTTY_2D::alloc_display_mem(size_t size) {
|
||||
char* alloc_ptr = reinterpret_cast<char*>(video_memory_sp);
|
||||
video_memory_sp += size;
|
||||
|
||||
return alloc_ptr;
|
||||
}
|
||||
|
||||
bool OrbisTTY_2D::alloc_video_mem(size_t size, int alignment) {
|
||||
this->direct_mem_alloc_size = (size + alignment - 1) / alignment * alignment;
|
||||
|
||||
if (sceKernelAllocateDirectMemory(0, sceKernelGetDirectMemorySize(), this->direct_mem_alloc_size, alignment, 3, &this->direct_mem_off) < 0) {
|
||||
this->direct_mem_alloc_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sceKernelMapDirectMemory(&this->video_mem, this->direct_mem_alloc_size, 0x33, 0, this->direct_mem_off, alignment) < 0) {
|
||||
sceKernelReleaseDirectMemory(this->direct_mem_off, this->direct_mem_alloc_size);
|
||||
|
||||
this->direct_mem_off = 0;
|
||||
this->direct_mem_alloc_size = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this->video_memory_sp = reinterpret_cast<uintptr_t>(this->video_mem);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::free_video_mem(void) {
|
||||
sceKernelReleaseDirectMemory(this->direct_mem_off, this->direct_mem_alloc_size);
|
||||
|
||||
this->video_mem = 0;
|
||||
this->video_memory_sp = 0;
|
||||
this->direct_mem_off = 0;
|
||||
this->direct_mem_alloc_size = 0;
|
||||
|
||||
delete this->frame_buffers;
|
||||
this->frame_buffers = 0;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::set_active_frame_buffer(int index) {
|
||||
this->active_frame_buffer_index = index;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::submit_flip(int frame_id) {
|
||||
sceVideoOutSubmitFlip(this->video, this->active_frame_buffer_index, ORBIS_VIDEO_OUT_FLIP_VSYNC, frame_id);
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::frame_wait(int frame_id) {
|
||||
OrbisKernelEvent event;
|
||||
int count;
|
||||
|
||||
if (this->video == 0)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
OrbisVideoOutFlipStatus flip_status;
|
||||
sceVideoOutGetFlipStatus(video, &flip_status);
|
||||
if (flip_status.flipArg == frame_id)
|
||||
break;
|
||||
|
||||
if (sceKernelWaitEqueue(this->flip_queue, &event, 1, &count, 0) != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::frame_buffer_swap(void) {
|
||||
this->active_frame_buffer_index = (this->active_frame_buffer_index + 1) % 2;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::frame_buffer_clear(void) {
|
||||
this->frame_buffer_fill(white);
|
||||
}
|
||||
|
||||
bool OrbisTTY_2D::use_font(const char* font_path) {
|
||||
if (FT_New_Face(this->freetype_lib, font_path, 0, &this->font_face) < 0)
|
||||
return false;
|
||||
|
||||
if (FT_Set_Pixel_Sizes(this->font_face, 0, 16) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::frame_buffer_fill(struct OrbisTTY_Color color) {
|
||||
this->draw_rectangle(0, 0, this->resolution.x, this->resolution.y, color);
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::draw_pixel(int x, int y, struct OrbisTTY_Color color) {
|
||||
int pixel = (y * this->resolution.x) + x;
|
||||
|
||||
uint32_t encoded_color = 0x80000000 + (color.red << 16) + (color.green << 8) + color.blue;
|
||||
|
||||
(reinterpret_cast<uint32_t*>(this->frame_buffers[this->active_frame_buffer_index]))[pixel] = encoded_color;
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::draw_rectangle(int x, int y, int width, int height, struct OrbisTTY_Color color) {
|
||||
int x_position;
|
||||
int y_position;
|
||||
|
||||
for (y_position = y; y_position < y + height; y_position++) {
|
||||
for (x_position = x; x_position < x + width; x_position++)
|
||||
this->draw_pixel(x_position, y_position, color);
|
||||
}
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::draw_text(char* text, int start_x, int start_y, struct OrbisTTY_Color bg_color, struct OrbisTTY_Color fg_color) {
|
||||
int x_offset = 0;
|
||||
int y_offset = 0;
|
||||
|
||||
FT_GlyphSlot slot = this->font_face->glyph;
|
||||
|
||||
for (int n = 0; n < strlen(text); n++) {
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(this->font_face, text[n]);
|
||||
|
||||
if (FT_Load_Glyph(this->font_face, glyph_index, FT_LOAD_DEFAULT))
|
||||
continue;
|
||||
|
||||
if (FT_Render_Glyph(slot, ft_render_mode_normal))
|
||||
continue;
|
||||
|
||||
if (text[n] == '\n') {
|
||||
x_offset = 0;
|
||||
y_offset += slot->bitmap.width * 2;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int y_position = 0; y_position < slot->bitmap.rows; y_position++) {
|
||||
for (int x_position = 0; x_position < slot->bitmap.width; x_position++) {
|
||||
char pixel = slot->bitmap.buffer[(y_position * slot->bitmap.width) + x_position];
|
||||
|
||||
int x = start_x + x_position + x_offset + slot->bitmap_left;
|
||||
int y = start_y + y_position + y_offset - slot->bitmap_top;
|
||||
|
||||
uint8_t red = (pixel * fg_color.red) / 255;
|
||||
uint8_t green = (pixel * fg_color.green) / 255;
|
||||
uint8_t blue = (pixel * fg_color.blue) / 255;
|
||||
|
||||
struct OrbisTTY_Color final_color = { red, green, blue };
|
||||
|
||||
if (x < 0 || y < 0 || x >= this->resolution.x || y >= this->resolution.y)
|
||||
continue;
|
||||
|
||||
if (pixel != 0x00)
|
||||
this->draw_pixel(x, y, final_color);
|
||||
}
|
||||
}
|
||||
|
||||
x_offset += slot->advance.x >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
void OrbisTTY_2D::draw_textf(int start_x, int start_y, struct OrbisTTY_Color bg_color, struct OrbisTTY_Color fg_color, char* fmt, ...) {
|
||||
char buffer[512];
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
this->draw_text(buffer, start_x, start_y, bg_color, fg_color);
|
||||
}
|
||||
|
||||
|
||||
// OrbisTTY Namespace
|
||||
|
||||
bool OrbisTTY::init(const char* font_path) {
|
||||
scene = new OrbisTTY_2D(4);
|
||||
if (!scene->init(0xC000000, 2))
|
||||
return false;
|
||||
|
||||
if (!set_font(font_path))
|
||||
return false;
|
||||
|
||||
for (int index = 0; index <= (floor(scene->resolution.y / 17) - 1); index++)
|
||||
lines.push_back("");
|
||||
|
||||
line_index = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OrbisTTY::set_font(const char* font_path) {
|
||||
if (!scene->use_font(font_path))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OrbisTTY::move_lines_up(void) {
|
||||
int total_lines = floor(scene->resolution.y / 17) - 1;
|
||||
|
||||
for (int index = 0; index <= total_lines - 1; index++)
|
||||
lines[index] = lines[index + 1];
|
||||
|
||||
lines[total_lines] = "";
|
||||
}
|
||||
|
||||
int OrbisTTY::get_y_offset(int line) {
|
||||
return (line * 17) + 17;
|
||||
}
|
||||
|
||||
void OrbisTTY::orbis_printf(const char* fmt, ...) {
|
||||
char buffer[512];
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
int total_lines = floor(scene->resolution.y / 17) - 1;
|
||||
|
||||
if (line_index <= total_lines - 1)
|
||||
lines[line_index++] = buffer;
|
||||
else {
|
||||
move_lines_up();
|
||||
lines[total_lines - 1] = buffer;
|
||||
}
|
||||
|
||||
scene->set_active_frame_buffer((frame_id + 1) % 2);
|
||||
scene->frame_buffer_fill(black);
|
||||
|
||||
for (int index = 0; index <= total_lines; index++)
|
||||
scene->draw_text((char*)lines[index].c_str(), 5, get_y_offset(index), black, white);
|
||||
|
||||
scene->submit_flip(frame_id);
|
||||
scene->frame_wait(frame_id);
|
||||
scene->frame_buffer_swap();
|
||||
|
||||
frame_id++;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#ifndef ORBISTTY_H_
|
||||
#define ORBISTTY_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <orbis/libkernel.h>
|
||||
#include <orbis/VideoOut.h>
|
||||
#include <orbis/Sysmodule.h>
|
||||
#include <proto-include.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct OrbisTTY_Color {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
};
|
||||
|
||||
struct OrbisTTY_Resolution {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
static struct OrbisTTY_Color white = { 255, 255, 255 };
|
||||
static struct OrbisTTY_Color black = { 0, 0, 0 };
|
||||
|
||||
class OrbisTTY_2D {
|
||||
private:
|
||||
FT_Library freetype_lib;
|
||||
FT_Face font_face;
|
||||
|
||||
int video;
|
||||
int depth;
|
||||
|
||||
off_t direct_mem_off;
|
||||
size_t direct_mem_alloc_size;
|
||||
|
||||
uintptr_t video_memory_sp;
|
||||
void* video_mem;
|
||||
|
||||
char** frame_buffers;
|
||||
OrbisKernelEqueue flip_queue;
|
||||
OrbisVideoOutBufferAttribute attr;
|
||||
|
||||
int frame_buffer_size;
|
||||
int frame_buffer_count;
|
||||
|
||||
int active_frame_buffer_index;
|
||||
|
||||
bool init_flip_queue (void);
|
||||
bool alloc_frame_buffers (int num);
|
||||
char* alloc_display_mem (size_t size);
|
||||
bool alloc_video_mem (size_t size, int alignment);
|
||||
void free_video_mem (void);
|
||||
void update_resolution (void);
|
||||
|
||||
public:
|
||||
struct OrbisTTY_Resolution resolution = { 0, 0 }; // Screen resolution
|
||||
|
||||
OrbisTTY_2D(int pixel_depth);
|
||||
~OrbisTTY_2D(void);
|
||||
|
||||
bool init (size_t mem_size, int num_frame_buffers);
|
||||
|
||||
void set_active_frame_buffer (int index);
|
||||
void submit_flip (int frame_id);
|
||||
|
||||
void frame_wait (int frame_id);
|
||||
void frame_buffer_swap (void);
|
||||
void frame_buffer_clear (void);
|
||||
void frame_buffer_fill (struct OrbisTTY_Color color);
|
||||
|
||||
void draw_pixel (int x, int y, struct OrbisTTY_Color color);
|
||||
void draw_rectangle (int x, int y, int width, int height, struct OrbisTTY_Color color);
|
||||
|
||||
bool use_font (const char* font_path);
|
||||
void draw_text (char* text, int start_x, int start_y, struct OrbisTTY_Color bg_color, struct OrbisTTY_Color fg_color);
|
||||
void draw_textf (int start_x, int start_y, struct OrbisTTY_Color bgColor, struct OrbisTTY_Color fg_color, char* fmt, ...);
|
||||
};
|
||||
|
||||
namespace OrbisTTY {
|
||||
static OrbisTTY_2D* scene;
|
||||
static std::vector<std::string> lines;
|
||||
static int line_index;
|
||||
static int frame_id;
|
||||
|
||||
bool init (const char* font_path);
|
||||
bool set_font (const char* font_path);
|
||||
void move_lines_up (void);
|
||||
int get_y_offset (int line);
|
||||
void orbis_printf (const char* fmt, ...);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
# Compiling the example
|
||||
|
||||
```bat
|
||||
C:\\Users\\maxim\\Downloads\\example> build.bat build orbistty-example .
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,82 @@
|
||||
@echo off
|
||||
|
||||
SETLOCAL EnableDelayedExpansion
|
||||
|
||||
Rem Package information
|
||||
set PKG_TITLE="OrbisTTY Example"
|
||||
set PKG_VERSION="1.00"
|
||||
set PKG_ASSETS="assets"
|
||||
set PKG_TITLE_ID="OTTY01010"
|
||||
set PKG_CONTENT_ID="IV0000-OTTY01010_00-ORBISTTY0EXAMPLE"
|
||||
|
||||
Rem Libraries to link in
|
||||
set libraries=-lc -lkernel -lc++ -lSceVideoOut -lSceFreeType -lSceSysmodule
|
||||
|
||||
Rem set extra_flags=
|
||||
|
||||
Rem Read the script arguments into local vars
|
||||
set intdir=%1
|
||||
set targetname=%~2
|
||||
set outputPath=%3
|
||||
|
||||
set outputElf=%intdir%\%targetname%.elf
|
||||
set outputOelf=%intdir%\%targetname%.oelf
|
||||
|
||||
@mkdir %intdir%
|
||||
|
||||
Rem Compile object files for all the source files
|
||||
for %%f in (*.c) do (
|
||||
clang --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" %extra_flags% -c -o %intdir%\%%~nf.o %%~nf.c
|
||||
)
|
||||
|
||||
for %%f in (*.cpp) do (
|
||||
clang++ --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" %extra_flags% -c -o %intdir%\%%~nf.o %%~nf.cpp
|
||||
)
|
||||
|
||||
Rem Get a list of object files for linking
|
||||
set obj_files=
|
||||
for %%f in (%1\\*.o) do set obj_files=!obj_files! .\%%f
|
||||
|
||||
Rem Link the input ELF
|
||||
ld.lld -m elf_x86_64 -pie --script "%OO_PS4_TOOLCHAIN%\link.x" --eh-frame-hdr -o "%outputElf%" "-L%OO_PS4_TOOLCHAIN%\\lib" %libraries% --verbose "%OO_PS4_TOOLCHAIN%\lib\crt1.o" %obj_files%
|
||||
|
||||
Rem Create the eboot
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\create-fself.exe -in "%outputElf%" --out "%outputOelf%" --eboot "eboot.bin" --paid 0x3800000000000011
|
||||
|
||||
Rem Create param.sfo
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_new sce_sys/param.sfo
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo APP_TYPE --type Integer --maxsize 4 --value 1
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo APP_VER --type Utf8 --maxsize 8 --value %PKG_VERSION%
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo ATTRIBUTE --type Integer --maxsize 4 --value 0
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo CATEGORY --type Utf8 --maxsize 4 --value "gd"
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo CONTENT_ID --type Utf8 --maxsize 48 --value %PKG_CONTENT_ID%
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo DOWNLOAD_DATA_SIZE --type Integer --maxsize 4 --value 0
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo SYSTEM_VER --type Integer --maxsize 4 --value 0
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo TITLE --type Utf8 --maxsize 128 --value %PKG_TITLE%
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo TITLE_ID --type Utf8 --maxsize 12 --value %PKG_TITLE_ID%
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe sfo_setentry sce_sys/param.sfo VERSION --type Utf8 --maxsize 8 --value %PKG_VERSION%
|
||||
|
||||
Rem Get a list of assets for packaging
|
||||
set module_files=
|
||||
for %%f in (sce_module\\*) do set module_files=!module_files! sce_module/%%~nxf
|
||||
|
||||
set asset_audio_files=
|
||||
for %%f in (assets\\audio\\*) do set asset_audio_files=!asset_audio_files! assets/audio/%%~nxf
|
||||
|
||||
set asset_fonts_files=
|
||||
for %%f in (assets\\fonts\\*) do set asset_fonts_files=!asset_fonts_files! assets/fonts/%%~nxf
|
||||
|
||||
set asset_images_files=
|
||||
for %%f in (assets\\images\\*) do set asset_images_files=!asset_images_files! assets/images/%%~nxf
|
||||
|
||||
set asset_misc_files=
|
||||
for %%f in (assets\\misc\\*) do set asset_misc_files=!asset_misc_files! assets/misc/%%~nxf
|
||||
|
||||
set asset_videos_files=
|
||||
for %%f in (assets\\videos\\*) do set asset_videos_files=!asset_videos_files! assets/videos/%%~nxf
|
||||
|
||||
Rem Create gp4
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\create-gp4.exe -out pkg.gp4 --content-id=%PKG_CONTENT_ID% --files "eboot.bin sce_sys/about/right.sprx sce_sys/param.sfo sce_sys/icon0.png %module_files% %asset_audio_files% %asset_fonts_files% %asset_images_files% %asset_misc_files% %asset_videos_files%"
|
||||
|
||||
Rem Create pkg
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\PkgTool.Core.exe pkg_build pkg.gp4 .
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include "OrbisTTY.h"
|
||||
|
||||
#define printf(...) OrbisTTY::orbis_printf(__VA_ARGS__)
|
||||
|
||||
int main() {
|
||||
if (!OrbisTTY::init("/app0/assets/fonts/Inconsolata-Regular.ttf"))
|
||||
return 1;
|
||||
|
||||
for (int index = 0; ; index++)
|
||||
printf("This PS4 application counts to infinitie! %d", index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 197 KiB |
Binary file not shown.
Reference in new issue
Block a user