Commit f263a65d authored by phcoder's avatar phcoder
Browse files

Support 16-bit pixels

parent 9e5d641a
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
#include "vm/machine.h" #include "vm/machine.h"
#include "vm/input.h" #include "vm/input.h"
#include <stdio.h>
#include <cstdarg> #include <cstdarg>
#include <cstring> #include <cstring>
#define LIBRETRO_LOG(x, ...) env.logger(retro_log_level::RETRO_LOG_INFO, x # __VA_ARGS__) #define LIBRETRO_LOG(x, ...) env.logger(retro_log_level::RETRO_LOG_INFO, x # __VA_ARGS__)
namespace r8 = retro8; namespace r8 = retro8;
using pixel_t = uint32_t;
constexpr int SAMPLE_RATE = 44100; constexpr int SAMPLE_RATE = 44100;
constexpr int SAMPLES_PER_FRAME = SAMPLE_RATE / 60; constexpr int SAMPLES_PER_FRAME = SAMPLE_RATE / 60;
...@@ -24,8 +24,66 @@ r8::Machine machine; ...@@ -24,8 +24,66 @@ r8::Machine machine;
r8::io::Loader loader; r8::io::Loader loader;
r8::input::InputManager input; r8::input::InputManager input;
r8::gfx::ColorTable colorTable; template <typename pixel_t>
pixel_t* screen; class Screen {
public:
~Screen() {
delete[] buffer;
}
void draw(const r8::gfx::color_byte_t *data, r8::gfx::palette_t *palette) {
auto pointer = buffer;
for (size_t i = 0; i < r8::gfx::BYTES_PER_SCREEN; ++i) {
const r8::gfx::color_byte_t* pixels = data + i;
const auto rc1 = colorTable.get(palette->get((pixels)->low()));
const auto rc2 = colorTable.get(palette->get((pixels)->high()));
*(pointer) = rc1;
*((pointer)+1) = rc2;
(pointer) += 2;
}
}
const pixel_t *getBuffer() {
return buffer;
}
protected:
Screen(): buffer(new pixel_t[r8::gfx::SCREEN_WIDTH * r8::gfx::SCREEN_HEIGHT]) {
}
protected:
r8::gfx::ColorTable colorTable;
private:
pixel_t *buffer;
};
struct Screen32 : Screen<uint32_t> {
public:
Screen32() {
colorTable.init(ColorMapper32());
}
private:
struct ColorMapper32
{
r8::gfx::ColorTable::pixel_t operator()(uint8_t r, uint8_t g, uint8_t b) const { return 0xff000000 | (r << 16) | (g << 8) | b; }
};
};
struct Screen16 : Screen<uint16_t> {
public:
Screen16() {
colorTable.init(ColorMapper16());
}
private:
struct ColorMapper16
{
r8::gfx::ColorTable::pixel_t operator()(uint8_t r, uint8_t g, uint8_t b) const { return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); }
};
};
Screen16 *screen16;
Screen32 *screen32;
int16_t* audioBuffer; int16_t* audioBuffer;
static void fallback_log(enum retro_log_level level, const char *fmt, ...) static void fallback_log(enum retro_log_level level, const char *fmt, ...)
...@@ -45,21 +103,38 @@ struct RetroArchEnv ...@@ -45,21 +103,38 @@ struct RetroArchEnv
retro_input_poll_t inputPoll; retro_input_poll_t inputPoll;
retro_input_state_t inputState; retro_input_state_t inputState;
retro_log_printf_t logger = fallback_log; retro_log_printf_t logger = fallback_log;
retro_environment_t retro_cb;
uint32_t frameCounter; uint32_t frameCounter;
uint16_t buttonState; uint16_t buttonState;
bool isRGB32;
}; };
RetroArchEnv env; RetroArchEnv env;
struct ColorMapper
{
r8::gfx::ColorTable::pixel_t operator()(uint8_t r, uint8_t g, uint8_t b) const { return 0xff000000 | (r << 16) | (g << 8) | b; }
};
//TODO //TODO
uint32_t Platform::getTicks() { return 0; } uint32_t Platform::getTicks() { return 0; }
static bool tryScreen32() {
retro_pixel_format pixelFormat = RETRO_PIXEL_FORMAT_XRGB8888;
if (!env.retro_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pixelFormat))
return false;
env.isRGB32 = true;
screen32 = new Screen32();
env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing XRGB8888 screen buffer of %d bytes\n", 4*r8::gfx::SCREEN_WIDTH*r8::gfx::SCREEN_HEIGHT);
return true;
}
static bool tryScreen16() {
retro_pixel_format pixelFormat = RETRO_PIXEL_FORMAT_RGB565;
if (!env.retro_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pixelFormat))
return false;
env.isRGB32 = false;
screen16 = new Screen16();
env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing RGB565 screen buffer of %d bytes\n", 2*r8::gfx::SCREEN_WIDTH*r8::gfx::SCREEN_HEIGHT);
return true;
}
extern "C" extern "C"
{ {
unsigned retro_api_version() unsigned retro_api_version()
...@@ -69,13 +144,9 @@ extern "C" ...@@ -69,13 +144,9 @@ extern "C"
void retro_init() void retro_init()
{ {
screen = new pixel_t[r8::gfx::SCREEN_WIDTH * r8::gfx::SCREEN_HEIGHT];
env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing screen buffer of %d bytes\n", sizeof(pixel_t)*r8::gfx::SCREEN_WIDTH*r8::gfx::SCREEN_HEIGHT);
audioBuffer = new int16_t[SAMPLE_RATE * 2]; audioBuffer = new int16_t[SAMPLE_RATE * 2];
env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing audio buffer of %d bytes\n", sizeof(int16_t) * SAMPLE_RATE * 2); env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing audio buffer of %d bytes\n", sizeof(int16_t) * SAMPLE_RATE * 2);
colorTable.init(ColorMapper());
machine.font().load(); machine.font().load();
machine.code().loadAPI(); machine.code().loadAPI();
input.setMachine(&machine); input.setMachine(&machine);
...@@ -83,7 +154,6 @@ extern "C" ...@@ -83,7 +154,6 @@ extern "C"
void retro_deinit() void retro_deinit()
{ {
delete[] screen;
delete[] audioBuffer; delete[] audioBuffer;
//TODO: release all structures bound to Lua etc //TODO: release all structures bound to Lua etc
} }
...@@ -114,8 +184,7 @@ extern "C" ...@@ -114,8 +184,7 @@ extern "C"
void retro_set_environment(retro_environment_t e) void retro_set_environment(retro_environment_t e)
{ {
retro_pixel_format pixelFormat = RETRO_PIXEL_FORMAT_XRGB8888; env.retro_cb = e;
e(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pixelFormat);
retro_log_callback logger; retro_log_callback logger;
if (e(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logger)) if (e(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logger))
...@@ -184,6 +253,13 @@ extern "C" ...@@ -184,6 +253,13 @@ extern "C"
env.frameCounter = 0; env.frameCounter = 0;
screen16 = NULL;
screen32 = NULL;
if (!tryScreen32() && !tryScreen16()) {
env.logger(retro_log_level::RETRO_LOG_ERROR, "Couldn't find compatible pixel format\n");
return false;
}
return true; return true;
} }
...@@ -193,6 +269,12 @@ extern "C" ...@@ -193,6 +269,12 @@ extern "C"
void retro_unload_game(void) void retro_unload_game(void)
{ {
/* TODO */ /* TODO */
if (screen16)
delete screen16;
if (screen32)
delete screen32;
screen16 = NULL;
screen32 = NULL;
} }
void retro_run() void retro_run()
...@@ -208,23 +290,18 @@ extern "C" ...@@ -208,23 +290,18 @@ extern "C"
auto* data = machine.memory().screenData(); auto* data = machine.memory().screenData();
auto* screenPalette = machine.memory().paletteAt(retro8::gfx::SCREEN_PALETTE_INDEX); auto* screenPalette = machine.memory().paletteAt(retro8::gfx::SCREEN_PALETTE_INDEX);
auto pointer = screen; if (env.isRGB32)
screen32->draw(data, screenPalette);
for (size_t i = 0; i < r8::gfx::BYTES_PER_SCREEN; ++i) else
{ screen16->draw(data, screenPalette);
const r8::gfx::color_byte_t* pixels = data + i;
const auto rc1 = colorTable.get(screenPalette->get((pixels)->low()));
const auto rc2 = colorTable.get(screenPalette->get((pixels)->high()));
*(pointer) = rc1;
*((pointer)+1) = rc2;
(pointer) += 2;
}
input.manageKeyRepeat(); input.manageKeyRepeat();
} }
env.video(screen, r8::gfx::SCREEN_WIDTH, r8::gfx::SCREEN_HEIGHT, r8::gfx::SCREEN_WIDTH * sizeof(pixel_t)); if (env.isRGB32)
env.video(screen32->getBuffer(), r8::gfx::SCREEN_WIDTH, r8::gfx::SCREEN_HEIGHT, r8::gfx::SCREEN_WIDTH * sizeof(uint32_t));
else
env.video(screen16->getBuffer(), r8::gfx::SCREEN_WIDTH, r8::gfx::SCREEN_HEIGHT, r8::gfx::SCREEN_WIDTH * sizeof(uint16_t));
++env.frameCounter; ++env.frameCounter;
machine.sound().renderSounds(audioBuffer, SAMPLES_PER_FRAME); machine.sound().renderSounds(audioBuffer, SAMPLES_PER_FRAME);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment