mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 15:01:11 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aea38240b2 | |||
| 0142468125 | |||
| e7d898625d | |||
| 5ee4a3cd35 | |||
| 4794ddcfdf | |||
| 6503e982db | |||
| 72ce1fe33e |
@@ -12,6 +12,20 @@
|
|||||||
"tintColor": "3b5ca8",
|
"tintColor": "3b5ca8",
|
||||||
"category": "games",
|
"category": "games",
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"version": "0.2.23",
|
||||||
|
"date": "2026-08-24",
|
||||||
|
"size": 14060437,
|
||||||
|
"downloadURL": "https://github.com/bryanthaboi/gen1recomp/releases/download/v0.2.23/gen1recomp++-0.2.23-ios.ipa",
|
||||||
|
"localizedDescription": "Download the correct version for your computer below.\n\n## Contributors\n\n- @bryanthaboi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.2.22",
|
||||||
|
"date": "2026-08-24",
|
||||||
|
"size": 14060365,
|
||||||
|
"downloadURL": "https://github.com/bryanthaboi/gen1recomp/releases/download/v0.2.22/gen1recomp++-0.2.22-ios.ipa",
|
||||||
|
"localizedDescription": "Download the correct version for your computer below.\n\n## Contributors\n\n- @bryanthaboi\n- @ShaneMcGovernIE\n- @thibautbus"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.2.21",
|
"version": "0.2.21",
|
||||||
"date": "2026-08-24",
|
"date": "2026-08-24",
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ local GameVersion = require("src.core.GameVersion")
|
|||||||
local CacheContract = {}
|
local CacheContract = {}
|
||||||
|
|
||||||
CacheContract.FORMAT = "rom-cache-v10:"
|
CacheContract.FORMAT = "rom-cache-v10:"
|
||||||
|
CacheContract.VERSION_FORMAT = {
|
||||||
|
crystal = "rom-cache-v10-crystal2:",
|
||||||
|
}
|
||||||
CacheContract.MARKER_PATH = "rom-cache.complete"
|
CacheContract.MARKER_PATH = "rom-cache.complete"
|
||||||
|
|
||||||
CacheContract.REQUIRED_FILES = {
|
CacheContract.REQUIRED_FILES = {
|
||||||
@@ -136,8 +139,13 @@ function CacheContract.requiredFilesFor(version)
|
|||||||
return CacheContract.REQUIRED_FILES, false
|
return CacheContract.REQUIRED_FILES, false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function CacheContract.formatFor(version)
|
||||||
|
return CacheContract.VERSION_FORMAT[version] or CacheContract.FORMAT
|
||||||
|
end
|
||||||
|
|
||||||
function CacheContract.markerFor(version, sha1)
|
function CacheContract.markerFor(version, sha1)
|
||||||
return CacheContract.FORMAT .. (sha1 or GameVersion.info(version).sha1)
|
return CacheContract.formatFor(version)
|
||||||
|
.. (sha1 or GameVersion.info(version).sha1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function CacheContract.markerMatches(version, marker)
|
function CacheContract.markerMatches(version, marker)
|
||||||
|
|||||||
@@ -56,9 +56,6 @@ local MAP_GROUP_COUNT = 26 -- constants/map_constants.asm NUM_MAP_GROUPS
|
|||||||
-- "bank13" (../pokecrystal/main.asm:192-195).
|
-- "bank13" (../pokecrystal/main.asm:192-195).
|
||||||
local PAL_MAP_BANK = 0x02
|
local PAL_MAP_BANK = 0x02
|
||||||
local PAL_MAP_BANK_CRYSTAL = 0x13
|
local PAL_MAP_BANK_CRYSTAL = 0x13
|
||||||
-- LoadBallIconGFX.gfx (engine/battle/trainer_huds.asm:225-232); bank $0b
|
|
||||||
-- carries no manifest symbol to resolve it through.
|
|
||||||
local BALL_ICON_GFX = { 0x0b, 0x41a4 }
|
|
||||||
-- A tileset sheet is 96 tiles (128x48 at 8x8), and its PalMap packs two
|
-- A tileset sheet is 96 tiles (128x48 at 8x8), and its PalMap packs two
|
||||||
-- tiles per byte: low nibble first tile, high nibble second (`dn` in the
|
-- tiles per byte: low nibble first tile, high nibble second (`dn` in the
|
||||||
-- tilepal macro). The high bit of each nibble is the VRAM bank, not colour.
|
-- tilepal macro). The high bit of each nibble is the VRAM bank, not colour.
|
||||||
@@ -2852,7 +2849,10 @@ function RomExtractorGen2:decodeGen2Text(bank, address, charmap, buffers)
|
|||||||
out[#out + 1] = "\f"
|
out[#out + 1] = "\f"
|
||||||
elseif b == 0x55 then
|
elseif b == 0x55 then
|
||||||
out[#out + 1] = "\v"
|
out[#out + 1] = "\v"
|
||||||
elseif b == 0x52 then
|
elseif b == 0x52
|
||||||
|
or (b == 0x14 and inString and self.edition == "crystal") then
|
||||||
|
-- ../pokecrystal/constants/charmap.asm:6 <PLAY_G>,
|
||||||
|
-- ../pokecrystal/home/text.asm:243,380 PlaceGenderedPlayerName
|
||||||
out[#out + 1] = "{PLAYER}"
|
out[#out + 1] = "{PLAYER}"
|
||||||
elseif b == 0x53 then
|
elseif b == 0x53 then
|
||||||
out[#out + 1] = "{RIVAL}"
|
out[#out + 1] = "{RIVAL}"
|
||||||
@@ -5716,8 +5716,8 @@ function RomExtractorGen2:extractMenuGfx()
|
|||||||
|
|
||||||
-- Four OAM tiles at $31 -- normal, statused, fainted, empty -- and OBJ
|
-- Four OAM tiles at $31 -- normal, statused, fainted, empty -- and OBJ
|
||||||
-- colour 0 is transparent (engine/battle/trainer_huds.asm:47-99, :225-232).
|
-- colour 0 is transparent (engine/battle/trainer_huds.asm:47-99, :225-232).
|
||||||
local balls = self.symbols["LoadBallIconGFX.gfx"] or BALL_ICON_GFX
|
local balls = self:symbol("LoadBallIconGFX.gfx")
|
||||||
self:write2bpp(self.rom:bytes(balls[1], balls[2], 4 * 16), 32, 8,
|
self:write2bpp(self.rom:bytes(balls.bank, balls.address, 4 * 16), 32, 8,
|
||||||
"battle/hud/balls.png", true)
|
"battle/hud/balls.png", true)
|
||||||
hud.balls = "assets/generated/battle/hud/balls.png"
|
hud.balls = "assets/generated/battle/hud/balls.png"
|
||||||
hud.ballsFirstTile = 0x31
|
hud.ballsFirstTile = 0x31
|
||||||
|
|||||||
+13
-3
@@ -371,9 +371,13 @@ end
|
|||||||
-- `es`: true for GLSL ES 1.00 (mobile), false for GLSL 1.20 (desktop). Only
|
-- `es`: true for GLSL ES 1.00 (mobile), false for GLSL 1.20 (desktop). Only
|
||||||
-- ever called from ShaderFX.convert().
|
-- ever called from ShaderFX.convert().
|
||||||
function ShaderFX.translate(fullPath, es)
|
function ShaderFX.translate(fullPath, es)
|
||||||
local ffi = require("ffi")
|
local okFfi, ffi = pcall(require, "ffi")
|
||||||
local ok, l = pcall(ensureLib)
|
if not okFfi or type(ffi) ~= "table" then
|
||||||
|
return nil, "this build has no ffi, so presets cannot be converted here"
|
||||||
|
end
|
||||||
|
local ok, l, lerr = pcall(ensureLib)
|
||||||
if not ok then return nil, "ffi.load failed: " .. tostring(l) end
|
if not ok then return nil, "ffi.load failed: " .. tostring(l) end
|
||||||
|
if not l then return nil, tostring(lerr or libError or "librashader bridge not available") end
|
||||||
local ptr = l.librashader_translate_preset(fullPath, es and 1 or 0)
|
local ptr = l.librashader_translate_preset(fullPath, es and 1 or 0)
|
||||||
if ptr == nil then return nil, "librashader_translate_preset returned NULL" end
|
if ptr == nil then return nil, "librashader_translate_preset returned NULL" end
|
||||||
local json = ffi.string(ptr)
|
local json = ffi.string(ptr)
|
||||||
@@ -780,7 +784,7 @@ end
|
|||||||
|
|
||||||
-- Translates `entry` via the bridge and writes ShaderFX.artifactPath(entry).
|
-- Translates `entry` via the bridge and writes ShaderFX.artifactPath(entry).
|
||||||
-- Sets entry.converted on success; an existing artifact survives a failure.
|
-- Sets entry.converted on success; an existing artifact survives a failure.
|
||||||
function ShaderFX.convert(entry, es)
|
local function doConvert(entry, es)
|
||||||
ShaderSourcePatches.apply(entry)
|
ShaderSourcePatches.apply(entry)
|
||||||
local preset, err = ShaderFX.translate(entry.fullPath, es == nil and defaultEs() or es)
|
local preset, err = ShaderFX.translate(entry.fullPath, es == nil and defaultEs() or es)
|
||||||
if not preset then return false, err end
|
if not preset then return false, err end
|
||||||
@@ -797,6 +801,12 @@ function ShaderFX.convert(entry, es)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ShaderFX.convert(entry, es)
|
||||||
|
local ok, res, err = pcall(doConvert, entry, es)
|
||||||
|
if not ok then return false, tostring(res) end
|
||||||
|
return res, err
|
||||||
|
end
|
||||||
|
|
||||||
-- Two independent slots. "shaderfx" stays main's option key, so existing
|
-- Two independent slots. "shaderfx" stays main's option key, so existing
|
||||||
-- saves keep meaning what they already meant.
|
-- saves keep meaning what they already meant.
|
||||||
ShaderFX.SLOTS = { "main", "secondary" }
|
ShaderFX.SLOTS = { "main", "secondary" }
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ function ShaderFXScreen.new(game, slot)
|
|||||||
item.entry.name, tostring(err))
|
item.entry.name, tostring(err))
|
||||||
end
|
end
|
||||||
applyRowState(item)
|
applyRowState(item)
|
||||||
|
if not ok then item.right = Strings("FAILED") end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -114,21 +114,26 @@ check(CacheContract.VERSION_REQUIRED_FILES.yellow ~= nil,
|
|||||||
local CRYSTAL_1_0 = "f4cd194bdee0d04ca4eac29e09b8e4e9d818c133"
|
local CRYSTAL_1_0 = "f4cd194bdee0d04ca4eac29e09b8e4e9d818c133"
|
||||||
local CRYSTAL_1_1 = "f2f52230b536214ef7c9924f483392993e226cfb"
|
local CRYSTAL_1_1 = "f2f52230b536214ef7c9924f483392993e226cfb"
|
||||||
|
|
||||||
|
local CRYSTAL_FORMAT = CacheContract.formatFor("crystal")
|
||||||
|
|
||||||
eq(CacheContract.markerFor("crystal", CRYSTAL_1_1),
|
eq(CacheContract.markerFor("crystal", CRYSTAL_1_1),
|
||||||
CacheContract.FORMAT .. CRYSTAL_1_1,
|
CRYSTAL_FORMAT .. CRYSTAL_1_1,
|
||||||
"markerFor with an explicit sha1 uses that sha1, not the canonical one")
|
"markerFor with an explicit sha1 uses that sha1, not the canonical one")
|
||||||
eq(CacheContract.markerFor("crystal"), CacheContract.FORMAT .. CRYSTAL_1_0,
|
eq(CacheContract.markerFor("crystal"), CRYSTAL_FORMAT .. CRYSTAL_1_0,
|
||||||
"markerFor with no sha1 still defaults to the canonical (1.0) sha1")
|
"markerFor with no sha1 still defaults to the canonical (1.0) sha1")
|
||||||
|
|
||||||
check(CacheContract.markerMatches("crystal", CacheContract.FORMAT .. CRYSTAL_1_0),
|
check(CacheContract.markerMatches("crystal", CRYSTAL_FORMAT .. CRYSTAL_1_0),
|
||||||
"a marker written from the 1.0 hash matches crystal")
|
"a marker written from the 1.0 hash matches crystal")
|
||||||
check(CacheContract.markerMatches("crystal", CacheContract.FORMAT .. CRYSTAL_1_1),
|
check(CacheContract.markerMatches("crystal", CRYSTAL_FORMAT .. CRYSTAL_1_1),
|
||||||
"a marker written from the 1.1 hash also matches crystal")
|
"a marker written from the 1.1 hash also matches crystal")
|
||||||
check(not CacheContract.markerMatches("crystal",
|
check(not CacheContract.markerMatches("crystal",
|
||||||
CacheContract.FORMAT .. "ea9bcae617fdf159b045185467ae58b2e4a48b9a"),
|
CRYSTAL_FORMAT .. "ea9bcae617fdf159b045185467ae58b2e4a48b9a"),
|
||||||
"a marker written from Red's hash does not match crystal")
|
"a marker written from Red's hash does not match crystal")
|
||||||
check(not CacheContract.markerMatches("red", CacheContract.FORMAT .. CRYSTAL_1_1),
|
check(not CacheContract.markerMatches("red", CRYSTAL_FORMAT .. CRYSTAL_1_1),
|
||||||
"a marker written from Crystal's 1.1 hash does not match red")
|
"a marker written from Crystal's 1.1 hash does not match red")
|
||||||
|
check(not CacheContract.markerMatches("crystal",
|
||||||
|
CacheContract.FORMAT .. CRYSTAL_1_0),
|
||||||
|
"a crystal marker written on the shared format no longer matches")
|
||||||
|
|
||||||
local crystalFs = { prefix = "crystal-marker-test/", files = {} }
|
local crystalFs = { prefix = "crystal-marker-test/", files = {} }
|
||||||
function crystalFs.exists(path) return crystalFs.files[crystalFs.prefix .. path] ~= nil end
|
function crystalFs.exists(path) return crystalFs.files[crystalFs.prefix .. path] ~= nil end
|
||||||
@@ -146,7 +151,7 @@ end
|
|||||||
local published11 = CacheContract.publish("crystal", crystalFs, CRYSTAL_1_1)
|
local published11 = CacheContract.publish("crystal", crystalFs, CRYSTAL_1_1)
|
||||||
check(published11, "publishing with the 1.1 sha1 succeeds")
|
check(published11, "publishing with the 1.1 sha1 succeeds")
|
||||||
eq(crystalFs.files["crystal/" .. CacheContract.MARKER_PATH],
|
eq(crystalFs.files["crystal/" .. CacheContract.MARKER_PATH],
|
||||||
CacheContract.FORMAT .. CRYSTAL_1_1, "the marker records the 1.1 sha1")
|
CRYSTAL_FORMAT .. CRYSTAL_1_1, "the marker records the 1.1 sha1")
|
||||||
check(CacheContract.isReady("crystal", crystalFs),
|
check(CacheContract.isReady("crystal", crystalFs),
|
||||||
"a cache published with the 1.1 sha1 still reads ready for crystal")
|
"a cache published with the 1.1 sha1 still reads ready for crystal")
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,35 @@ do
|
|||||||
:format(extra))
|
:format(extra))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ---- the gendered player name ---------------------------------------------
|
||||||
|
-- ../pokecrystal/constants/charmap.asm:6 <PLAY_G> ($14),
|
||||||
|
-- ../pokecrystal/home/text.asm:243,380 PlaceGenderedPlayerName
|
||||||
|
do
|
||||||
|
local Extractor = require("src.import.RomExtractorGen2")
|
||||||
|
local charmap = manifest("tools/rom_manifest_crystal.json").charmap
|
||||||
|
|
||||||
|
local function decode(edition, bytes)
|
||||||
|
local rom = {}
|
||||||
|
function rom:byte(_, address) return bytes[address] or 0x50 end
|
||||||
|
function rom:word(_, address)
|
||||||
|
return (bytes[address] or 0) + (bytes[address + 1] or 0) * 0x100
|
||||||
|
end
|
||||||
|
local extractor = setmetatable({ rom = rom, edition = edition }, Extractor)
|
||||||
|
return extractor:decodeGen2Text(0, 0, charmap)
|
||||||
|
end
|
||||||
|
|
||||||
|
local H, i, comma, space, bang = 0x87, 0xa8, 0xf4, 0x7f, 0xe7
|
||||||
|
local inString = { [0] = 0x00, H, i, comma, space, 0x14, bang, 0x57 }
|
||||||
|
eq(decode("crystal", inString), "Hi, {PLAYER}!",
|
||||||
|
"an in-string $14 decodes as the player's name")
|
||||||
|
eq(decode("gold", inString), "Hi, !",
|
||||||
|
"and only on Crystal, which is the only edition that writes one")
|
||||||
|
|
||||||
|
local command = { [0] = 0x14, 0x03, 0x00, H, i, 0x57 }
|
||||||
|
eq(decode("crystal", command), "{STRBUF}Hi",
|
||||||
|
"a $14 outside a string is still TX_STRINGBUFFER and eats its buffer id")
|
||||||
|
end
|
||||||
|
|
||||||
-- ---- the slots RomText fills ----------------------------------------------
|
-- ---- the slots RomText fills ----------------------------------------------
|
||||||
-- decodeGen2Text emits {USER}, {TARGET} and {ENEMY} for the three names
|
-- decodeGen2Text emits {USER}, {TARGET} and {ENEMY} for the three names
|
||||||
-- PlaceMoveUsersName / PlaceMoveTargetsName / PlaceEnemysName write at
|
-- PlaceMoveUsersName / PlaceMoveTargetsName / PlaceEnemysName write at
|
||||||
|
|||||||
@@ -778,6 +778,9 @@ REQUIRED_SYMBOLS = {
|
|||||||
# nine fill cells. "HP:" and the ten HP-bar cells come from
|
# nine fill cells. "HP:" and the ten HP-bar cells come from
|
||||||
# FontBattleExtra, which is already extracted.
|
# FontBattleExtra, which is already extracted.
|
||||||
"EnemyHPBarBorderGFX", "HPExpBarBorderGFX", "ExpBarGFX",
|
"EnemyHPBarBorderGFX", "HPExpBarBorderGFX", "ExpBarGFX",
|
||||||
|
# gfx/battle/balls.2bpp, the four party-ball OAM tiles
|
||||||
|
# (engine/battle/trainer_huds.asm LoadBallIconGFX).
|
||||||
|
"LoadBallIconGFX.gfx",
|
||||||
# gfx/stats/stats_tiles.png + gfx/stats/pages.pal, StatsScreen_LoadFont
|
# gfx/stats/stats_tiles.png + gfx/stats/pages.pal, StatsScreen_LoadFont
|
||||||
# and _CGB_StatsScreenHPPals (#1558)
|
# and _CGB_StatsScreenHPPals (#1558)
|
||||||
"StatsScreenPageTilesGFX", "StatsScreenPagePals",
|
"StatsScreenPageTilesGFX", "StatsScreenPagePals",
|
||||||
|
|||||||
@@ -17024,6 +17024,10 @@
|
|||||||
32,
|
32,
|
||||||
21684
|
21684
|
||||||
],
|
],
|
||||||
|
"LoadBallIconGFX.gfx": [
|
||||||
|
11,
|
||||||
|
16754
|
||||||
|
],
|
||||||
"LoadOpponentTrainerAndPokemon.resample": [
|
"LoadOpponentTrainerAndPokemon.resample": [
|
||||||
126,
|
126,
|
||||||
16418
|
16418
|
||||||
|
|||||||
@@ -15084,6 +15084,10 @@
|
|||||||
64,
|
64,
|
||||||
24169
|
24169
|
||||||
],
|
],
|
||||||
|
"LoadBallIconGFX.gfx": [
|
||||||
|
11,
|
||||||
|
16804
|
||||||
|
],
|
||||||
"LoadOrientedFrontpic": [
|
"LoadOrientedFrontpic": [
|
||||||
20,
|
20,
|
||||||
22948
|
22948
|
||||||
|
|||||||
@@ -15084,6 +15084,10 @@
|
|||||||
64,
|
64,
|
||||||
24169
|
24169
|
||||||
],
|
],
|
||||||
|
"LoadBallIconGFX.gfx": [
|
||||||
|
11,
|
||||||
|
16804
|
||||||
|
],
|
||||||
"LoadOrientedFrontpic": [
|
"LoadOrientedFrontpic": [
|
||||||
20,
|
20,
|
||||||
22948
|
22948
|
||||||
|
|||||||
Reference in New Issue
Block a user