mirror of
https://github.com/izzy2lost/Super3.git
synced 2026-07-05 15:18:38 -07:00
Fix some missing textures. Fixed reload button.
This commit is contained in:
@@ -417,9 +417,10 @@ void CNew3D::RenderFrame(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw to default framebuffer.
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
// Draw to default framebuffer.
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
// Android compositor draws TileGen bottom surface first; keep color, clear depth for 3D.
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
for (int pri = 0; pri <= 3; pri++) {
|
||||
if (SkipLayer(pri)) continue;
|
||||
|
||||
@@ -132,7 +132,7 @@ InputGunX = MOUSE_XAXIS,JOY1_XAXIS
|
||||
InputGunY = MOUSE_YAXIS,JOY1_YAXIS
|
||||
InputTrigger = KEY_A,JOY1_BUTTON1,MOUSE_LEFT_BUTTON
|
||||
InputOffscreen = KEY_S,JOY1_BUTTON2,MOUSE_RIGHT_BUTTON
|
||||
InputAutoTrigger = 0
|
||||
InputAutoTrigger = 1
|
||||
InputGunLeft2 = NONE
|
||||
InputGunRight2 = NONE
|
||||
InputGunUp2 = NONE
|
||||
@@ -141,7 +141,7 @@ InputGunX2 = JOY2_XAXIS
|
||||
InputGunY2 = JOY2_YAXIS
|
||||
InputTrigger2 = JOY2_BUTTON1
|
||||
InputOffscreen2 = JOY2_BUTTON2
|
||||
InputAutoTrigger2 = 0
|
||||
InputAutoTrigger2 = 1
|
||||
InputAnalogGunLeft = KEY_LEFT
|
||||
InputAnalogGunRight = KEY_RIGHT
|
||||
InputAnalogGunUp = KEY_UP
|
||||
|
||||
@@ -143,6 +143,8 @@ void AndroidInputSystem::ApplyConfig(const Util::Config::Node& config)
|
||||
return config[key].ValueAsDefault<std::string>(fallback);
|
||||
};
|
||||
|
||||
m_gunAutoTrigger = config["InputAutoTrigger"].ValueAsDefault<unsigned>(0) != 0;
|
||||
|
||||
auto keySc = [&](const std::string& mapping, SDL_Scancode fallback) -> SDL_Scancode {
|
||||
if (mapping.empty()) return fallback;
|
||||
SDL_Scancode sc = ParseFirstKeyboardScancode(mapping, *this);
|
||||
@@ -228,6 +230,8 @@ bool AndroidInputSystem::InitializeSystem()
|
||||
std::memset(m_mouseButtonPulseUntilMs, 0, sizeof(m_mouseButtonPulseUntilMs));
|
||||
m_gunFingerActive = false;
|
||||
m_gunFinger = 0;
|
||||
m_suppressGunTriggerUntilMs = 0;
|
||||
m_pendingReloadTriggerAtMs = 0;
|
||||
m_wheelFingerActive = false;
|
||||
m_wheelFinger = 0;
|
||||
m_virtualJoyX.store(0, std::memory_order_relaxed);
|
||||
@@ -271,6 +275,14 @@ bool AndroidInputSystem::Poll()
|
||||
SDL_GameControllerUpdate();
|
||||
|
||||
const uint32_t now = SDL_GetTicks();
|
||||
if (m_pendingReloadTriggerAtMs != 0 && now >= m_pendingReloadTriggerAtMs)
|
||||
{
|
||||
// Manual reload helper when the core's InputAutoTrigger is disabled:
|
||||
// fire the trigger shortly after offscreen is pressed (offscreen->trigger order).
|
||||
m_suppressGunTriggerUntilMs = 0;
|
||||
PulseMouseButton(0, 80);
|
||||
m_pendingReloadTriggerAtMs = 0;
|
||||
}
|
||||
for (auto it = m_pulseUntilMs.begin(); it != m_pulseUntilMs.end();)
|
||||
{
|
||||
if (now >= it->second)
|
||||
@@ -578,11 +590,16 @@ void AndroidInputSystem::HandleTouch(const SDL_TouchFingerEvent& tf, bool down)
|
||||
{
|
||||
if (down)
|
||||
{
|
||||
// Most lightgun games treat "reload" as offscreen + trigger.
|
||||
// If the player is already holding the trigger (aim finger active), only pulse offscreen.
|
||||
// Temporarily suppress trigger so reload happens in the correct order even if the
|
||||
// user is holding the screen to aim/fire (our touch mapping holds MOUSE_LEFT_BUTTON).
|
||||
m_suppressGunTriggerUntilMs = SDL_GetTicks() + 150;
|
||||
|
||||
// Keep offscreen asserted long enough that the core's poll loop won't miss it.
|
||||
PulseMouseButton(2, 140); // right = reload/offscreen
|
||||
if (!m_gunFingerActive)
|
||||
PulseMouseButton(0, 80); // left = trigger pulse (only when not already held)
|
||||
|
||||
// If the core auto-trigger is disabled, approximate the same behavior ourselves.
|
||||
if (!m_gunAutoTrigger)
|
||||
m_pendingReloadTriggerAtMs = SDL_GetTicks() + 90;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -814,6 +831,13 @@ bool AndroidInputSystem::IsMouseButPressed(int mseNum, int butNum)
|
||||
return false;
|
||||
if (butNum < 0 || butNum >= kMouseButtons)
|
||||
return false;
|
||||
if (butNum == 0 && m_suppressGunTriggerUntilMs != 0)
|
||||
{
|
||||
const uint32_t now = SDL_GetTicks();
|
||||
if (now < m_suppressGunTriggerUntilMs)
|
||||
return false;
|
||||
m_suppressGunTriggerUntilMs = 0;
|
||||
}
|
||||
return m_mouseButtons[butNum] != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +192,14 @@ private:
|
||||
uint8_t m_mouseButtons[kMouseButtons]{};
|
||||
uint32_t m_mouseButtonPulseUntilMs[kMouseButtons]{};
|
||||
|
||||
// Lightgun reload behavior:
|
||||
// - If InputAutoTrigger is enabled, we only need to assert Offscreen; the core will
|
||||
// synthesize trigger timing. We also temporarily suppress the trigger so reload
|
||||
// happens in the correct order even if the user is holding the screen to aim/fire.
|
||||
bool m_gunAutoTrigger = false;
|
||||
uint32_t m_suppressGunTriggerUntilMs = 0;
|
||||
uint32_t m_pendingReloadTriggerAtMs = 0;
|
||||
|
||||
std::vector<ControllerState> m_controllers;
|
||||
std::vector<uint8_t> m_keys; // indexed by SDL_Scancode
|
||||
std::unordered_map<SDL_FingerID, HeldDirKeys> m_fingerHeldDir;
|
||||
|
||||
@@ -37,6 +37,92 @@
|
||||
|
||||
static std::string JoinPath(const std::string& a, const std::string& b);
|
||||
|
||||
class CompositedRender3D final : public IRender3D
|
||||
{
|
||||
public:
|
||||
CompositedRender3D(IRender3D* inner, CRender2D* render2d, GlesPresenter* presenter)
|
||||
: m_inner(inner), m_render2d(render2d), m_presenter(presenter)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderFrame(void) override
|
||||
{
|
||||
if (m_presenter && m_render2d && m_render2d->HasFrame())
|
||||
{
|
||||
const uint32_t* pixels = m_render2d->GetFrameBufferRGBA();
|
||||
m_presenter->UpdateFrameARGB(pixels, (int)m_render2d->GetFrameWidth(), (int)m_render2d->GetFrameHeight());
|
||||
m_presenter->Render(false);
|
||||
}
|
||||
if (m_inner)
|
||||
m_inner->RenderFrame();
|
||||
}
|
||||
|
||||
void BeginFrame(void) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->BeginFrame();
|
||||
}
|
||||
|
||||
void EndFrame(void) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->EndFrame();
|
||||
}
|
||||
|
||||
void UploadTextures(unsigned level, unsigned x, unsigned y, unsigned width, unsigned height) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->UploadTextures(level, x, y, width, height);
|
||||
}
|
||||
|
||||
void AttachMemory(const uint32_t* cullingRAMLoPtr,
|
||||
const uint32_t* cullingRAMHiPtr,
|
||||
const uint32_t* polyRAMPtr,
|
||||
const uint32_t* vromPtr,
|
||||
const uint16_t* textureRAMPtr) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->AttachMemory(cullingRAMLoPtr, cullingRAMHiPtr, polyRAMPtr, vromPtr, textureRAMPtr);
|
||||
}
|
||||
|
||||
void SetStepping(int stepping) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->SetStepping(stepping);
|
||||
}
|
||||
|
||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes) override
|
||||
{
|
||||
if (!m_inner)
|
||||
return true;
|
||||
return m_inner->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes);
|
||||
}
|
||||
|
||||
void SetSunClamp(bool enable) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->SetSunClamp(enable);
|
||||
}
|
||||
|
||||
void SetSignedShade(bool enable) override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->SetSignedShade(enable);
|
||||
}
|
||||
|
||||
float GetLosValue(int layer) override
|
||||
{
|
||||
if (!m_inner)
|
||||
return 0.0f;
|
||||
return m_inner->GetLosValue(layer);
|
||||
}
|
||||
|
||||
private:
|
||||
IRender3D* m_inner = nullptr;
|
||||
CRender2D* m_render2d = nullptr;
|
||||
GlesPresenter* m_presenter = nullptr;
|
||||
};
|
||||
|
||||
class NullRender3D : public IRender3D {
|
||||
public:
|
||||
void RenderFrame() override {}
|
||||
@@ -71,6 +157,7 @@ struct Super3Host {
|
||||
StubOutputs outputs;
|
||||
GlesStubRender3D stub3d;
|
||||
std::unique_ptr<New3D::CNew3D> new3d;
|
||||
std::unique_ptr<IRender3D> composited3d;
|
||||
IRender3D* render3d = &stub3d;
|
||||
CRender2D render2d{config};
|
||||
|
||||
@@ -188,6 +275,10 @@ struct Super3Host {
|
||||
config.Set("XResolution", "496");
|
||||
config.Set("YResolution", "384");
|
||||
|
||||
// Lightgun games: reload immediately when tapping the off-screen button.
|
||||
config.Set("InputAutoTrigger", "1");
|
||||
config.Set("InputAutoTrigger2", "1");
|
||||
|
||||
// Minimal default input bindings (keyboard scancodes). On Android, our input
|
||||
// system synthesizes these via touch/controller.
|
||||
config.Set("InputCoin1", "KEY_5");
|
||||
@@ -598,7 +689,13 @@ struct Super3Host {
|
||||
SDL_Log("Loaded state from '%s'.", filePath.c_str());
|
||||
}
|
||||
|
||||
bool InstallNew3D(unsigned xOff, unsigned yOff, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes)
|
||||
bool InstallNew3D(GlesPresenter* presenter,
|
||||
unsigned xOff,
|
||||
unsigned yOff,
|
||||
unsigned xRes,
|
||||
unsigned yRes,
|
||||
unsigned totalXRes,
|
||||
unsigned totalYRes)
|
||||
{
|
||||
if (!model3 || new3d)
|
||||
return !!new3d;
|
||||
@@ -613,7 +710,8 @@ struct Super3Host {
|
||||
return false;
|
||||
}
|
||||
|
||||
render3d = new3d.get();
|
||||
composited3d = std::make_unique<CompositedRender3D>(new3d.get(), &render2d, presenter);
|
||||
render3d = composited3d.get();
|
||||
model3->AttachRenderers(&render2d, render3d);
|
||||
SDL_Log("New3D attached");
|
||||
return true;
|
||||
@@ -899,16 +997,16 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
if (!new3dAttached) {
|
||||
new3dAttached = host.InstallNew3D(xOff, yOff, xRes, yRes, totalXRes, totalYRes);
|
||||
new3dAttached = host.InstallNew3D(&presenter, xOff, yOff, xRes, yRes, totalXRes, totalYRes);
|
||||
}
|
||||
|
||||
if (new3dAttached) {
|
||||
// 3D path: let New3D draw into the default framebuffer from inside the core (scissored).
|
||||
presenter.Resize(winW, winH);
|
||||
presenter.SetStretch(false);
|
||||
host.RunFrame();
|
||||
|
||||
// Overlay TileGen top layers (HUD/menus) on top of 3D.
|
||||
presenter.Resize(winW, winH);
|
||||
presenter.SetStretch(false);
|
||||
if (host.render2d.HasTopSurface()) {
|
||||
const uint32_t* pixels = host.render2d.GetTopSurfaceARGB();
|
||||
presenter.UpdateFrameARGB(pixels, (int)host.render2d.GetFrameWidth(), (int)host.render2d.GetFrameHeight());
|
||||
@@ -916,9 +1014,9 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
}
|
||||
} else {
|
||||
// 2D-only path: keep showing TileGen software output.
|
||||
host.RunFrame();
|
||||
presenter.Resize(winW, winH);
|
||||
presenter.SetStretch(wideBackground);
|
||||
host.RunFrame();
|
||||
if (host.render2d.HasFrame()) {
|
||||
const uint32_t* pixels = host.render2d.GetFrameBufferRGBA();
|
||||
presenter.UpdateFrameARGB(pixels, (int)host.render2d.GetFrameWidth(), (int)host.render2d.GetFrameHeight());
|
||||
|
||||
@@ -55,6 +55,8 @@ object AssetInstaller {
|
||||
"InputGearShift3 = KEY_E,JOY1_BUTTON4" to "InputGearShift3 = KEY_9,JOY1_BUTTON4",
|
||||
"InputGearShift4 = KEY_R,JOY1_BUTTON2" to "InputGearShift4 = KEY_0,JOY1_BUTTON2",
|
||||
"InputGearShiftN = KEY_T" to "InputGearShiftN = KEY_6",
|
||||
"InputAutoTrigger = 0" to "InputAutoTrigger = 1",
|
||||
"InputAutoTrigger2 = 0" to "InputAutoTrigger2 = 1",
|
||||
)
|
||||
val updated =
|
||||
lines.map { line ->
|
||||
|
||||
Reference in New Issue
Block a user