mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 11:11:10 +02:00
CLOSES #1090, CLOSES #1093, CLOSES #1094, CLOSES #1095, CLOSES #1098, CLOSES #1102, CLOSES #1105, CLOSES #1106, CLOSES #1108, CLOSES #1109, CLOSES #1110, CLOSES #1111, CLOSES #1113, CLOSES #1114, CLOSES #1117, CLOSES #1118, CLOSES #1121, CLOSES #1122, CLOSES #1123, CLOSES #1124, CLOSES #1126, CLOSES #1127, CLOSES #1128, CLOSES #1131, CLOSES #1132, CLOSES #1134, CLOSES #1137, CLOSES #1141
This commit is contained in:
+13
-2
@@ -203,7 +203,8 @@ function ChipAudio.playMusic(data, header, allowLoops)
|
||||
cmdCh:push({ cmd = "play", gen = gen, header = header,
|
||||
allowLoops = allowLoops, audio = slimAudio(data),
|
||||
channelVolumes = ChipSynth.getChannelVolumes(),
|
||||
channelPitches = ChipSynth.getChannelPitches() })
|
||||
channelPitches = ChipSynth.getChannelPitches(),
|
||||
stereo = ChipSynth.getStereo() })
|
||||
currentMusic = { source = source, gen = gen, threaded = true,
|
||||
started = false, finished = false }
|
||||
-- playback starts in update() once the first buffer arrives (~1 frame)
|
||||
@@ -214,7 +215,8 @@ local function pushChannelMix()
|
||||
if workerReady and cmdCh then
|
||||
cmdCh:push({ cmd = "channelMix",
|
||||
volumes = ChipSynth.getChannelVolumes(),
|
||||
pitches = ChipSynth.getChannelPitches() })
|
||||
pitches = ChipSynth.getChannelPitches(),
|
||||
stereo = ChipSynth.getStereo() })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -352,6 +354,15 @@ function ChipAudio.shutdown()
|
||||
workerReady = false
|
||||
end
|
||||
|
||||
function ChipAudio.setStereo(enabled)
|
||||
ChipSynth.setStereo(enabled)
|
||||
pushChannelMix()
|
||||
end
|
||||
|
||||
function ChipAudio.getStereo()
|
||||
return ChipSynth.getStereo()
|
||||
end
|
||||
|
||||
-- Runtime mix for one hardware channel (1..4). Takes effect on the next
|
||||
-- synthesized buffer (live music) and on any SFX/cry rendered after the call.
|
||||
function ChipAudio.setChannelVolume(hw, scale)
|
||||
|
||||
+19
-4
@@ -29,6 +29,18 @@ ChipSynth.SAMPLE_RATE = SAMPLE_RATE
|
||||
ChipSynth.MUSIC_BUFFER_SAMPLES = MUSIC_BUFFER_SAMPLES
|
||||
ChipSynth.MUSIC_BUFFER_COUNT = MUSIC_BUFFER_COUNT
|
||||
|
||||
-- Gen 2 SOUND option (MONO/STEREO): gates Music_StereoPanning's per-song
|
||||
-- panning byte (audio/engine.asm:1987 wOptions STEREO bit).
|
||||
local stereoEnabled = false
|
||||
|
||||
function ChipSynth.setStereo(enabled)
|
||||
stereoEnabled = not not enabled
|
||||
end
|
||||
|
||||
function ChipSynth.getStereo()
|
||||
return stereoEnabled
|
||||
end
|
||||
|
||||
-- Runtime mix per hardware channel (1 pulse, 2 pulse, 3 wave, 4 noise).
|
||||
-- Volume: 1 = authentic GB, 0 = mute. Pitch: 1 = authentic, 2 = +1 octave,
|
||||
-- 0.5 = -1 octave. Applied at sample time so a live change reaches the next
|
||||
@@ -760,11 +772,14 @@ function Channel:nextEventGen2()
|
||||
-- no-op for the PCM renderer
|
||||
elseif command == 0xEE then -- unknownmusic0xee
|
||||
self:word()
|
||||
elseif command == 0xEF then -- stereo_panning (honor always; options.stereo)
|
||||
elseif command == 0xEF then
|
||||
-- audio/engine.asm:1987 Music_StereoPanning: apply only when STEREO is on
|
||||
local packed = self:byte()
|
||||
local mask = bit.lshift(1, self.hardware - 1)
|
||||
local default = bit.bor(bit.lshift(mask, 4), mask)
|
||||
self.tracks = bit.band(packed, default)
|
||||
if stereoEnabled then
|
||||
local mask = bit.lshift(1, self.hardware - 1)
|
||||
local default = bit.bor(bit.lshift(mask, 4), mask)
|
||||
self.tracks = bit.band(packed, default)
|
||||
end
|
||||
elseif command == 0xF0 then -- sfx_toggle_noise
|
||||
if self.noiseSampling then
|
||||
self.noiseSampling = false
|
||||
|
||||
+13
-28
@@ -140,7 +140,7 @@ Game2.anchorNewGameClock = anchorNewGameClock
|
||||
|
||||
function Game2.new()
|
||||
local self = setmetatable({
|
||||
speedOverride = 1,
|
||||
speedOverride = nil,
|
||||
capturePath = nil,
|
||||
world = nil,
|
||||
status = nil,
|
||||
@@ -975,27 +975,9 @@ function Game2:load()
|
||||
local Pipelines = require("src.render.Pipelines")
|
||||
Pipelines.install(self.data)
|
||||
Pipelines.applyOptions(self.options)
|
||||
-- Gold composites the WHOLE-FRAME half of a pipeline (`present`) and not the
|
||||
-- world half: its overworld draws straight to the window rather than into a
|
||||
-- canvas the way src/world/OverworldController.lua:4827 hands one to
|
||||
-- Pipelines.drawWorld, so there is nothing here for drawWorld to replace yet.
|
||||
-- A restored level for a world-only pipeline is retired rather than left
|
||||
-- switched on, because on Gold it would render nothing AND hold TILT off
|
||||
-- (Pipelines.setLevel's tilt exclusion). The stored level in
|
||||
-- options.pipelines is left untouched, so the mode comes back the day Gold
|
||||
-- grows a world canvas; Tilt is re-applied from the option the exclusion just
|
||||
-- cleared.
|
||||
local retired = false
|
||||
for _, entry in ipairs(Pipelines.list()) do
|
||||
if entry.def.drawWorld and not entry.def.present
|
||||
and Pipelines.level(entry.id) > 0 then
|
||||
Pipelines.setLevel(entry.id, 0)
|
||||
retired = true
|
||||
end
|
||||
end
|
||||
if retired then
|
||||
require("src.render.Tilt").applyOptions(self.options)
|
||||
end
|
||||
-- Both halves run on Gold now: `present` folds over the composite in
|
||||
-- Game2:draw, `drawWorld` owns the world pass in World:drawPipeline. So a
|
||||
-- restored world level stays switched on, as it does for Gen 1.
|
||||
|
||||
-- After the merge, so a font override and a translation mod's catalog
|
||||
-- (#501) are both in Data before the first screen draws a glyph. Gen 1
|
||||
@@ -1112,19 +1094,20 @@ function Game2:update(dt)
|
||||
-- reason and at the same place Gen 1 ticks them (src/core/Game.lua:265):
|
||||
-- they are presentational, so fast-forward must not speed them up.
|
||||
require("src.render.Pipelines").update(dt)
|
||||
if self.phase == "boot" then
|
||||
FixedStep.maxAccum = 0.25
|
||||
FixedStep:update(dt)
|
||||
return
|
||||
end
|
||||
if not self.world or not self.world.map then return end
|
||||
-- GAME SPEED scales the logic clock only, exactly as the Gen 1 path does:
|
||||
-- audio runs off its own real-time accumulator, so music and sfx keep their
|
||||
-- tempo at every multiplier. speedOverride is the driver/CLI hook and wins
|
||||
-- over the saved option.
|
||||
-- pokegold engine/menus/intro_menu.asm:848 IntroSequence: boot cinema runs on the same clock as the overworld
|
||||
local speed = math.max(1,
|
||||
tonumber(self.speedOverride) or tonumber(self.options and self.options.speed)
|
||||
or 1)
|
||||
if self.phase == "boot" then
|
||||
FixedStep.maxAccum = math.max(0.25, speed / 60 + 0.05)
|
||||
FixedStep:update(dt * speed)
|
||||
return
|
||||
end
|
||||
if not self.world or not self.world.map then return end
|
||||
FixedStep.maxAccum = math.max(0.25, speed / 60 + 0.05)
|
||||
FixedStep:update(dt * speed)
|
||||
end
|
||||
@@ -1921,6 +1904,8 @@ function Game2:applyOptions()
|
||||
-- the mod pipeline ladder rides options.pipelines and restores with the rest
|
||||
-- of the display block, as it does in src/core/Game.lua:1041
|
||||
require("src.render.Pipelines").applyOptions(options)
|
||||
-- src/core/Game.lua:1121 mirrors this call for Gen 1
|
||||
Input:applyBindings(options.bindings)
|
||||
-- options.touchControls (the launcher editor's per-orientation layouts) and
|
||||
-- options.haptics, the same two keys Gen 1 hands over here
|
||||
-- (src/core/Game.lua:1073). One options.lua serves both games, so the pad a
|
||||
|
||||
@@ -460,6 +460,8 @@ end
|
||||
function Music.applyOptions(opts)
|
||||
Music.setVolumeLevel(opts and opts.musicVol or 7)
|
||||
Music.setFilterLevel(opts and opts.musicFilter or 0)
|
||||
-- engine/menus/options_menu.asm SOUND row (wOptions STEREO bit)
|
||||
require("src.core.ChipAudio").setStereo(opts and opts.sound == "STEREO")
|
||||
end
|
||||
|
||||
local function sourceStopped(src)
|
||||
|
||||
@@ -53,6 +53,9 @@ local function handle(cmd)
|
||||
if cmd.channelPitches ~= nil then
|
||||
ChipSynth.setChannelPitches(cmd.channelPitches)
|
||||
end
|
||||
if cmd.stereo ~= nil then
|
||||
ChipSynth.setStereo(cmd.stereo)
|
||||
end
|
||||
local ok, eng = pcall(ChipSynth.newEngine, data, cmd.header,
|
||||
{ allowLoops = cmd.allowLoops })
|
||||
if ok then
|
||||
@@ -69,6 +72,7 @@ local function handle(cmd)
|
||||
elseif cmd.cmd == "channelMix" then
|
||||
if cmd.volumes ~= nil then ChipSynth.setChannelVolumes(cmd.volumes) end
|
||||
if cmd.pitches ~= nil then ChipSynth.setChannelPitches(cmd.pitches) end
|
||||
if cmd.stereo ~= nil then ChipSynth.setStereo(cmd.stereo) end
|
||||
elseif cmd.cmd == "invalidate" then
|
||||
ChipSynth.invalidateBanks()
|
||||
elseif cmd.cmd == "quit" then
|
||||
|
||||
@@ -96,7 +96,7 @@ function Nests.landmark(data, index)
|
||||
end
|
||||
|
||||
local function landmarkOfMap(data, mapId)
|
||||
local def = data and data.maps and data.maps[mapId]
|
||||
local def = data and data.gen2Maps and data.gen2Maps[mapId]
|
||||
return def and def.landmark
|
||||
end
|
||||
|
||||
@@ -131,7 +131,7 @@ function Nests.find(data, species, region, save)
|
||||
out[#out + 1] = landmark
|
||||
end
|
||||
|
||||
local enc = data and data.encounters
|
||||
local enc = data and data.gen2Encounters
|
||||
for _, key in ipairs({ "grass", "water" }) do
|
||||
for mapId, entry in pairs((enc and enc[key]) or {}) do
|
||||
if tableHasSpecies(entry, species) then
|
||||
|
||||
@@ -127,6 +127,9 @@ end
|
||||
Save.filenames = saveNames
|
||||
|
||||
local function fs()
|
||||
-- portable.txt: same standard/portable root as Gen 1 (SaveData.persistenceFs).
|
||||
local ok, SaveData = pcall(require, "src.core.SaveData")
|
||||
if ok and SaveData.persistenceFs then return SaveData.persistenceFs() end
|
||||
return love.filesystem
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user