Implement more of binding-sandbox

This commit is contained in:
刘皓 2025-01-22 11:52:10 -05:00
parent 4c9e68e066
commit 739185594e
No known key found for this signature in database
GPG key ID: 7901753DB465B711
14 changed files with 480 additions and 15 deletions

View file

@ -25,6 +25,8 @@
#include "binding-sandbox/core.h"
#include "sandbox.h"
#define GFX_GUARD_EXC(exp) exp // TODO: implement
#define SANDBOX_DEF_ALLOC(rbtype) \
static VALUE alloc(VALUE _klass) { \
SANDBOX_COROUTINE(alloc, \
@ -78,6 +80,11 @@ namespace mkxp_sandbox {
// Given Ruby typed data `obj`, stores `ptr` into the private data field of `obj`.
void set_private_data(VALUE obj, void *ptr);
// Given Ruby typed data `obj`, retrieves the private data field of `obj`.
template <typename T> inline T *get_private_data(VALUE obj) {
return *(T **)(**sb() + *(wasm_ptr_t *)(**sb() + sb()->rtypeddata_data(obj)));
}
// Gets the length of a Ruby object.
SANDBOX_COROUTINE(get_length,
ID id;

View file

@ -33,6 +33,40 @@ namespace mkxp_sandbox {
SANDBOX_DEF_ALLOC(bitmap_type)
SANDBOX_DEF_DFREE(Bitmap)
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Bitmap *bitmap;
wasm_ptr_t filename;
wasm_size_t width;
wasm_size_t height;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) {
SANDBOX_AWAIT_AND_SET(filename, rb_string_value_cstr, (VALUE *)(**sb() + argv));
GFX_GUARD_EXC(bitmap = new Bitmap((const char *)(**sb() + filename));)
} else {
SANDBOX_AWAIT_AND_SET(width, rb_num2ulong, ((VALUE *)(**sb() + argv))[0]);
SANDBOX_AWAIT_AND_SET(height, rb_num2ulong, ((VALUE *)(**sb() + argv))[1]);
GFX_GUARD_EXC(bitmap = new Bitmap(width, height);)
}
set_private_data(self, bitmap);
//SANDBOX_AWAIT(init_props, bitmap, self); // TODO: implement
}
return self;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE clear(VALUE self) {
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->clear());
return self;
}
VALUE klass;
void operator()() {
@ -40,6 +74,8 @@ namespace mkxp_sandbox {
bitmap_type = sb()->rb_data_type("Bitmap", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Bitmap", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);
SANDBOX_AWAIT(rb_define_method, klass, "clear", (VALUE (*)(ANYARGS))clear, 0);
}
}
)

View file

@ -33,10 +33,44 @@ namespace mkxp_sandbox {
SANDBOX_COROUTINE(etc_binding_init,
SANDBOX_COROUTINE(color_binding_init,
SANDBOX_DEF_ALLOC_WITH_INIT(color_type, new Color())
SANDBOX_DEF_ALLOC(color_type)
SANDBOX_DEF_DFREE(Color)
SANDBOX_DEF_LOAD(Color)
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Color *color;
double red;
double green;
double blue;
double alpha;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
if (argc == 0) {
color = new Color();
} else {
SANDBOX_AWAIT_AND_SET(red, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]);
SANDBOX_AWAIT_AND_SET(green, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]);
SANDBOX_AWAIT_AND_SET(blue, rb_num2dbl, ((VALUE *)(**sb() + argv))[2]);
if (argc <= 3) {
color = new Color(red, green, blue);
} else {
SANDBOX_AWAIT_AND_SET(alpha, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]);
color = new Color(red, green, blue, alpha);
}
}
set_private_data(self, color);
}
return self;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
VALUE klass;
void operator()() {
@ -44,6 +78,7 @@ namespace mkxp_sandbox {
color_type = sb()->rb_data_type("Color", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Color", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);
SANDBOX_AWAIT(rb_define_singleton_method, klass, "_load", (VALUE (*)(ANYARGS))load, 1);
}
}

View file

@ -23,12 +23,28 @@
#define MKXPZ_SANDBOX_SPRITE_BINDING_H
#include "sandbox.h"
#include "binding-util.h"
#include "sprite.h"
namespace mkxp_sandbox {
static struct mkxp_sandbox::bindings::rb_data_type sprite_type;
SANDBOX_COROUTINE(sprite_binding_init,
SANDBOX_DEF_ALLOC(sprite_type)
SANDBOX_DEF_DFREE(Sprite)
static VALUE todo(int32_t argc, wasm_ptr_t argv, VALUE self) {
return self;
}
VALUE klass;
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT(rb_define_class, "Sprite", sb()->rb_cObject());
sprite_type = sb()->rb_data_type("Sprite", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Sprite", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "bitmap=", (VALUE (*)(ANYARGS))todo, -1);
}
}
)

View file

@ -23,12 +23,93 @@
#define MKXPZ_SANDBOX_WINDOW_BINDING_H
#include "sandbox.h"
#include "binding-util.h"
#include "window.h"
namespace mkxp_sandbox {
static struct mkxp_sandbox::bindings::rb_data_type window_type;
SANDBOX_COROUTINE(window_binding_init,
SANDBOX_DEF_ALLOC(window_type)
SANDBOX_DEF_DFREE(Window)
static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Window *window;
VALUE viewport_obj;
Viewport *viewport;
VALUE klass;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
viewport_obj = SANDBOX_NIL;
viewport = NULL;
if (argc > 0) {
viewport_obj = *(VALUE *)(**sb() + argv);
if (viewport_obj != SANDBOX_NIL) {
viewport = get_private_data<Viewport>(viewport_obj);
}
}
GFX_LOCK
window = new Window(viewport);
SANDBOX_AWAIT(rb_iv_set, self, "viewport", viewport_obj);
set_private_data(self, window);
window->initDynAttribs();
GFX_UNLOCK
}
return self;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE get_contents(VALUE self) {
return sb()->bind<struct rb_iv_get>()()(self, "contents");
}
static VALUE set_contents(VALUE self, VALUE value) {
SANDBOX_COROUTINE(coro,
VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) {
GFX_GUARD_EXC(get_private_data<Window>(self)->setContents(value == SANDBOX_NIL ? NULL : get_private_data<Bitmap>(value)));
SANDBOX_AWAIT(rb_iv_set, self, "contents", value);
}
return self;
}
)
return sb()->bind<struct coro>()()(self, value);
}
static VALUE todo(int32_t argc, wasm_ptr_t argv, VALUE self) {
return self;
}
VALUE klass;
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT(rb_define_class, "Window", sb()->rb_cObject());
window_type = sb()->rb_data_type("Window", NULL, dfree, NULL, NULL, 0, 0, 0);
SANDBOX_AWAIT_AND_SET(klass, rb_define_class, "Window", sb()->rb_cObject());
SANDBOX_AWAIT(rb_define_alloc_func, klass, alloc);
SANDBOX_AWAIT(rb_define_method, klass, "initialize", (VALUE (*)(ANYARGS))initialize, -1);
SANDBOX_AWAIT(rb_define_method, klass, "windowskin=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "contents", (VALUE (*)(ANYARGS))get_contents, 0);
SANDBOX_AWAIT(rb_define_method, klass, "contents=", (VALUE (*)(ANYARGS))set_contents, 1);
SANDBOX_AWAIT(rb_define_method, klass, "stretch=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "cursor_rect=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "active=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "pause=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "x=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "y=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "width=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "height=", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_method, klass, "z=", (VALUE (*)(ANYARGS))todo, -1);
}
}
)

View file

@ -162,6 +162,7 @@ if get_option('retro') == true
include_directories('.'),
include_directories('src'),
include_directories('src/display'),
include_directories('src/display/gl'),
include_directories('src/etc'),
include_directories('src/util'),
include_directories(retro_phase1),
@ -170,6 +171,11 @@ if get_option('retro') == true
],
sources: [
'src/core.cpp',
'src/sharedstate.cpp',
'src/display/bitmap.cpp',
'src/display/viewport.cpp',
'src/display/window.cpp',
'src/display/gl/scene.cpp',
'src/etc/etc.cpp',
'src/etc/table.cpp',
'binding-sandbox/binding-util.cpp',

View file

@ -60,6 +60,8 @@ ARG_HANDLERS = {
'unsigned long' => { primitive: :size },
'long long' => { primitive: :s64 },
'unsigned long long' => { primitive: :u64 },
'float' => { primitive: :f32 },
'double' => { primitive: :f64 },
'const char *' => {
keep: true,
buf_size: 'std::strlen(ARG) + 1',
@ -127,6 +129,8 @@ RET_HANDLERS = {
'unsigned long' => { primitive: :size },
'long long' => { primitive: :s64 },
'unsigned long long' => { primitive: :u64 },
'float' => { primitive: :f32 },
'double' => { primitive: :f64 },
'char *' => { primitive: :ptr },
'const char *' => { primitive: :ptr },
}

View file

@ -109,6 +109,8 @@ static bool init_sandbox() {
mkxp_retro::sandbox.reset();
SharedState::initInstance(NULL);
try {
mkxp_retro::sandbox.reset(new struct sandbox(game_path));
sb().run<struct main>();

View file

@ -21,6 +21,7 @@
#include "bitmap.h"
#ifndef MKXPZ_RETRO
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
@ -33,18 +34,25 @@
#include "gl-meta.h"
#include "quad.h"
#include "quadarray.h"
#endif // MKXPZ_RETRO
#include "transform.h"
#include "exception.h"
#include "sharedstate.h"
#include "glstate.h"
#ifndef MKXPZ_RETRO
#include "texpool.h"
#include "shader.h"
#include "filesystem.h"
#endif // MKXPZ_RETRO
#include "font.h"
#ifndef MKXPZ_RETRO
#include "eventthread.h"
#endif // MKXPZ_RETRO
#include "graphics.h"
#ifndef MKXPZ_RETRO
#include "system.h"
#endif // MKXPZ_RETRO
#include "util/util.h"
#include "debugwriter.h"
@ -163,7 +171,9 @@ struct BitmapPrivate
bool playing;
bool needsReset;
bool loop;
#ifndef MKXPZ_RETRO
std::vector<TEXFBO> frames;
#endif // MKXPZ_RETRO
float fps;
int lastFrame;
double startTime, playTime;
@ -173,6 +183,7 @@ struct BitmapPrivate
return floor(lastFrame + (playTime / (1 / fps)));
}
#ifndef MKXPZ_RETRO
unsigned int currentFrameI() {
if (!playing || needsReset) return lastFrame;
int i = currentFrameIRaw();
@ -183,6 +194,7 @@ struct BitmapPrivate
int i = currentFrameI();
return frames[i];
}
#endif // MKXPZ_RETRO
inline void play() {
playing = true;
@ -190,17 +202,23 @@ struct BitmapPrivate
}
inline void stop() {
#ifndef MKXPZ_RETRO
lastFrame = currentFrameI();
#endif // MKXPZ_RETRO
playing = false;
}
inline void seek(int frame) {
#ifndef MKXPZ_RETRO
lastFrame = clamp(frame, 0, (int)frames.size());
#endif // MKXPZ_RETRO
}
void updateTimer() {
if (needsReset) {
#ifndef MKXPZ_RETRO
lastFrame = currentFrameI();
#endif // MKXPZ_RETRO
playTime = 0;
startTime = shState->runTime();
needsReset = false;
@ -214,7 +232,9 @@ struct BitmapPrivate
sigslot::connection prepareCon;
#ifndef MKXPZ_RETRO
TEXFBO gl;
#endif // MKXPZ_RETRO
Font *font;
@ -228,6 +248,7 @@ struct BitmapPrivate
* getPixel calls. Is invalidated any time the bitmap
* is modified */
SDL_Surface *surface;
#ifndef MKXPZ_RETRO
SDL_PixelFormat *format;
/* The 'tainted' area describes which parts of the
@ -237,6 +258,7 @@ struct BitmapPrivate
* in the texture and blit to it directly, saving
* ourselves the expensive blending calculation */
pixman_region16_t tainted;
#endif // MKXPZ_RETRO
// For high-resolution texture replacement.
Bitmap *selfHires;
@ -251,7 +273,9 @@ struct BitmapPrivate
surface(0),
assumingRubyGC(false)
{
#ifndef MKXPZ_RETRO
format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
#endif // MKXPZ_RETRO
animation.width = 0;
animation.height = 0;
@ -265,20 +289,26 @@ struct BitmapPrivate
prepareCon = shState->prepareDraw.connect(&BitmapPrivate::prepare, this);
#ifndef MKXPZ_RETRO
font = &shState->defaultFont();
pixman_region_init(&tainted);
#endif // MKXPZ_RETRO
}
~BitmapPrivate()
{
prepareCon.disconnect();
#ifndef MKXPZ_RETRO
SDL_FreeFormat(format);
pixman_region_fini(&tainted);
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
TEXFBO &getGLTypes() {
return (animation.enabled) ? animation.currentFrame() : gl;
}
#endif // MKXPZ_RETRO
void prepare()
{
@ -289,22 +319,28 @@ struct BitmapPrivate
void allocSurface()
{
#ifndef MKXPZ_RETRO
surface = SDL_CreateRGBSurface(0, gl.width, gl.height, format->BitsPerPixel,
format->Rmask, format->Gmask,
format->Bmask, format->Amask);
#endif // MKXPZ_RETRO
}
void clearTaintedArea()
{
#ifndef MKXPZ_RETRO
pixman_region_fini(&tainted);
pixman_region_init(&tainted);
#endif // MKXPZ_RETRO
}
void addTaintedArea(const IntRect &rect)
{
#ifndef MKXPZ_RETRO
IntRect norm = normalizedRect(rect);
pixman_region_union_rect
(&tainted, &tainted, norm.x, norm.y, norm.w, norm.h);
#endif // MKXPZ_RETRO
}
void substractTaintedArea(const IntRect &rect)
@ -312,16 +348,21 @@ struct BitmapPrivate
if (!touchesTaintedArea(rect))
return;
#ifndef MKXPZ_RETRO
pixman_region16_t m_reg;
pixman_region_init_rect(&m_reg, rect.x, rect.y, rect.w, rect.h);
pixman_region_subtract(&tainted, &m_reg, &tainted);
pixman_region_fini(&m_reg);
#endif // MKXPZ_RETRO
}
bool touchesTaintedArea(const IntRect &rect)
{
#ifdef MKXPZ_RETRO
return false; // TODO: implement
#else
pixman_box16_t box;
box.x1 = rect.x;
box.y1 = rect.y;
@ -332,6 +373,7 @@ struct BitmapPrivate
pixman_region_contains_rectangle(&tainted, &box);
return result != PIXMAN_REGION_OUT;
#endif // MKXPZ_RETRO
}
void bindTexture(ShaderBase &shader, bool substituteLoresSize = true)
@ -346,11 +388,14 @@ struct BitmapPrivate
Debug() << "BUG: High-res BitmapPrivate bindTexture for animations not implemented";
}
#ifndef MKXPZ_RETRO
TEXFBO cframe = animation.currentFrame();
TEX::bind(cframe.tex);
shader.setTexSize(Vec2i(cframe.width, cframe.height));
#endif // MKXPZ_RETRO
return;
}
#ifndef MKXPZ_RETRO
TEX::bind(gl.tex);
if (selfLores && substituteLoresSize) {
shader.setTexSize(Vec2i(selfLores->width(), selfLores->height()));
@ -358,17 +403,22 @@ struct BitmapPrivate
else {
shader.setTexSize(Vec2i(gl.width, gl.height));
}
#endif // MKXPZ_RETRO
}
void bindFBO()
{
#ifndef MKXPZ_RETRO
FBO::bind((animation.enabled) ? animation.currentFrame().fbo : gl.fbo);
#endif // MKXPZ_RETRO
}
void pushSetViewport(ShaderBase &shader) const
{
#ifndef MKXPZ_RETRO
glState.viewport.pushSet(IntRect(0, 0, gl.width, gl.height));
shader.applyViewportProj();
#endif // MKXPZ_RETRO
}
void popViewport() const
@ -379,7 +429,9 @@ struct BitmapPrivate
void blitQuad(Quad &quad)
{
glState.blend.pushSet(false);
#ifndef MKXPZ_RETRO
quad.draw();
#endif // MKXPZ_RETRO
glState.blend.pop();
}
@ -388,6 +440,7 @@ struct BitmapPrivate
{
bindFBO();
#ifndef MKXPZ_RETRO
glState.scissorTest.pushSet(true);
glState.scissorBox.pushSet(normalizedRect(rect));
glState.clearColor.pushSet(color);
@ -397,8 +450,10 @@ struct BitmapPrivate
glState.clearColor.pop();
glState.scissorBox.pop();
glState.scissorTest.pop();
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
static void ensureFormat(SDL_Surface *&surf, Uint32 format)
{
if (surf->format->format == format)
@ -408,12 +463,15 @@ struct BitmapPrivate
SDL_FreeSurface(surf);
surf = surfConv;
}
#endif // MKXPZ_RETRO
void onModified(bool freeSurface = true)
{
if (surface && freeSurface)
{
#ifndef MKXPZ_RETRO
SDL_FreeSurface(surface);
#endif // MKXPZ_RETRO
surface = 0;
}
@ -421,6 +479,7 @@ struct BitmapPrivate
}
};
#ifndef MKXPZ_RETRO
struct BitmapOpenHandler : FileSystem::OpenHandler
{
// Non-GIF
@ -487,12 +546,14 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
return (surface || gif);
}
};
#endif // MKXPZ_RETRO
Bitmap::Bitmap(const char *filename)
{
std::string hiresPrefix = "Hires/";
std::string filenameStd = filename;
Bitmap *hiresBitmap = nullptr;
#ifndef MKXPZ_RETRO
// TODO: once C++20 is required, switch to filenameStd.starts_with(hiresPrefix)
if (shState->config().enableHires && filenameStd.compare(0, hiresPrefix.size(), hiresPrefix) != 0) {
// Look for a high-res version of the file.
@ -632,6 +693,7 @@ Bitmap::Bitmap(const char *filename)
SDL_Surface *imgSurf = handler.surface;
initFromSurface(imgSurf, hiresBitmap, false);
#endif // MKXPZ_RETRO
}
Bitmap::Bitmap(int width, int height, bool isHires)
@ -641,6 +703,7 @@ Bitmap::Bitmap(int width, int height, bool isHires)
Bitmap *hiresBitmap = nullptr;
#ifndef MKXPZ_RETRO
if (shState->config().enableHires && !isHires) {
// Create a high-res version as well.
double scalingFactor = shState->config().textureScalingFactor;
@ -658,19 +721,23 @@ Bitmap::Bitmap(int width, int height, bool isHires)
delete hiresBitmap;
throw e;
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
#ifndef MKXPZ_RETRO
p->gl = tex;
p->selfHires = hiresBitmap;
if (p->selfHires != nullptr) {
p->gl.selfHires = &p->selfHires->getGLTypes();
}
#endif // MKXPZ_RETRO
clear();
}
Bitmap::Bitmap(void *pixeldata, int width, int height)
{
#ifndef MKXPZ_RETRO
SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, p->format->BitsPerPixel,
p->format->Rmask,
p->format->Gmask,
@ -703,7 +770,9 @@ Bitmap::Bitmap(void *pixeldata, int width, int height)
throw e;
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
#ifndef MKXPZ_RETRO
p->gl = tex;
TEX::bind(p->gl.tex);
@ -711,6 +780,7 @@ Bitmap::Bitmap(void *pixeldata, int width, int height)
SDL_FreeSurface(surface);
}
#endif // MKXPZ_RETRO
p->addTaintedArea(rect());
}
@ -730,6 +800,7 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
// TODO: Clean me up
if (!other.isAnimated() || frame >= -1) {
#ifndef MKXPZ_RETRO
try {
p->gl = shState->texPool().request(other.width(), other.height());
} catch (const Exception &e) {
@ -748,6 +819,7 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
}
GLMeta::blitRectangle(rect(), rect());
GLMeta::blitEnd();
#endif // MKXPZ_RETRO
}
else {
p->animation.enabled = true;
@ -759,6 +831,7 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
p->animation.startTime = 0;
p->animation.loop = other.getLooping();
#ifndef MKXPZ_RETRO
for (TEXFBO &sourceframe : other.getFrames()) {
TEXFBO newframe;
try {
@ -775,6 +848,7 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
p->animation.frames.push_back(newframe);
}
#endif // MKXPZ_RETRO
}
p->addTaintedArea(rect());
@ -784,15 +858,18 @@ Bitmap::Bitmap(TEXFBO &other)
{
Bitmap *hiresBitmap = nullptr;
#ifndef MKXPZ_RETRO
if (other.selfHires != nullptr) {
// Create a high-res version as well.
hiresBitmap = new Bitmap(*other.selfHires);
hiresBitmap->setLores(this);
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
#ifndef MKXPZ_RETRO
try {
p->gl = shState->texPool().request(other.width, other.height);
} catch (const Exception &e) {
@ -811,6 +888,7 @@ Bitmap::Bitmap(TEXFBO &other)
GLMeta::blitRectangle(rect(), rect());
GLMeta::blitEnd();
}
#endif // MKXPZ_RETRO
p->addTaintedArea(rect());
}
@ -837,6 +915,7 @@ Bitmap::~Bitmap()
void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool forceMega)
{
#ifndef MKXPZ_RETRO
p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
if (imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize || forceMega)
@ -865,8 +944,10 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
throw e;
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
#ifndef MKXPZ_RETRO
p->gl = tex;
if (p->selfHires != nullptr) {
p->gl.selfHires = &p->selfHires->getGLTypes();
@ -877,6 +958,7 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
SDL_FreeSurface(imgSurf);
}
#endif // MKXPZ_RETRO
p->addTaintedArea(rect());
}
@ -885,6 +967,9 @@ int Bitmap::width() const
{
guardDisposed();
#ifdef MKXPZ_RETRO
return 32; // TODO: implement
#else
if (p->megaSurface) {
return p->megaSurface->w;
}
@ -894,12 +979,16 @@ int Bitmap::width() const
}
return p->gl.width;
#endif // MKXPZ_RETRO
}
int Bitmap::height() const
{
guardDisposed();
#ifdef MKXPZ_RETRO
return 32; // TODO: implement
#else
if (p->megaSurface)
return p->megaSurface->h;
@ -907,6 +996,7 @@ int Bitmap::height() const
return p->animation.height;
return p->gl.height;
#endif // MKXPZ_RETRO
}
bool Bitmap::hasHires() const{
@ -1085,6 +1175,7 @@ void Bitmap::stretchBlt(IntRect destRect,
SDL_Surface *srcSurf = source.megaSurface();
SDL_Surface *blitTemp = 0;
bool touchesTaintedArea = p->touchesTaintedArea(destRect);
#ifndef MKXPZ_RETRO
bool unpack_subimage = srcSurf && gl.unpack_subimage;
const bool scaleIsOne = sourceRect.w == destRect.w && sourceRect.h == destRect.h;
@ -1317,6 +1408,7 @@ void Bitmap::stretchBlt(IntRect destRect,
if (blitTemp)
SDL_FreeSurface(blitTemp);
#endif // MKXPZ_RETRO
p->addTaintedArea(destRect);
p->onModified();
@ -1385,6 +1477,7 @@ void Bitmap::gradientFillRect(const IntRect &rect,
p->selfHires->gradientFillRect(IntRect(destX, destY, destWidth, destHeight), color1, color2, vertical);
}
#ifndef MKXPZ_RETRO
SimpleColorShader &shader = shState->shaders().simpleColor;
shader.bind();
shader.setTranslation(Vec2i());
@ -1414,6 +1507,7 @@ void Bitmap::gradientFillRect(const IntRect &rect,
p->blitQuad(quad);
p->popViewport();
#endif // MKXPZ_RETRO
p->addTaintedArea(rect);
@ -1460,6 +1554,7 @@ void Bitmap::blur()
// TODO: Is there some kind of blur radius that we need to handle for high-res mode?
#ifndef MKXPZ_RETRO
Quad &quad = shState->gpQuad();
FloatRect rect(0, 0, width(), height());
quad.setTexPosRect(rect, rect);
@ -1495,6 +1590,7 @@ void Bitmap::blur()
glState.blend.pop();
shState->texPool().release(auxTex);
#endif // MKXPZ_RETRO
p->onModified();
}
@ -1521,6 +1617,7 @@ void Bitmap::radialBlur(int angle, int divisions)
float opacity = 1.0f / divisions;
float baseAngle = -((float) angle / 2);
#ifndef MKXPZ_RETRO
ColorQuadArray qArray;
qArray.resize(5);
@ -1597,6 +1694,7 @@ void Bitmap::radialBlur(int angle, int divisions)
shState->texPool().release(p->gl);
p->gl = newTex;
#endif // MKXPZ_RETRO
p->onModified();
}
@ -1613,17 +1711,20 @@ void Bitmap::clear()
p->bindFBO();
#ifndef MKXPZ_RETRO
glState.clearColor.pushSet(Vec4());
FBO::clear();
glState.clearColor.pop();
#endif // MKXPZ_RETRO
p->clearTaintedArea();
p->onModified();
}
#ifndef MKXPZ_RETRO
static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int y)
{
size_t offset = x*form->BytesPerPixel + y*surf->pitch;
@ -1631,6 +1732,7 @@ static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int
return *((uint32_t*) bytes);
}
#endif // MKXPZ_RETRO
Color Bitmap::getPixel(int x, int y) const
{
@ -1689,6 +1791,7 @@ Color Bitmap::getPixel(int x, int y) const
{
p->allocSurface();
#ifndef MKXPZ_RETRO
FBO::bind(p->gl.fbo);
glState.viewport.pushSet(IntRect(0, 0, width(), height()));
@ -1696,14 +1799,19 @@ Color Bitmap::getPixel(int x, int y) const
gl.ReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, p->surface->pixels);
glState.viewport.pop();
#endif // MKXPZ_RETRO
}
#ifdef MKXPZ_RETRO
return Color(); // TODO: implement
#else
uint32_t pixel = getPixelAt(p->surface, p->format, x, y);
return Color((pixel >> p->format->Rshift) & 0xFF,
(pixel >> p->format->Gshift) & 0xFF,
(pixel >> p->format->Bshift) & 0xFF,
(pixel >> p->format->Ashift) & 0xFF);
#endif // MKXPZ_RETRO
}
void Bitmap::setPixel(int x, int y, const Color &color)
@ -1739,19 +1847,23 @@ void Bitmap::setPixel(int x, int y, const Color &color)
(uint8_t) clamp<double>(color.alpha, 0, 255)
};
#ifndef MKXPZ_RETRO
TEX::bind(p->gl.tex);
TEX::uploadSubImage(x, y, 1, 1, &pixel, GL_RGBA);
#endif // MKXPZ_RETRO
p->addTaintedArea(IntRect(x, y, 1, 1));
/* Setting just a single pixel is no reason to throw away the
* whole cached surface; we can just apply the same change */
#ifndef MKXPZ_RETRO
if (p->surface)
{
uint32_t &surfPixel = getPixelAt(p->surface, p->format, x, y);
surfPixel = SDL_MapRGBA(p->format, pixel[0], pixel[1], pixel[2], pixel[3]);
}
#endif // MKXPZ_RETRO
p->onModified(false);
}
@ -1766,6 +1878,7 @@ bool Bitmap::getRaw(void *output, int output_size)
Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
}
#ifndef MKXPZ_RETRO
if (!p->animation.enabled && (p->surface || p->megaSurface)) {
void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels;
memcpy(output, src, output_size);
@ -1774,6 +1887,7 @@ bool Bitmap::getRaw(void *output, int output_size)
FBO::bind(getGLTypes().fbo);
gl.ReadPixels(0,0,width(),height(),GL_RGBA,GL_UNSIGNED_BYTE,output);
}
#endif // MKXPZ_RETRO
return true;
}
@ -1794,8 +1908,10 @@ void Bitmap::replaceRaw(void *pixel_data, int size)
if (size != w*h*4)
throw Exception(Exception::MKXPError, "Replacement bitmap data is not large enough (given %i bytes, need %i)", size, requiredsize);
#ifndef MKXPZ_RETRO
TEX::bind(getGLTypes().tex);
TEX::uploadImage(w, h, pixel_data, GL_RGBA);
#endif // MKXPZ_RETRO
taintArea(IntRect(0,0,w,h));
p->onModified();
@ -1815,12 +1931,14 @@ void Bitmap::saveToFile(const char *filename)
surf = (p->surface) ? p->surface : p->megaSurface;
}
else {
#ifndef MKXPZ_RETRO
surf = SDL_CreateRGBSurface(0, width(), height(),p->format->BitsPerPixel, p->format->Rmask,p->format->Gmask,p->format->Bmask,p->format->Amask);
if (!surf)
throw Exception(Exception::SDLError, "Failed to prepare bitmap for saving: %s", SDL_GetError());
getRaw(surf->pixels, surf->w * surf->h * 4);
#endif // MKXPZ_RETRO
}
// Try and determine the intended image format from the filename extension
@ -1841,6 +1959,7 @@ void Bitmap::saveToFile(const char *filename)
}
}
#ifndef MKXPZ_RETRO
std::string fn_normalized = shState->fileSystem().normalize(filename, 1, 1);
int rc;
switch (filetype) {
@ -1859,6 +1978,7 @@ void Bitmap::saveToFile(const char *filename)
SDL_FreeSurface(surf);
if (rc) throw Exception(Exception::SDLError, "%s", SDL_GetError());
#endif // MKXPZ_RETRO
}
void Bitmap::hueChange(int hue)
@ -1876,6 +1996,7 @@ void Bitmap::hueChange(int hue)
if ((hue % 360) == 0)
return;
#ifndef MKXPZ_RETRO
TEXFBO newTex = shState->texPool().request(width(), height());
FloatRect texRect(rect());
@ -1901,6 +2022,7 @@ void Bitmap::hueChange(int hue)
shState->texPool().release(p->gl);
p->gl = newTex;
#endif // MKXPZ_RETRO
p->onModified();
}
@ -1927,6 +2049,7 @@ static std::string fixupString(const char *str)
return s;
}
#ifndef MKXPZ_RETRO
static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_Color &c)
{
SDL_Surface *out = SDL_CreateRGBSurface
@ -2013,6 +2136,7 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C
SDL_FreeSurface(in);
in = out;
}
#endif // MKXPZ_RETRO
void Bitmap::drawText(const IntRect &rect, const char *str, int align)
{
@ -2021,6 +2145,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
GUARD_MEGA;
GUARD_ANIMATED;
#ifndef MKXPZ_RETRO
if (hasHires()) {
Font &loresFont = getFont();
Font &hiresFont = p->selfHires->getFont();
@ -2042,6 +2167,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
return;
}
#endif // MKXPZ_RETRO
std::string fixed = fixupString(str);
str = fixed.c_str();
@ -2052,6 +2178,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
if (str[0] == ' ' && str[1] == '\0')
return;
#ifndef MKXPZ_RETRO
TTF_Font *font = p->font->getSdlFont();
const Color &fontColor = p->font->getColor();
const Color &outColor = p->font->getOutColor();
@ -2144,6 +2271,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
Bitmap txtBitmap(txtSurf, nullptr, true);
bool smooth = squeeze != 1.0f;
stretchBlt(destRect, txtBitmap, sourceRect, fontColor.alpha, smooth);
#endif // MKXPZ_RETRO
}
/* http://www.lemoda.net/c/utf8-to-ucs2/index.html */
@ -2200,6 +2328,9 @@ IntRect Bitmap::textSize(const char *str)
// TODO: High-res Bitmap textSize not implemented, but I think it's the same as low-res?
// Need to double-check this.
#ifdef MKXPZ_RETRO
return IntRect(); // TODO: implement
#else
TTF_Font *font = p->font->getSdlFont();
std::string fixed = fixupString(str);
@ -2218,6 +2349,7 @@ IntRect Bitmap::textSize(const char *str)
TTF_GlyphMetrics(font, ucs2, 0, 0, 0, 0, &w);
return IntRect(0, 0, w, h);
#endif // MKXPZ_RETRO
}
DEF_ATTR_RD_SIMPLE(Bitmap, Font, Font&, *p->font)
@ -2225,27 +2357,33 @@ DEF_ATTR_RD_SIMPLE(Bitmap, Font, Font&, *p->font)
void Bitmap::setFont(Font &value)
{
// High-res support handled in drawText, not here.
#ifndef MKXPZ_RETRO
*p->font = value;
#endif // MKXPZ_RETRO
}
void Bitmap::setInitFont(Font *value)
{
if (hasHires()) {
Font *hiresFont = p->selfHires->p->font;
#ifndef MKXPZ_RETRO
if (hiresFont && hiresFont != &shState->defaultFont())
{
// Disable the illegal font size check when creating a high-res font.
hiresFont->setSize(hiresFont->getSize() * p->selfHires->width() / width(), false);
}
#endif // MKXPZ_RETRO
}
p->font = value;
}
#ifndef MKXPZ_RETRO
TEXFBO &Bitmap::getGLTypes() const
{
return p->getGLTypes();
}
#endif // MKXPZ_RETRO
SDL_Surface *Bitmap::surface() const
{
@ -2336,7 +2474,11 @@ bool Bitmap::isPlaying() const
if (p->animation.loop)
return true;
#ifdef MKXPZ_RETRO
return false; // TODO: implement
#else
return p->animation.currentFrameIRaw() < p->animation.frames.size();
#endif // MKXPZ_RETRO
}
void Bitmap::gotoAndStop(int frame)
@ -2376,9 +2518,14 @@ int Bitmap::numFrames() const
}
if (!p->animation.enabled) return 1;
#ifdef MKXPZ_RETRO
return 0; // TODO: implement
#else
return (int)p->animation.frames.size();
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
int Bitmap::currentFrameI() const
{
guardDisposed();
@ -2390,6 +2537,7 @@ int Bitmap::currentFrameI() const
if (!p->animation.enabled) return 0;
return p->animation.currentFrameI();
}
#endif // MKXPZ_RETRO
int Bitmap::addFrame(Bitmap &source, int position)
{
@ -2410,6 +2558,7 @@ int Bitmap::addFrame(Bitmap &source, int position)
throw Exception(Exception::MKXPError, "Animations with varying dimensions are not supported (%ix%i vs %ix%i)",
source.width(), source.height(), width(), height());
#ifndef MKXPZ_RETRO
TEXFBO newframe = shState->texPool().request(source.width(), source.height());
// Convert the bitmap into an animated bitmap if it isn't already one
@ -2444,14 +2593,23 @@ int Bitmap::addFrame(Bitmap &source, int position)
GLMeta::blitEnd();
}
#endif // MKXPZ_RETRO
int ret;
if (position < 0) {
#ifndef MKXPZ_RETRO
p->animation.frames.push_back(newframe);
#endif // MKXPZ_RETRO
#ifdef MKXPZ_RETRO
ret = 0; // TODO: implement
#else
ret = (int)p->animation.frames.size();
#endif // MKXPZ_RETRO
}
else {
#ifndef MKXPZ_RETRO
p->animation.frames.insert(p->animation.frames.begin() + clamp(position, 0, (int)p->animation.frames.size()), newframe);
#endif // MKXPZ_RETRO
ret = position;
}
@ -2467,6 +2625,7 @@ void Bitmap::removeFrame(int position) {
Debug() << "BUG: High-res Bitmap removeFrame not implemented";
}
#ifndef MKXPZ_RETRO
int pos = (position < 0) ? (int)p->animation.frames.size() - 1 : clamp(position, 0, (int)(p->animation.frames.size() - 1));
shState->texPool().release(p->animation.frames[pos]);
p->animation.frames.erase(p->animation.frames.begin() + pos);
@ -2486,6 +2645,7 @@ void Bitmap::removeFrame(int position) {
FBO::bind(p->gl.fbo);
taintArea(rect());
}
#endif // MKXPZ_RETRO
}
void Bitmap::nextFrame()
@ -2499,11 +2659,13 @@ void Bitmap::nextFrame()
}
stop();
#ifndef MKXPZ_RETRO
if ((uint32_t)p->animation.lastFrame >= p->animation.frames.size() - 1) {
if (!p->animation.loop) return;
p->animation.lastFrame = 0;
return;
}
#endif // MKXPZ_RETRO
p->animation.lastFrame++;
}
@ -2524,7 +2686,9 @@ void Bitmap::previousFrame()
p->animation.lastFrame = 0;
return;
}
#ifndef MKXPZ_RETRO
p->animation.lastFrame = (int)p->animation.frames.size() - 1;
#endif // MKXPZ_RETRO
return;
}
@ -2547,6 +2711,7 @@ void Bitmap::setAnimationFPS(float FPS)
if (restart) p->animation.play();
}
#ifndef MKXPZ_RETRO
std::vector<TEXFBO> &Bitmap::getFrames() const
{
if (hasHires()) {
@ -2555,6 +2720,7 @@ std::vector<TEXFBO> &Bitmap::getFrames() const
return p->animation.frames;
}
#endif // MKXPZ_RETRO
float Bitmap::getAnimationFPS() const
{
@ -2617,9 +2783,11 @@ void Bitmap::taintArea(const IntRect &rect)
p->addTaintedArea(rect);
}
#ifndef MKXPZ_RETRO
int Bitmap::maxSize(){
return glState.caps.maxTexSize;
}
#endif // MKXPZ_RETRO
void Bitmap::assumeRubyGC()
{
@ -2632,6 +2800,7 @@ void Bitmap::releaseResources()
delete p->selfHires;
}
#ifndef MKXPZ_RETRO
if (p->megaSurface)
SDL_FreeSurface(p->megaSurface);
else if (p->animation.enabled) {
@ -2642,6 +2811,7 @@ void Bitmap::releaseResources()
}
else
shState->texPool().release(p->gl);
#endif // MKXPZ_RETRO
delete p;
}

View file

@ -111,7 +111,12 @@ private:
GraphicsPrivate *p;
};
#define GFX_LOCK shState->graphics().lock()
#define GFX_UNLOCK shState->graphics().unlock()
#ifdef MKXPZ_RETRO
# define GFX_LOCK // TODO
# define GFX_UNLOCK // TODO
#else
# define GFX_LOCK shState->graphics().lock()
# define GFX_UNLOCK shState->graphics().unlock()
#endif // MKXPZ_RETRO
#endif // GRAPHICS_H

View file

@ -24,12 +24,12 @@
#include "sharedstate.h"
#include "etc.h"
#include "util.h"
#ifndef MKXPZ_RETRO
#include "quad.h"
#include "glstate.h"
#endif // MKXPZ_RETRO
#include "graphics.h"
#include <SDL_rect.h>
#include "sigslot/signal.hpp"
struct ViewportPrivate
@ -80,14 +80,10 @@ struct ViewportPrivate
void recomputeOnScreen()
{
SDL_Rect r1 = { screenRect.x, screenRect.y,
screenRect.w, screenRect.h };
SDL_Rect r2 = { rect->x, rect->y,
rect->width, rect->height };
SDL_Rect result;
isOnScreen = SDL_IntersectRect(&r1, &r2, &result);
isOnScreen = screenRect.x < rect->x + rect->width
&& rect->x < screenRect.x + screenRect.w
&& screenRect.y < rect->y + rect->height
&& rect->y < screenRect.y + screenRect.h;
}
bool needsEffectRender(bool flashing)
@ -117,8 +113,12 @@ Viewport::Viewport()
: SceneElement(*shState->screen()),
sceneLink(this)
{
#ifdef MKXPZ_RETRO
initViewport(0, 0, 640, 480); // TODO: use the actual viewport size
#else
const Graphics &graphics = shState->graphics();
initViewport(0, 0, graphics.width(), graphics.height());
#endif // MKXPZ_RETRO
}
void Viewport::initViewport(int x, int y, int width, int height)
@ -193,9 +193,11 @@ void Viewport::composite()
if (elements.getSize() == 0 && !renderEffect)
return;
#ifndef MKXPZ_RETRO
/* Setup scissor */
glState.scissorTest.pushSet(true);
glState.scissorBox.pushSet(p->rect->toIntRect());
#endif // MKXPZ_RETRO
Scene::composite();
@ -205,8 +207,10 @@ void Viewport::composite()
scene->requestViewportRender
(p->color->norm, flashColor, p->tone->norm);
#ifndef MKXPZ_RETRO
glState.scissorBox.pop();
glState.scissorTest.pop();
#endif // MKXPZ_RETRO
}
/* SceneElement */

View file

@ -26,6 +26,7 @@
#include "bitmap.h"
#include "etc.h"
#include "etc-internal.h"
#ifndef MKXPZ_RETRO
#include "tilequad.h"
#include "gl-util.h"
@ -33,6 +34,7 @@
#include "quadarray.h"
#include "texpool.h"
#include "glstate.h"
#endif // MKXPZ_RETRO
#include "sigslot/signal.hpp"
@ -118,6 +120,7 @@ static const uint8_t pauseAniAlpha[] =
static elementsN(pauseAniAlpha);
#ifndef MKXPZ_RETRO
/* Points to an array of quads which it doesn't own.
* Useful for setting alpha of quads stored inside
* bigger arrays */
@ -136,6 +139,7 @@ struct QuadChunk
vert[i].color.w = value;
}
};
#endif // MKXPZ_RETRO
/* Vocabulary:
*
@ -196,6 +200,7 @@ struct WindowPrivate
bool opacityDirty;
bool baseTexDirty;
#ifndef MKXPZ_RETRO
ColorQuadArray baseQuadArray;
/* Used when opacity < 255 */
@ -205,6 +210,7 @@ struct WindowPrivate
QuadChunk backgroundVert;
Quad baseTexQuad;
#endif // MKXPZ_RETRO
struct WindowControls : public ViewportElement
{
@ -233,6 +239,7 @@ struct WindowPrivate
WindowControls controlsElement;
#ifndef MKXPZ_RETRO
ColorQuadArray controlsQuadArray;
int controlsQuadCount;
@ -240,6 +247,7 @@ struct WindowPrivate
QuadChunk pauseAniVert;
QuadChunk cursorVert;
#endif // MKXPZ_RETRO
uint8_t cursorAniAlphaIdx;
uint8_t pauseAniAlphaIdx;
@ -272,9 +280,11 @@ struct WindowPrivate
{
refreshCursorRectCon();
#ifndef MKXPZ_RETRO
controlsQuadArray.resize(14);
cursorVert.count = 9;
pauseAniVert.count = 1;
#endif // MKXPZ_RETRO
prepareCon = shState->prepareDraw.connect
(&WindowPrivate::prepare, this);
@ -282,7 +292,9 @@ struct WindowPrivate
~WindowPrivate()
{
#ifndef MKXPZ_RETRO
shState->texPool().release(baseTex);
#endif // MKXPZ_RETRO
cursorRectCon.disconnect();
prepareCon.disconnect();
@ -333,6 +345,7 @@ struct WindowPrivate
cornerRects.bl = IntRect(0, h-16, 16, 16);
cornerRects.br = IntRect(w-16, h-16, 16, 16);
#ifndef MKXPZ_RETRO
/* Required quad count */
int count = 0;
@ -389,6 +402,7 @@ struct WindowPrivate
FloatRect texRect = FloatRect(0, 0, size.x, size.y);
baseTexQuad.setTexPosRect(texRect, texRect);
#endif // MKXPZ_RETRO
opacityDirty = true;
baseTexDirty = true;
@ -396,10 +410,12 @@ struct WindowPrivate
void updateBaseAlpha()
{
#ifndef MKXPZ_RETRO
/* This is always applied unconditionally */
backgroundVert.setAlpha(backOpacity.norm);
baseTexQuad.setColor(Vec4(1, 1, 1, opacity.norm));
#endif // MKXPZ_RETRO
baseTexDirty = true;
}
@ -407,6 +423,7 @@ struct WindowPrivate
void ensureBaseTexReady()
{
/* Make sure texture is big enough */
#ifndef MKXPZ_RETRO
int newW = baseTex.width;
int newH = baseTex.height;
bool resizeNeeded = false;
@ -427,12 +444,14 @@ struct WindowPrivate
shState->texPool().release(baseTex);
baseTex = shState->texPool().request(newW, newH);
#endif // MKXPZ_RETRO
baseTexDirty = true;
}
void redrawBaseTex()
{
#ifndef MKXPZ_RETRO
/* Discard old buffer */
TEX::bind(baseTex.tex);
TEX::allocEmpty(baseTex.width, baseTex.height);
@ -471,10 +490,12 @@ struct WindowPrivate
glState.blendMode.pop();
glState.viewport.pop();
TEX::setSmooth(false);
#endif // MKXPZ_RETRO
}
void buildControlsVert()
{
#ifndef MKXPZ_RETRO
int i = 0;
Vertex *vert = controlsQuadArray.vertices.data();
@ -524,6 +545,7 @@ struct WindowPrivate
controlsQuadArray.commit();
controlsQuadCount = i;
#endif // MKXPZ_RETRO
}
void prepare()
@ -547,6 +569,7 @@ struct WindowPrivate
updateBaseQuadArray = true;
}
#ifndef MKXPZ_RETRO
if (updateBaseQuadArray)
baseQuadArray.commit();
@ -564,6 +587,7 @@ struct WindowPrivate
baseTexDirty = false;
}
}
#endif // MKXPZ_RETRO
}
void drawBase()
@ -574,6 +598,7 @@ struct WindowPrivate
if (size == Vec2i(0, 0))
return;
#ifndef MKXPZ_RETRO
SimpleAlphaShader &shader = shState->shaders().simpleAlpha;
shader.bind();
shader.applyViewportProj();
@ -595,6 +620,7 @@ struct WindowPrivate
TEX::setSmooth(false);
}
#endif // MKXPZ_RETRO
}
void drawControls()
@ -618,6 +644,7 @@ struct WindowPrivate
const IntRect windowRect(efPos, size);
const IntRect contentsRect(efPos + Vec2i(16), size - Vec2i(32));
#ifndef MKXPZ_RETRO
glState.scissorTest.pushSet(true);
glState.scissorBox.push();
glState.scissorBox.setIntersect(windowRect);
@ -652,10 +679,12 @@ struct WindowPrivate
glState.scissorBox.pop();
glState.scissorTest.pop();
#endif // MKXPZ_RETRO
}
void updateControls()
{
#ifndef MKXPZ_RETRO
bool updateArray = false;
if (active && cursorVert.vert)
@ -680,6 +709,7 @@ struct WindowPrivate
if (updateArray)
controlsQuadArray.commit();
#endif // MKXPZ_RETRO
}
void stepAnimations()
@ -746,7 +776,9 @@ void Window::setWindowskin(Bitmap *value)
return;
}
#ifndef MKXPZ_RETRO
value->ensureNonMega();
#endif // MKXPZ_RETRO
p->windowskinDispCon = value->wasDisposed.connect(&WindowPrivate::windowskinDisposal, p);
}
@ -771,9 +803,11 @@ void Window::setContents(Bitmap *value)
p->contentsDispCon = value->wasDisposed.connect(&WindowPrivate::contentsDisposal, p);
#ifndef MKXPZ_RETRO
value->ensureNonMega();
p->contentsQuad.setTexPosRect(value->rect(), value->rect());
#endif // MKXPZ_RETRO
}
void Window::setStretch(bool value)
@ -885,7 +919,9 @@ void Window::setContentsOpacity(int value)
return;
p->contentsOpacity = value;
#ifndef MKXPZ_RETRO
p->contentsQuad.setColor(Vec4(1, 1, 1, p->contentsOpacity.norm));
#endif // MKXPZ_RETRO
}
void Window::initDynAttribs()

View file

@ -21,22 +21,33 @@
#include "sharedstate.h"
#include "scene.h"
#include "util.h"
#ifndef MKXPZ_RETRO
#include "filesystem.h"
#endif // MKXPZ_RETRO
#include "graphics.h"
#ifndef MKXPZ_RETRO
#include "input.h"
#include "audio.h"
#endif // MKXPZ_RETRO
#include "glstate.h"
#ifndef MKXPZ_RETRO
#include "shader.h"
#include "texpool.h"
#endif // MKXPZ_RETRO
#include "font.h"
#ifndef MKXPZ_RETRO
#include "eventthread.h"
#include "gl-util.h"
#include "global-ibo.h"
#include "quad.h"
#endif // MKXPZ_RETRO
#include "binding.h"
#include "exception.h"
#ifndef MKXPZ_RETRO
#include "sharedmidistate.h"
#endif // MKXPZ_RETRO
#include <unistd.h>
#include <stdio.h>
@ -63,9 +74,12 @@ static const char *gameArchExt()
struct SharedStatePrivate
{
void *bindingData;
#ifndef MKXPZ_RETRO
SDL_Window *sdlWindow;
#endif // MKXPZ_RETRO
Scene *screen;
#ifndef MKXPZ_RETRO
FileSystem fileSystem;
EventThread &eThread;
@ -88,14 +102,17 @@ struct SharedStatePrivate
Font *defaultFont;
TEX::ID globalTex;
#endif // MKXPZ_RETRO
int globalTexW, globalTexH;
bool globalTexDirty;
#ifndef MKXPZ_RETRO
TEXFBO gpTexFBO;
TEXFBO atlasTex;
Quad gpQuad;
#endif // MKXPZ_RETRO
unsigned int stampCounter;
@ -103,6 +120,7 @@ struct SharedStatePrivate
SharedStatePrivate(RGSSThreadData *threadData)
: bindingData(0),
#ifndef MKXPZ_RETRO
sdlWindow(threadData->window),
fileSystem(threadData->argv0, threadData->config.allowSymlinks),
eThread(*threadData->ethread),
@ -114,6 +132,7 @@ struct SharedStatePrivate
audio(*threadData),
_glState(threadData->config),
fontState(threadData->config),
#endif // MKXPZ_RETRO
stampCounter(0)
{}
@ -122,6 +141,7 @@ struct SharedStatePrivate
startupTime = std::chrono::steady_clock::now();
#ifndef MKXPZ_RETRO
/* Shaders have been compiled in ShaderSet's constructor */
if (gl.ReleaseShaderCompiler)
gl.ReleaseShaderCompiler();
@ -168,13 +188,16 @@ struct SharedStatePrivate
* no need to do it on startup */
if (rgssVer <= 2)
midiState.initIfNeeded(threadData->config);
#endif // MKXPZ_RETRO
}
~SharedStatePrivate()
{
#ifndef MKXPZ_RETRO
TEX::del(globalTex);
TEXFBO::fini(gpTexFBO);
TEXFBO::fini(atlasTex);
#endif // MKXPZ_RETRO
}
};
@ -184,6 +207,7 @@ void SharedState::initInstance(RGSSThreadData *threadData)
* SharedState depends on GlobalIBO existing,
* Font depends on SharedState existing */
#ifndef MKXPZ_RETRO
rgssVersion = threadData->config.rgssVersion;
_globalIBO = new GlobalIBO();
@ -191,32 +215,45 @@ void SharedState::initInstance(RGSSThreadData *threadData)
SharedState::instance = 0;
Font *defaultFont = 0;
#endif // MKXPZ_RETRO
try
{
SharedState::instance = new SharedState(threadData);
#ifndef MKXPZ_RETRO
Font::initDefaults(instance->p->fontState);
defaultFont = new Font();
#endif // MKXPZ_RETRO
}
catch (const Exception &exc)
{
#ifndef MKXPZ_RETRO
delete _globalIBO;
#endif // MKXPZ_RETRO
delete SharedState::instance;
#ifndef MKXPZ_RETRO
delete defaultFont;
#endif // MKXPZ_RETRO
throw exc;
}
#ifndef MKXPZ_RETRO
SharedState::instance->p->defaultFont = defaultFont;
#endif // MKXPZ_RETRO
}
void SharedState::finiInstance()
{
#ifndef MKXPZ_RETRO
delete SharedState::instance->p->defaultFont;
#endif // MKXPZ_RETRO
delete SharedState::instance;
#ifndef MKXPZ_RETRO
delete _globalIBO;
#endif // MKXPZ_RETRO
}
void SharedState::setScreen(Scene &screen)
@ -231,8 +268,11 @@ void SharedState::setScreen(Scene &screen)
}
GSATT(void*, bindingData)
#ifndef MKXPZ_RETRO
GSATT(SDL_Window*, sdlWindow)
#endif // MKXPZ_RETRO
GSATT(Scene*, screen)
#ifndef MKXPZ_RETRO
GSATT(FileSystem&, fileSystem)
GSATT(EventThread&, eThread)
GSATT(RGSSThreadData&, rtData)
@ -246,6 +286,7 @@ GSATT(TexPool&, texPool)
GSATT(Quad&, gpQuad)
GSATT(SharedFontState&, fontState)
GSATT(SharedMidiState&, midiState)
#endif // MKXPZ_RETRO
void SharedState::setBindingData(void *data)
{
@ -254,7 +295,9 @@ void SharedState::setBindingData(void *data)
void SharedState::ensureQuadIBO(size_t minSize)
{
#ifndef MKXPZ_RETRO
_globalIBO->ensureSize(minSize);
#endif // MKXPZ_RETRO
}
GlobalIBO &SharedState::globalIBO()
@ -264,6 +307,7 @@ GlobalIBO &SharedState::globalIBO()
void SharedState::bindTex()
{
#ifndef MKXPZ_RETRO
TEX::bind(p->globalTex);
if (p->globalTexDirty)
@ -271,6 +315,7 @@ void SharedState::bindTex()
TEX::allocEmpty(p->globalTexW, p->globalTexH);
p->globalTexDirty = false;
}
#endif // MKXPZ_RETRO
}
void SharedState::ensureTexSize(int minW, int minH, Vec2i &currentSizeOut)
@ -290,6 +335,7 @@ void SharedState::ensureTexSize(int minW, int minH, Vec2i &currentSizeOut)
currentSizeOut = Vec2i(p->globalTexW, p->globalTexH);
}
#ifndef MKXPZ_RETRO
TEXFBO &SharedState::gpTexFBO(int minW, int minH)
{
bool needResize = false;
@ -344,30 +390,37 @@ void SharedState::releaseAtlasTex(TEXFBO &tex)
p->atlasTex = tex;
}
#endif // MKXPZ_RETRO
void SharedState::checkShutdown()
{
#ifndef MKXPZ_RETRO
if (!p->rtData.rqTerm)
return;
p->rtData.rqTermAck.set();
p->texPool.disable();
scriptBinding->terminate();
#endif // MKXPZ_RETRO
}
void SharedState::checkReset()
{
#ifndef MKXPZ_RETRO
if (!p->rtData.rqReset)
return;
p->rtData.rqReset.clear();
scriptBinding->reset();
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
Font &SharedState::defaultFont() const
{
return *p->defaultFont;
}
#endif // MKXPZ_RETRO
double SharedState::runTime() {
if (!p) return 0;
@ -387,14 +440,20 @@ SharedState::SharedState(RGSSThreadData *threadData)
try
{
p->init(threadData);
#ifdef MKXPZ_RETRO
p->screen = new Scene(); // TODO: implement
#else
p->screen = p->graphics.getScreen();
#endif // MKXPZ_RETRO
}
catch (const Exception &exc)
{
#ifndef MKXPZ_RETRO
// If the "error" was the user quitting the game before the path cache finished building,
// then just return
if (rtData().rqTerm)
return;
#endif // MKXPZ_RETRO
delete p;
SharedState::instance = 0;

View file

@ -37,12 +37,16 @@ public:
: disposed(false),
link(this)
{
#ifndef MKXPZ_RETRO
shState->graphics().addDisposable(this);
#endif // MKXPZ_RETRO
}
virtual ~Disposable()
{
#ifndef MKXPZ_RETRO
shState->graphics().remDisposable(this);
#endif // MKXPZ_RETRO
}
void dispose()