Fix some missing textures. Fixed reload button.

This commit is contained in:
izzy2lost
2026-01-10 00:18:29 -05:00
parent d7b5b75b10
commit 6e1905e0b3
6 changed files with 148 additions and 15 deletions
+4 -3
View File
@@ -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;
+104 -6
View File
@@ -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 ->