mirror of
https://github.com/AverageConsumer/kanto-gear.git
synced 2026-08-28 18:24:42 +02:00
release: prepare Kanto Gear 1.3.0
This commit is contained in:
@@ -7,8 +7,8 @@ battles, menus and contextual touch controls move to the second display.
|
||||
> [!IMPORTANT]
|
||||
> This is an **unofficial Android public test build**, not an official
|
||||
> Gen1Recomp release. It is verified on an **AYN Thor running Android 13** and
|
||||
> is intended to work on comparable Android dual-display devices. Other
|
||||
> handhelds, docks and HDMI setups still need community testing.
|
||||
> community-tested on a **Retroid Pocket 5 with the Retroid Dual Screen Add-on**.
|
||||
> Other handhelds, docks and HDMI setups still need community testing.
|
||||
|
||||

|
||||
|
||||
@@ -25,31 +25,42 @@ battles, menus and contextual touch controls move to the second display.
|
||||
second display when those screens are active.
|
||||
- Can hide duplicated battle UI on the main display. On the tested Thor, the
|
||||
main UI returns immediately when the second display is switched off.
|
||||
- Offers `AUTO`, `HANDHELD` and `EXTRA SCREEN` display targeting for handheld,
|
||||
- Offers `AUTO`, `HANDHELD` and `EXTERNAL` display targeting for handheld,
|
||||
docked and TV-style layouts.
|
||||
- Works without the Voxel Mod. The matching Voxel performance fork is an
|
||||
optional visual upgrade.
|
||||
|
||||
## Which downloads do I need?
|
||||
|
||||
Use this matched release set:
|
||||
|
||||
| Download | Required? | What it provides |
|
||||
| --- | --- | --- |
|
||||
| [`gen1recomp-android-0.1.72-kanto.4.apk`](https://github.com/AverageConsumer/gen1recomp/releases/tag/v0.1.72-kanto.4) | **Required** | Android host with the dual-display bridge and device-routing fixes |
|
||||
| [`Kanto-Gear-Mod-1.3.0.zip`](https://github.com/AverageConsumer/kanto-gear/releases/tag/v1.3.0) | **Required** | Kanto Gear itself |
|
||||
| [`DRAMATIC_SHAPE-1.6.0-android.2.zip`](https://github.com/AverageConsumer/DramaticShapeVoxelMod/releases/tag/v1.6.0-android.2) | Optional | Tested Android 3D renderer and Stadium compatibility fix |
|
||||
|
||||
The official Gen1Recomp Android release does not yet contain the complete host
|
||||
support used by Kanto Gear, so the APK fork is currently required. Kanto Gear
|
||||
works without the Voxel fork; install it only if you want the 3D renderer.
|
||||
|
||||
## Install on Android
|
||||
|
||||
You need your own supported Pokemon Red, Blue or Yellow ROM. No ROM or
|
||||
ROM-extracted game data is included here.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> For the complete tested Android experience, use the exact three-part release
|
||||
> set linked below: the Gen1Recomp Android test APK, Kanto Gear, and the
|
||||
> Dramatic Shape Android performance fork. The host and Kanto Gear are
|
||||
> required; the Voxel fork is technically optional but is the recommended 3D
|
||||
> renderer for this package. Do not substitute the official host or mix
|
||||
> Use the matched versions above. The host APK and Kanto Gear are required;
|
||||
> the Voxel fork is optional. Do not substitute the official host or mix
|
||||
> versions from different release sets.
|
||||
|
||||
1. Download `gen1recomp-android-0.1.69-kanto.3.apk` from the latest
|
||||
[Gen1Recomp Android test release](https://github.com/AverageConsumer/gen1recomp/releases/tag/v0.1.69-kanto.3)
|
||||
1. Download `gen1recomp-android-0.1.72-kanto.4.apk` from the matching
|
||||
[Gen1Recomp Android test release](https://github.com/AverageConsumer/gen1recomp/releases/tag/v0.1.72-kanto.4)
|
||||
and install it.
|
||||
2. Download `Kanto-Gear-Mod-1.2.0.zip` from the latest
|
||||
[Kanto Gear release](https://github.com/AverageConsumer/kanto-gear/releases/tag/v1.2.0).
|
||||
2. Download `Kanto-Gear-Mod-1.3.0.zip` from the matching
|
||||
[Kanto Gear release](https://github.com/AverageConsumer/kanto-gear/releases/tag/v1.3.0).
|
||||
3. Start **Gen1Recomp Android Test**, import your ROM, open the **MODS** tab,
|
||||
tap **Import mod .zip**, and choose `Kanto-Gear-Mod-1.2.0.zip`.
|
||||
tap **Import mod .zip**, and choose `Kanto-Gear-Mod-1.3.0.zip`.
|
||||
4. Make sure **Kanto Gear** is enabled, then start the game. The companion
|
||||
appears automatically when Android reports a suitable second display.
|
||||
|
||||
@@ -76,7 +87,7 @@ Gear package because handhelds need additional frame-pacing work. If you want
|
||||
the tested Android 3D setup:
|
||||
|
||||
1. Download the latest `.zip` from the
|
||||
[Kanto Gear Voxel performance fork](https://github.com/AverageConsumer/DramaticShapeVoxelMod/releases/tag/v1.6.0-android.1).
|
||||
[Kanto Gear Voxel performance fork](https://github.com/AverageConsumer/DramaticShapeVoxelMod/releases/tag/v1.6.0-android.2).
|
||||
2. If the original Dramatic Shape Voxel Mod is already installed, remove it
|
||||
from the **MODS** tab first. Both versions intentionally use the same mod ID.
|
||||
3. Import the performance-fork `.zip` through **MODS → Import mod .zip**.
|
||||
@@ -96,7 +107,7 @@ handheld and the fork is not distributed as a PC replacement.
|
||||
- **Tap the arrows in the header** for the same navigation without swiping.
|
||||
Horizontal swipes and arrows also move through multi-page Guide and Area
|
||||
views before continuing to the next section.
|
||||
- **SPOILER LOCAL MAP** defaults to **OFF**. **MAP** adds a swipe page showing
|
||||
- **AREA MAP** defaults to **OFF**. **MAP** adds a swipe page showing
|
||||
the complete current map or floor and your live position; **ENHANCED** also
|
||||
marks exits plus visible and hidden items that have not been collected. The
|
||||
regular region map remains the Fly screen, so tapping its unlocked
|
||||
@@ -112,23 +123,21 @@ handheld and the fork is not distributed as a PC replacement.
|
||||
|
||||
## Settings worth knowing
|
||||
|
||||
- **BOTTOM SCREEN → AUTO** is the recommended default.
|
||||
- **GEAR SCREEN → AUTO** is the recommended default.
|
||||
- **HANDHELD** prefers the other built-in display.
|
||||
- **EXTRA SCREEN** prefers an external presentation display for TV-style use.
|
||||
- **HIDE UPPER BATTLE UI** removes duplicated battle menus only while the
|
||||
companion display is ready.
|
||||
- **FULL BOTTOM BATTLE UI** additionally moves both HP/status panels to the
|
||||
companion display. The current split layout remains the default.
|
||||
- **PROFILE → PURIST** hides gameplay-assistance pages; **ENHANCED** enables
|
||||
them; **CUSTOM** lets you choose each assist separately.
|
||||
- **EXTERNAL** prefers an external presentation display for TV-style use.
|
||||
- **BATTLE VIEW → STANDARD** keeps the normal game HUD. **GEAR** moves
|
||||
duplicated battle controls to Kanto Gear, while **FULL GEAR** also moves the
|
||||
HP/status panels. The standard split layout remains the default.
|
||||
- **INFO → PURIST** hides gameplay-assistance pages; **ENHANCED** enables them.
|
||||
|
||||
## Tested release set
|
||||
|
||||
| Component | Version | Role |
|
||||
| --- | --- | --- |
|
||||
| [Kanto Gear](https://github.com/AverageConsumer/kanto-gear) | 1.2.0 public test | Required second-screen mod |
|
||||
| [Gen1Recomp Android test fork](https://github.com/AverageConsumer/gen1recomp) | 0.1.69-kanto.3 | Required Android host APK |
|
||||
| [Dramatic Shape performance fork](https://github.com/AverageConsumer/DramaticShapeVoxelMod) | 1.6.0-android.1 | Recommended for the complete tested 3D setup; technically optional |
|
||||
| [Kanto Gear](https://github.com/AverageConsumer/kanto-gear) | 1.3.0 public test | Required second-screen mod |
|
||||
| [Gen1Recomp Android test fork](https://github.com/AverageConsumer/gen1recomp) | 0.1.72-kanto.4 | Required Android host APK |
|
||||
| [Dramatic Shape performance fork](https://github.com/AverageConsumer/DramaticShapeVoxelMod) | 1.6.0-android.2 | Optional Android 3D renderer |
|
||||
|
||||
Do not mix arbitrary releases from the three repositories. Each Kanto Gear
|
||||
release links the exact set that was tested together.
|
||||
@@ -139,8 +148,9 @@ Gear release sets manually as a matched group.
|
||||
|
||||
## Known limits
|
||||
|
||||
- The AYN Thor is the confirmed reference device. Comparable Android
|
||||
dual-display hardware is intended to work but remains community-tested.
|
||||
- The AYN Thor is the confirmed reference device. Retroid Pocket 5 support was
|
||||
tested with Retroid's USB-C Dual Screen Add-on. Other Android dual-display
|
||||
hardware, including GammaOS devices, still needs community testing.
|
||||
- Desktop and ordinary single-screen builds have no companion display; the mod
|
||||
stays inactive rather than opening another desktop window.
|
||||
- External-monitor rotation, unusual three-display layouts and manufacturer
|
||||
@@ -178,6 +188,11 @@ Their progress, code and project direction remain theirs. These forks exist to
|
||||
test additional work without presenting it as official or asking upstream
|
||||
users to debug our changes.
|
||||
|
||||
Special thanks to [@Rocky5150](https://github.com/Rocky5150) for patiently
|
||||
testing the Retroid Pocket 5 dual-screen support, collecting detailed
|
||||
diagnostics, and working with us for more than 24 hours to identify and verify
|
||||
the Android display-routing fixes.
|
||||
|
||||
Kanto Gear's own code is available under the [MIT License](LICENSE). That
|
||||
license does not replace or extend the licenses, rights or ownership of
|
||||
Gen1Recomp, Dramatic Shape Voxel Mod, Pokemon or their respective assets.
|
||||
|
||||
+59
-87
@@ -236,18 +236,13 @@ local function methodLines(methods)
|
||||
return lines[1] or "", lines[2] or ""
|
||||
end
|
||||
|
||||
local function profileFromAssists(get)
|
||||
local hints, details = get("type_hints"), get("move_details")
|
||||
local guide, area = get("guide"), get("area")
|
||||
local radar, catchOdds = get("item_radar"), get("catch_odds")
|
||||
if hints and details and guide and area and radar and catchOdds then
|
||||
return "enhanced"
|
||||
local function battleUIMode(value, legacyFull)
|
||||
if value == "standard" or value == "gear" or value == "full" then
|
||||
return value
|
||||
end
|
||||
if not hints and not details and not guide and not area and not radar
|
||||
and not catchOdds then
|
||||
return "purist"
|
||||
end
|
||||
return "custom"
|
||||
if legacyFull == true then return "full" end
|
||||
if value == true then return "gear" end
|
||||
return "standard"
|
||||
end
|
||||
|
||||
local function checklistPages(sections)
|
||||
@@ -413,18 +408,11 @@ end
|
||||
assert(not assistEnabled("purist", true)
|
||||
and assistEnabled("enhanced", false)
|
||||
and assistEnabled("custom", true), "assist profiles")
|
||||
do
|
||||
local values = { type_hints = true, move_details = true,
|
||||
guide = true, area = true, item_radar = true,
|
||||
catch_odds = true }
|
||||
local function get(key) return values[key] end
|
||||
assert(profileFromAssists(get) == "enhanced", "all assists enhanced")
|
||||
values.guide = false
|
||||
assert(profileFromAssists(get) == "custom", "mixed assists custom")
|
||||
values.type_hints, values.move_details, values.area, values.item_radar,
|
||||
values.catch_odds = false, false, false, false, false
|
||||
assert(profileFromAssists(get) == "purist", "all assists purist")
|
||||
end
|
||||
assert(battleUIMode("standard", true) == "standard"
|
||||
and battleUIMode("gear", false) == "gear"
|
||||
and battleUIMode("full", false) == "full"
|
||||
and battleUIMode(true, false) == "gear"
|
||||
and battleUIMode(false, true) == "full", "battle UI settings")
|
||||
do
|
||||
local pages = checklistPages({
|
||||
{ name = "TRAINERS", rows = { { done = true }, { done = false } } },
|
||||
@@ -618,73 +606,65 @@ local function inside(x, y, left, top, width, height)
|
||||
end
|
||||
|
||||
return function(mod)
|
||||
local infoDefault = mod.options:get("info_level")
|
||||
if infoDefault == nil then
|
||||
local legacyProfile = mod.options:get("profile")
|
||||
infoDefault = legacyProfile == "custom" and "legacy"
|
||||
or legacyProfile == "purist" and "purist" or "enhanced"
|
||||
end
|
||||
local infoChoices = {
|
||||
{ "PURIST", "purist" }, { "ENHANCED", "enhanced" },
|
||||
}
|
||||
if infoDefault == "legacy" then
|
||||
infoChoices[#infoChoices + 1] = { "SAVED CUSTOM", "legacy" }
|
||||
end
|
||||
|
||||
local battleDefault = mod.options:get("battle_view")
|
||||
if battleDefault == nil then
|
||||
battleDefault = battleUIMode(mod.options:get("hide_upper_battle_ui"),
|
||||
mod.options:get("full_bottom_battle_ui"))
|
||||
end
|
||||
|
||||
mod.options:define({
|
||||
{ key = "theme", label = "BOTTOM THEME", type = "choice",
|
||||
{ key = "theme", label = "THEME", type = "choice",
|
||||
default = "kanto", choices = {
|
||||
{ "KANTO GREEN", "kanto" }, { "MATCH GAME", "match" },
|
||||
{ "OG", "og" }, { "OG INVERTED", "og_inv" },
|
||||
{ "SGB", "sgb" }, { "ADVANCED", "advanced" },
|
||||
{ "VERSION COLOR", "version" },
|
||||
} },
|
||||
{ key = "profile", label = "PROFILE", type = "choice",
|
||||
default = "enhanced", choices = {
|
||||
{ "PURIST", "purist" }, { "ENHANCED", "enhanced" },
|
||||
{ "CUSTOM", "custom" },
|
||||
}, sync = true, sets = {
|
||||
purist = { type_hints = false, move_details = false,
|
||||
guide = false, area = false, item_radar = false,
|
||||
catch_odds = false },
|
||||
enhanced = { type_hints = true, move_details = true,
|
||||
guide = true, area = true, item_radar = true,
|
||||
catch_odds = true },
|
||||
custom = { profile = profileFromAssists },
|
||||
} },
|
||||
{ key = "type_hints", label = "ASSIST TYPE HINTS",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "move_details", label = "ASSIST MOVE INFO",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "guide", label = "ASSIST GUIDE PAGE",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "area", label = "ASSIST AREA PAGE",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "item_radar", label = "ASSIST ITEM RADAR",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "catch_odds", label = "ASSIST CATCH ODDS",
|
||||
type = "toggle", default = true,
|
||||
sets = { [false] = { profile = profileFromAssists },
|
||||
[true] = { profile = profileFromAssists } } },
|
||||
{ key = "local_map", label = "SPOILER LOCAL MAP",
|
||||
{ key = "info_level", label = "INFO", type = "choice",
|
||||
default = infoDefault, choices = infoChoices },
|
||||
{ key = "local_map", label = "AREA MAP",
|
||||
type = "choice", default = false, choices = {
|
||||
{ "OFF", false }, { "MAP", true }, { "ENHANCED", "enhanced" },
|
||||
} },
|
||||
{ key = "display_target", label = "BOTTOM SCREEN", type = "choice",
|
||||
{ key = "display_target", label = "GEAR SCREEN", type = "choice",
|
||||
default = "auto", choices = {
|
||||
{ "AUTO", "auto" }, { "HANDHELD", "handheld" },
|
||||
{ "EXTRA SCREEN", "secondary" },
|
||||
{ "EXTERNAL", "secondary" },
|
||||
} },
|
||||
{ key = "battle_view", label = "BATTLE VIEW",
|
||||
type = "choice", default = battleDefault, choices = {
|
||||
{ "STANDARD", "standard" }, { "GEAR", "gear" },
|
||||
{ "FULL GEAR", "full" },
|
||||
} },
|
||||
{ key = "hide_upper_battle_ui", label = "HIDE UPPER BATTLE UI",
|
||||
type = "toggle", default = false },
|
||||
{ key = "full_bottom_battle_ui", label = "FULL BOTTOM BATTLE UI",
|
||||
type = "toggle", default = false },
|
||||
})
|
||||
local function assist(key)
|
||||
return assistEnabled(mod.options:get("profile"), mod.options:get(key))
|
||||
local level = mod.options:get("info_level")
|
||||
if level == "legacy" then
|
||||
return assistEnabled("custom", mod.options:get(key))
|
||||
end
|
||||
return level ~= "purist"
|
||||
end
|
||||
local function currentBattleUIMode()
|
||||
return mod.options:get("battle_view") or "standard"
|
||||
end
|
||||
local function fullBottomBattleUI()
|
||||
return mod.options:get("full_bottom_battle_ui") == true
|
||||
return currentBattleUIMode() == "full"
|
||||
end
|
||||
local function hideUpperBattleUI()
|
||||
return fullBottomBattleUI() or mod.options:get("hide_upper_battle_ui")
|
||||
return currentBattleUIMode() ~= "standard"
|
||||
end
|
||||
|
||||
local runtime = rawget(_G, "love")
|
||||
@@ -696,7 +676,7 @@ return function(mod)
|
||||
end
|
||||
|
||||
local PaletteFX = require("src.render.PaletteFX")
|
||||
local EngineFont = require("src.render.Font")
|
||||
local EngineFont = mod.ui.Font
|
||||
|
||||
local canvas = G.newCanvas(WIDTH, HEIGHT, { dpiscale = 1 })
|
||||
canvas:setFilter("nearest", "nearest")
|
||||
@@ -723,7 +703,6 @@ return function(mod)
|
||||
local mapAsset = nil
|
||||
local localMap = nil
|
||||
local spriteCache = {}
|
||||
local caughtBall = nil
|
||||
local touchDown = nil
|
||||
local textSpeedToken
|
||||
local textSpeedReleasePending = false
|
||||
@@ -2061,20 +2040,13 @@ return function(mod)
|
||||
end
|
||||
|
||||
local function drawCaughtBall(x, y)
|
||||
if caughtBall == nil then
|
||||
local ok, image = pcall(G.newImage,
|
||||
"assets/generated/battle/balls.png")
|
||||
if ok then
|
||||
image:setFilter("nearest", "nearest")
|
||||
caughtBall = { image = image,
|
||||
quad = G.newQuad(0, 0, 8, 8, image:getDimensions()) }
|
||||
else
|
||||
caughtBall = false
|
||||
end
|
||||
end
|
||||
if not caughtBall then return end
|
||||
G.setColor(1, 1, 1, 1)
|
||||
G.draw(caughtBall.image, caughtBall.quad, x, y)
|
||||
box("fill", x + 2, y, 4, 1, INK)
|
||||
box("fill", x + 1, y + 1, 6, 1, INK)
|
||||
box("fill", x, y + 2, 8, 4, INK)
|
||||
box("fill", x + 1, y + 6, 6, 1, INK)
|
||||
box("fill", x + 2, y + 7, 4, 1, INK)
|
||||
box("fill", x + 1, y + 3, 6, 2, PAPER)
|
||||
box("fill", x + 3, y + 3, 2, 2, DARK)
|
||||
end
|
||||
|
||||
local function drawFullBattleStatus(mon, y, player)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "kanto_gear",
|
||||
"name": "Kanto Gear",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"api": 2,
|
||||
"entry": "main.lua",
|
||||
"category": "UI",
|
||||
@@ -12,5 +12,5 @@
|
||||
"optional_dependencies": [],
|
||||
"conflicts": [],
|
||||
"permissions": ["engine_internals"],
|
||||
"description": "Dual-screen map, party, battle, PC and contextual touch controls for supported Gen1Recomp Android hosts. Public hardware test; currently verified on AYN Thor."
|
||||
"description": "Dual-screen map, party, battle, PC and contextual touch controls for supported Gen1Recomp Android hosts. Tested on AYN Thor and Retroid Pocket 5."
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@ T.love.graphics.newCanvas = newCanvas
|
||||
T.eq(#run.errors, 0,
|
||||
"Kanto Gear loads clean: " .. table.concat(run.errors, "; "))
|
||||
T.check(run.loader.exports.kanto_gear ~= nil, "Kanto Gear registers")
|
||||
local options = run.loader.optionSchemas.kanto_gear
|
||||
T.eq(#options, 5, "Kanto Gear keeps its settings compact")
|
||||
T.eq(options[1].label, "THEME", "theme setting is device-neutral")
|
||||
T.eq(options[2].label, "INFO", "assist features use one preset")
|
||||
T.eq(options[4].label, "GEAR SCREEN", "display setting is device-neutral")
|
||||
T.eq(options[5].label, "BATTLE VIEW", "battle layout uses one setting")
|
||||
T.eq(#options[5].choices, 3, "battle view exposes three clear layouts")
|
||||
local hooks = T.record.hooks(run.loader)
|
||||
T.eq(hooks:depth("render.compose"), 1,
|
||||
"Kanto Gear uses the upstream composition seam")
|
||||
|
||||
Reference in New Issue
Block a user