mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 00:02:23 +02:00
196 lines
10 KiB
Markdown
196 lines
10 KiB
Markdown
# New features (deliberate additions beyond the original)
|
||
|
||
Intentional enhancements this port adds on top of faithful Pokémon Red
|
||
behavior. They have no Game Boy equivalent and are kept by design.
|
||
Genuine divergences from the original (things still missing, wrong, or
|
||
approximated) live in docs/known-differences.md; faithfully-ported
|
||
behavior is in docs/behavior-porting-notes.md.
|
||
|
||
## Survey zoom
|
||
|
||
The mouse wheel (or `-`/`=`), the Options **ZOOM** row, or hotkey `4`
|
||
zooms the overworld between 1 pixel per world pixel (full survey) and 2×
|
||
the window fit scale (close-up), in crisp integer steps. This has no Game
|
||
Boy equivalent:
|
||
|
||
- Connected maps render their full bodies, and their NPCs appear as
|
||
visual-only "ghosts", they wander but have no sight lines, triggers,
|
||
dialogue, or collision until the map is actually entered.
|
||
- Menus, text boxes, and battles draw at normal scale on top of the
|
||
zoomed world. Zoom input is ignored while a script, menu, or battle is
|
||
active; the zoom offset is persisted as `save.options.zoom` (default
|
||
`0` = FIT) and survives New Game via `options.lua`.
|
||
- Hotkey `4` ticks through every integer zoom level (survey → FIT →
|
||
close-up → wrap). The Options row shows `FIT` / `OUTn` / `INn`.
|
||
- Beyond the border ring the void fill repeats indefinitely (see VOID
|
||
FILL below); interiors keep their own border block. Each visible map
|
||
area is colorized with its own SGB palette (the original recolored the
|
||
whole screen per map).
|
||
- Neighbor maps load two connection hops out so corner-adjacent maps
|
||
don't pop in and out, and ghost NPCs share instances with the real ones
|
||
so their wander positions persist across seamless connection crossings
|
||
(a warp or fresh map entry still respawns everything at its script
|
||
position, like the original's per-entry sprite init).
|
||
|
||
## VOID FILL
|
||
|
||
The Options **VOID FILL** row picks what paints the infinite beyond-edge
|
||
space on OVERWORLD-tileset maps during survey zoom:
|
||
|
||
- **TREES** (default): solid tree wall block `$0F`.
|
||
- **WATER**: animated water tile `$14` (same hshift cycle as on-map water).
|
||
- **BLACK**: solid black.
|
||
|
||
Other tilesets are unchanged (house/cave borders stay as authored).
|
||
Persisted as `save.options.voidFill`.
|
||
|
||
## Tilt mode
|
||
|
||
The `3` key (and the Options menu TILT row) cycles a visual-only perspective
|
||
tilt of the overworld through **OFF → 15° → 35° → 50° → OFF** for an HD-2D /
|
||
diorama look. Like survey zoom this is purely presentational and has no
|
||
Game Boy equivalent:
|
||
|
||
- The entire map tilts as one rigid ground plane, paths, grass, water,
|
||
floors, and every background-tile structure (buildings, trees, fences,
|
||
signs; in Gen 1 these are baked into the tile layer, not sprites), so
|
||
rows above the player recede and rows below come toward the viewer. Only
|
||
things that actually *stand* on the ground draw as upright billboards,
|
||
unscaled and pixel-identical to flat mode: the player, NPCs, item balls,
|
||
and the standing FX attached to them (emote bubbles, the fishing rod,
|
||
the FLY bird). The Poké Center heal-machine overlay stays on the ground
|
||
plane with the machine tiles (it is OAM glued to a BG graphic, not a
|
||
standing sprite). An earlier revision tried
|
||
billboarding buildings/trees/signs too (cutting them out of the ground
|
||
per hand-curated per-tileset tables); that chased an endless tail of
|
||
special cases, dense tree canopy, fences fused into grass, building
|
||
facades with their own baked-in fake perspective, because Gen 1's art
|
||
was never drawn with a clean seam between ground and standing scenery. It
|
||
wasn't merged; tilting everything but the characters as one plane is the
|
||
simpler, shipped tradeoff (buildings recede/foreshorten with the ground
|
||
like a photo of a diorama, rather than standing fully upright next to
|
||
a full-height character).
|
||
- Cycling tweens the angle between levels over ~0.25s rather than snapping;
|
||
with tilt fully off the world pass drops back onto the flat blit path, so
|
||
flat rendering stays pixel-identical to tilt-off and off costs nothing.
|
||
- Tilt input is gated exactly like survey zoom, honored only while
|
||
free-roaming, ignored while a script, menu, or battle is active, and it
|
||
composes with survey zoom (the zoom scale feeds the projection). The tilt
|
||
level is persisted in `save.options.tilt` (default OFF).
|
||
- It applies everywhere the overworld draws, interiors and caves included.
|
||
Menus, text boxes, and battles render flat on top, unaffected, and the
|
||
infinite beyond-the-border-ring fill stays flat by design.
|
||
- Collision, movement, sight lines, triggers, encounters, and scripts are
|
||
untouched; nothing about the tilt reaches gameplay.
|
||
|
||
## Colors mode
|
||
|
||
The `2` key (and the Options menu COLORS row) cycles the display mode
|
||
through **OG RED → SGB → RED++ → OG → OG INV → SGB INV → CLASSIC → OG RED**.
|
||
The first three are the real colorizations; the rest are DMG-shade novelties:
|
||
|
||
- **OG RED**: the Game Boy Color boot-ROM look for Pokemon Red -- one global
|
||
red BG palette + one green OBJ palette, every map, no per-map variation
|
||
(Pokemon Red has no CGB code, so on a GBC the boot ROM colors it globally).
|
||
The player/NPCs stay green over the red terrain via the OBP bake +
|
||
post-zone redraw (`PaletteFX.GBC_BG` / `GBC_OBJ`).
|
||
- **SGB** (default): the per-map Super Game Boy region palettes
|
||
(`data/sgb/sgb_palettes.asm`). Sprites tint with the region palette, as on
|
||
real SGB. (This is the mode formerly mislabeled "GBC".)
|
||
- **RED++**: pokered-gbc SuperPalettes -- real per-tile GBC coloring plus
|
||
per-species mon colors (`data/palettes_gbc.lua`).
|
||
- **OG**: force the four DMG grays (colorization off).
|
||
- **OG INV**: inverted DMG grays.
|
||
- **SGB INV**: each SGB zone palette with shade order reversed.
|
||
- **CLASSIC**: original Game Boy pea-soup greens
|
||
(`#9BBC0F` / `#8BAC0F` / `#306230` / `#0F380F`).
|
||
|
||
The shade-remap transform is applied centrally in `PaletteFX.sendColors`, so
|
||
it covers overworld, menus, battles, and tilt upright billboards. OG RED's
|
||
global BG palette is supplied by `OverworldState:overworldBgColors` (per-map
|
||
override in the overworld pass). Persisted as `save.options.colors`; the
|
||
`gbc` / `gbc_inv` save ids are kept for back-compat under the new labels.
|
||
|
||
## GBC FX
|
||
|
||
The `5` key (and the Options menu GBC FX row) cycles a "played on real
|
||
unlit-GBC hardware" post-process through **OFF → 1 → 2 → 3 → 4**. The
|
||
levels are a cumulative ladder:
|
||
|
||
- **1**: reflective-screen backing transparency.
|
||
- **2**: + LCD pixel grid.
|
||
- **3**: + pixel drop shadows.
|
||
- **4**: + sunlight glare and rainbow shimmer with a drifting light.
|
||
|
||
It runs as a final present pass after world + UI composite in
|
||
`Renderer:endFrame`, inspired by the Pixel Transparency RetroArch shader
|
||
([github.com/mattakins/Pixel_Transparency](https://github.com/mattakins/Pixel_Transparency)).
|
||
Default OFF; persisted as `save.options.gbcfx`.
|
||
|
||
## Peer-to-peer link play (lua-enet)
|
||
|
||
Trades and link battles connect two copies of the game directly over
|
||
lua-enet (ENet ships inside LÖVE, nothing to install, no server to run)
|
||
on a reliable-ordered channel, replacing the original standalone Python
|
||
room-code relay (`tools/relay_server.py`, deleted). HOST A GAME shows the
|
||
host's LAN address (UDP 7777; `POKEPORT_LINK_PORT` overrides); JOIN A
|
||
GAME enters it. Closing performs a graceful ENet disconnect so the final
|
||
confirm/bye always lands; a vanished peer exits with "The link was
|
||
broken." Internet play needs a forwarded UDP port or a VPN (deliberate
|
||
tradeoff vs. the relay). Headless tests drive the protocol over an
|
||
in-memory loopback (`Net.loopbackPair`); under LÖVE the same test file
|
||
also exercises real UDP pairing.
|
||
|
||
## Custom boot text
|
||
|
||
The boot sequence replaces the Nintendo / GAME FREAK identifiers with
|
||
"bois club" / "bryanthaboi", a deliberate branding customization. The
|
||
rest of the boot beats (copyright splash, "presents" shooting-star, the
|
||
Nidorino-vs-Gengar attract scene) mirror the original.
|
||
|
||
|
||
## Custom Options
|
||
|
||
Options persist in a standalone `options.lua` (separate from the game
|
||
progress `save.lua`), so audio/display/battle preferences survive New Game
|
||
and aren't wiped when a save slot is cleared. Changing a row in the Options
|
||
menu or cycling hotkeys `2`/`3`/`4`/`5` writes immediately; an in-game save also
|
||
flushes the live options. Old saves that still embed an `options` table are
|
||
migrated once into `options.lua` on load.
|
||
|
||
- Music / SFX volume
|
||
- Music Filter
|
||
- OG GLITCHES on / off (Gen 1 quirks vs. modern-clean battle rules)
|
||
- COLORS (OG RED / SGB / RED++ / OG / OG INV / SGB INV / CLASSIC), also
|
||
hotkey `2` (OG RED = GBC boot-ROM look; RED++ uses pokered-gbc
|
||
SuperPalettes + per-species mon colors)
|
||
- TILT (OFF / 15 / 35 / 50), also hotkey `3` while free-roaming
|
||
- ZOOM (FIT / OUTn / INn), also hotkey `4` while free-roaming; wheel and
|
||
`-`/`=` step one level and save
|
||
- VOID FILL (TREES / WATER / BLACK) for OVERWORLD beyond-edge space
|
||
- GBC FX (OFF / 1 / 2 / 3 / 4), also hotkey `5`
|
||
- MAX FPS (30 / 40 / 50 / 60 / 75 / 90 / 100 / 120 / 144 / 160, default 60),
|
||
a hard render frame-rate cap (`save.options.fpsCap`).
|
||
|
||
## Battle transition cascade + white battle letterbox
|
||
|
||
Into-battle wipes still run the original eight styles inside the classic
|
||
160×144 letterbox. On wide/tall windows (survey zoom), matching black 8×8
|
||
blocks cascade outward from that square into the surrounding world so the
|
||
void outside the OG wipe fills in lockstep. Once the battle state is up,
|
||
letterbox voids around the battle canvas fill **white** instead of black
|
||
so the whole window reads as one continuous battle screen.
|
||
|
||
## On-screen touch controls (mobile)
|
||
|
||
On Android/iOS the game draws a translucent d-pad (bottom-left), A/B
|
||
buttons (bottom-right, Game Boy diagonal), and +/- START/SELECT (bottom
|
||
center) over the frame, using Xelu's CC0 controller prompts
|
||
(`assets/touch/`). Real buttons, not gestures: press lands the frame the
|
||
finger does, sliding on the d-pad changes direction without lifting, and
|
||
multi-touch chords (e.g. hold a direction + tap B) work. The overlay only
|
||
appears while no controller is being used: the first gamepad button or
|
||
stick push hides it, the next screen touch brings it back, and unplugging
|
||
the last controller restores it immediately. Layout re-derives from the
|
||
window size on rotation. Desktop testing: `POKEPORT_TOUCH=1 love .` forces
|
||
the overlay on and lets the mouse act as a finger (`=0` forces it off). |