Implement Graphics.transition binding and related bindings in libretro builds

This commit is contained in:
刘皓 2025-04-05 14:35:43 -04:00
parent 5a0a8b76bd
commit d60b23781b
No known key found for this signature in database
GPG key ID: 7901753DB465B711
5 changed files with 151 additions and 30 deletions

View file

@ -25,6 +25,7 @@
#include "sandbox.h"
#include "sharedstate.h"
#include "graphics.h"
#include "bitmap.h"
namespace mkxp_sandbox {
SANDBOX_COROUTINE(graphics_binding_init,
@ -32,6 +33,7 @@ namespace mkxp_sandbox {
SANDBOX_COROUTINE(coro,
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
shState->graphics().update();
SANDBOX_YIELD;
}
@ -42,6 +44,123 @@ namespace mkxp_sandbox {
return sb()->bind<struct coro>()()(self);
}
static VALUE freeze(VALUE self) {
shState->graphics().freeze();
return SANDBOX_NIL;
}
static VALUE transition(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
Bitmap *trans_map;
wasm_ptr_t str;
int32_t duration;
int32_t vague;
int32_t i;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
trans_map = NULL;
duration = 8;
vague = 40;
if (argc >= 1) {
SANDBOX_AWAIT_AND_SET(duration, rb_num2uint, ((VALUE *)(**sb() + argv))[0]);
if (argc >= 2) {
SANDBOX_AWAIT_AND_SET(str, rb_string_value_cstr, &((VALUE *)(**sb() + argv))[1]);
if (*(const char *)(**sb() + str)) {
trans_map = new Bitmap((const char *)(**sb() + str));
}
if (argc >= 3) {
SANDBOX_AWAIT_AND_SET(vague, rb_num2int, ((VALUE *)(**sb() + argv))[2]);
}
}
}
for (i = 0; i < duration; ++i) {
shState->graphics().transition(duration, trans_map, vague, i, i);
SANDBOX_YIELD;
}
}
return SANDBOX_NIL;
}
~coro() {
if (trans_map != NULL) {
delete trans_map;
}
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE wait(VALUE self, VALUE value) {
SANDBOX_COROUTINE(coro,
int32_t duration;
int32_t i;
VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(duration, rb_num2uint, value);
for (i = 0; i < duration; ++i) {
shState->graphics().wait(duration, i, i);
SANDBOX_YIELD;
}
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(self, value);
}
static VALUE fadeout(VALUE self, VALUE value) {
SANDBOX_COROUTINE(coro,
int32_t duration;
int32_t i;
VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(duration, rb_num2uint, value);
for (i = 0; i < duration; ++i) {
shState->graphics().fadeout(duration, i, i);
SANDBOX_YIELD;
}
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(self, value);
}
static VALUE fadein(VALUE self, VALUE value) {
SANDBOX_COROUTINE(coro,
int32_t duration;
int32_t i;
VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(duration, rb_num2uint, value);
for (i = 0; i < duration; ++i) {
shState->graphics().fadein(duration, i, i);
SANDBOX_YIELD;
}
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(self, value);
}
static VALUE frame_reset(VALUE self) {
GFX_LOCK;
shState->graphics().frameReset();
@ -76,18 +195,17 @@ namespace mkxp_sandbox {
return sb()->bind<struct rb_float_new>()()(60.0); // TODO: use actual FPS
}
static VALUE todo(int32_t argc, wasm_ptr_t argv, VALUE self) {
return SANDBOX_NIL;
}
VALUE module;
void operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(module, rb_define_module, "Graphics");
SANDBOX_AWAIT(rb_define_module_function, module, "update", (VALUE (*)(ANYARGS))update, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "freeze", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "transition", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "freeze", (VALUE (*)(ANYARGS))freeze, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "transition", (VALUE (*)(ANYARGS))transition, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "wait", (VALUE (*)(ANYARGS))wait, 1);
SANDBOX_AWAIT(rb_define_module_function, module, "fadeout", (VALUE (*)(ANYARGS))fadeout, 1);
SANDBOX_AWAIT(rb_define_module_function, module, "fadein", (VALUE (*)(ANYARGS))fadein, 1);
SANDBOX_AWAIT(rb_define_module_function, module, "frame_reset", (VALUE (*)(ANYARGS))frame_reset, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "frame_count", (VALUE (*)(ANYARGS))get_frame_count, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "frame_count=", (VALUE (*)(ANYARGS))set_frame_count, 1);

View file

@ -21,6 +21,7 @@
#include "config.h"
#include "graphics.h"
#include "bitmap.h"
#include "sharedstate.h"
#include "binding-util.h"
#include "binding-types.h"
@ -77,7 +78,7 @@ RB_METHOD_GUARD_END
typedef struct {
int duration;
const char *filename;
Bitmap *transMap;
int vague;
} TransitionArgs;
@ -91,19 +92,19 @@ RB_METHOD_GUARD(graphicsTransition)
rb_get_args(argc, argv, "|izi", &duration, &filename, &vague RB_ARG_END);
TransitionArgs args = {duration, filename, vague};
TransitionArgs args = {duration, *filename ? new Bitmap(filename) : 0, vague};
#if RAPI_MAJOR >= 2
drop_gvl_guard([](void *args) -> void* {
TransitionArgs &a = *((TransitionArgs*)args);
GFX_GUARD_EXC( shState->graphics().transition(a.duration,
a.filename,
a.transMap,
a.vague
); );
return 0;
}, &args, 0, 0);
#else
GFX_GUARD_EXC( shState->graphics().transition(duration, filename, vague); )
GFX_GUARD_EXC( shState->graphics().transition(duration, transMap, vague); )
#endif
return Qnil;

View file

@ -439,10 +439,6 @@ extern "C" RETRO_API void retro_run() {
}
}
if (mkxp_retro::sandbox.has_value()) {
shState->graphics().update();
}
void *fb;
if (hw_render.context_type != RETRO_HW_CONTEXT_NONE) {
gl.UseProgram(0);

View file

@ -1321,14 +1321,13 @@ void Graphics::freeze() {
p->compositeToBuffer(p->frozenScene);
}
void Graphics::transition(int duration, const char *filename, int vague) {
void Graphics::transition(int duration, Bitmap *transMap, int vague, int start, int stop) {
p->checkSyncLock();
if (!p->frozen)
return;
vague = clamp(vague, 1, 256);
Bitmap *transMap = *filename ? new Bitmap(filename) : 0;
setBrightness(255);
@ -1373,7 +1372,7 @@ void Graphics::transition(int duration, const char *filename, int vague) {
glState.blend.pushSet(false);
for (int i = 0; i < duration; ++i) {
for (int i = start; i <= stop && i < duration; ++i) {
#ifndef MKXPZ_RETRO
/* We need to clean up transMap properly before
* a possible longjmp, so we manually test for
@ -1431,9 +1430,13 @@ void Graphics::transition(int duration, const char *filename, int vague) {
glState.blend.pop();
#ifndef MKXPZ_RETRO
delete transMap;
#endif // MKXPZ_RETRO
p->frozen = false;
if (stop == INT_MAX || stop + 1 >= duration) {
p->frozen = false;
}
}
void Graphics::frameReset() {
@ -1467,20 +1470,20 @@ double Graphics::averageFrameRate() {
return p->averageFPS();
}
void Graphics::wait(int duration) {
for (int i = 0; i < duration; ++i) {
void Graphics::wait(int duration, int start, int stop) {
for (int i = start; i <= stop && i < duration; ++i) {
p->checkShutDownReset();
p->redrawScreen();
}
}
void Graphics::fadeout(int duration) {
void Graphics::fadeout(int duration, int start, int stop) {
FBO::unbind();
float curr = p->brightness;
float diff = 255.0f - curr;
for (int i = duration - 1; i > -1; --i) {
for (int i = std::min(stop, duration - 1); i >= start; --i) {
setBrightness(diff + (curr / duration) * i);
if (p->frozen) {
@ -1501,14 +1504,14 @@ void Graphics::fadeout(int duration) {
}
}
void Graphics::fadein(int duration) {
void Graphics::fadein(int duration, int start, int stop) {
FBO::unbind();
float curr = p->brightness;
float diff = 255.0f - curr;
for (int i = 1; i <= duration; ++i) {
setBrightness(curr + (diff / duration) * i);
for (int i = start; i <= stop && i < duration;) {
setBrightness(curr + (diff / duration) * ++i);
if (p->frozen) {
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), p->frozenScene, IntRect(0, 0, p->scRes.x, p->scRes.y));

View file

@ -22,6 +22,7 @@
#ifndef GRAPHICS_H
#define GRAPHICS_H
#include <climits>
#include "util.h"
class Scene;
@ -42,17 +43,19 @@ public:
void update(bool checkForShutdown = true);
void freeze();
void transition(int duration = 8,
const char *filename = "",
int vague = 40);
Bitmap *transMap = 0,
int vague = 40,
int start = 0,
int stop = INT_MAX);
void frameReset();
DECL_ATTR( FrameRate, int )
DECL_ATTR( FrameCount, int )
DECL_ATTR( Brightness, int )
void wait(int duration);
void fadeout(int duration);
void fadein(int duration);
void wait(int duration, int start = 0, int stop = INT_MAX);
void fadeout(int duration, int start = 0, int stop = INT_MAX);
void fadein(int duration, int start = 0, int stop = INT_MAX);
Bitmap *snapToBitmap();