implement custom base address for GES

This commit is contained in:
2022-04-18 16:40:16 +02:00
parent 6f20d303c8
commit 7a52ce4e4c
6 changed files with 46 additions and 37 deletions

View File

@@ -55,6 +55,7 @@ data 80 {
include "../../platform/src/ges.cwa" include "../../platform/src/ges.cwa"
import "env.pow" fn pow(f32, f32) -> f32; import "env.pow" fn pow(f32, f32) -> f32;
import "env.exp" fn exp(f32) -> f32;
import "env.sin" fn sin(f32) -> f32; import "env.sin" fn sin(f32) -> f32;
export fn snd(t: i32) -> f32 { export fn snd(t: i32) -> f32 {

Binary file not shown.

View File

@@ -7,21 +7,22 @@ const GesChannelState.Size = 8;
const GesState.Filter = GesChannelState.Size * 4; const GesState.Filter = GesChannelState.Size * 4;
const GesState.Size = GesState.Filter + 8*4; const GesState.Size = GesState.Filter + 8*4;
const GesStateOffset = 112; const GesStateOffset = 32;
const GesBufferOffset = 112 + GesState.Size; const GesBufferOffset = 32 + GesState.Size;
export fn gesSnd(t: i32) -> f32 { export fn gesSnd(t: i32) -> f32 {
let baseAddr = 0!0x12c78;
if !(t & 127) { if !(t & 127) {
let i: i32; let i: i32;
loop clearLoop { loop clearLoop {
i!GesBufferOffset = 0; (baseAddr + i)!GesBufferOffset = 0;
branch_if (i := i + 4) < 128*8: clearLoop; branch_if (i := i + 4) < 128*8: clearLoop;
} }
let ch: i32; let ch: i32;
loop channelLoop { loop channelLoop {
let lazy channelState = GesStateOffset + ch * GesChannelState.Size; let lazy channelState = baseAddr + GesStateOffset + ch * GesChannelState.Size;
let lazy channelReg = 80 + ch * 6; let lazy channelReg = baseAddr + ch * 6;
let envState = channelState?GesChannelState.EnvState; let envState = channelState?GesChannelState.EnvState;
let envVol = i32.load16_u(channelState, GesChannelState.EnvVol); let envVol = i32.load16_u(channelState, GesChannelState.EnvVol);
@@ -77,7 +78,7 @@ export fn gesSnd(t: i32) -> f32 {
let saw2 = saw2 - let saw2 = saw2 -
polyBlep((p - pulsePhase1) >> 16, invPhaseInc, -saw) - polyBlep((p - pulsePhase1) >> 16, invPhaseInc, -saw) -
polyBlep((p - pulsePhase2) >> 16, invPhaseInc, saw); polyBlep((p - pulsePhase2) >> 16, invPhaseInc, saw);
i!(GesBufferOffset + 128*4) = saw2; (baseAddr + i)!(GesBufferOffset + 128*4) = saw2;
phase = phase + phaseInc; phase = phase + phaseInc;
branch_if (i := i + 4) < 64*4: sawLoop; branch_if (i := i + 4) < 64*4: sawLoop;
} }
@@ -86,7 +87,7 @@ export fn gesSnd(t: i32) -> f32 {
{ {
let pulsePhase = 32768 + pulseWidth * 128; let pulsePhase = 32768 + pulseWidth * 128;
loop rectLoop { loop rectLoop {
i!(GesBufferOffset + 128*4) = select((phase & 65535) < pulsePhase, -32768, 32767) - (baseAddr + i)!(GesBufferOffset + 128*4) = select((phase & 65535) < pulsePhase, -32768, 32767) -
polyBlep(phase, invPhaseInc, -32767) - polyBlep(phase, invPhaseInc, -32767) -
polyBlep(phase - pulsePhase, invPhaseInc, 32767); polyBlep(phase - pulsePhase, invPhaseInc, 32767);
phase = phase + phaseInc; phase = phase + phaseInc;
@@ -101,7 +102,7 @@ export fn gesSnd(t: i32) -> f32 {
s = (s ^ (s >> 31)); s = (s ^ (s >> 31));
s = (s >> 8) * scale; s = (s >> 8) * scale;
s = (s ^ (s >> 31)); s = (s ^ (s >> 31));
i!(GesBufferOffset + 128*4) = (s >> 15) - 32768; (baseAddr + i)!(GesBufferOffset + 128*4) = (s >> 15) - 32768;
phase = phase + phaseInc; phase = phase + phaseInc;
branch_if (i := i + 4) < 64*4: triLoop; branch_if (i := i + 4) < 64*4: triLoop;
} }
@@ -111,7 +112,7 @@ export fn gesSnd(t: i32) -> f32 {
let inline pulse = ((phase >> 8) & 255) >= pulseWidth; let inline pulse = ((phase >> 8) & 255) >= pulseWidth;
s = s * 0x6746ba73; s = s * 0x6746ba73;
s = s ^ (s >> 15) * pulse; s = s ^ (s >> 15) * pulse;
i!(GesBufferOffset + 128*4) = (s * 0x835776c7) >> 16; (baseAddr + i)!(GesBufferOffset + 128*4) = (s * 0x835776c7) >> 16;
phase = phase + phaseInc; phase = phase + phaseInc;
branch_if (i := i + 4) < 64*4: noiseLoop; branch_if (i := i + 4) < 64*4: noiseLoop;
} }
@@ -122,8 +123,8 @@ export fn gesSnd(t: i32) -> f32 {
if ctrl & 32 { if ctrl & 32 {
let lazy modSrc = (ch - 1) & 3; let lazy modSrc = (ch - 1) & 3;
let inline channelState = GesStateOffset + modSrc * GesChannelState.Size; let inline channelState = baseAddr + GesStateOffset + modSrc * GesChannelState.Size;
let inline channelReg = 80 + modSrc * 6; let inline channelReg = baseAddr + modSrc * 6;
let inline note = i32.load16_u(channelReg, 2); let inline note = i32.load16_u(channelReg, 2);
let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32); let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32);
@@ -138,13 +139,13 @@ export fn gesSnd(t: i32) -> f32 {
loop ringLoop { loop ringLoop {
let s = phase << 16; let s = phase << 16;
s = (s ^ (s >> 31)); s = (s ^ (s >> 31));
i!(GesBufferOffset + 128*4) = (i!(GesBufferOffset + 128*4) * ((s >> 15) - 32768)) >> 15; (baseAddr + i)!(GesBufferOffset + 128*4) = ((baseAddr + i)!(GesBufferOffset + 128*4) * ((s >> 15) - 32768)) >> 15;
phase = phase + phaseInc; phase = phase + phaseInc;
branch_if (i := i + 4) < 64*4: ringLoop; branch_if (i := i + 4) < 64*4: ringLoop;
} }
} }
let channelVol = ((ch >> 1)?0x68 >> ((ch & 1) * 4)) & 15; let channelVol = ((baseAddr + (ch >> 1))?24 >> ((ch & 1) * 4)) & 15;
envVol = envVol * channelVol / 15; envVol = envVol * channelVol / 15;
let leftVol = (select(ctrl & 16, 0x3d5b, 0x6a79) >> (ch * 4)) & 15; let leftVol = (select(ctrl & 16, 0x3d5b, 0x6a79) >> (ch * 4)) & 15;
@@ -156,30 +157,30 @@ export fn gesSnd(t: i32) -> f32 {
if filter < 2 { if filter < 2 {
if filter { if filter {
let f = (4096 as f32 - min(4096 as f32, 4096 as f32 * exp(freq * (-8.0 * 3.141 / 44100.0)))) as i32; let f = (4096 as f32 - min(4096 as f32, 4096 as f32 * exp(freq * (-8.0 * 3.141 / 44100.0)))) as i32;
let low = (ch * 8)!(GesStateOffset + GesState.Filter); let low = (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter);
loop filterLoop { loop filterLoop {
let in = (i!(GesBufferOffset + 128*4) * envVol) >> 18; let in = ((baseAddr + i)!(GesBufferOffset + 128*4) * envVol) >> 18;
low = low + (((in - low) * f) >> 12); low = low + (((in - low) * f) >> 12);
(i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((low * leftVol) >> 4); (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((low * leftVol) >> 4);
(i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((low * rightVol) >> 4); (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((low * rightVol) >> 4);
branch_if (i := i + 4) < 64*4: filterLoop; branch_if (i := i + 4) < 64*4: filterLoop;
(ch * 8)!(GesStateOffset + GesState.Filter) = low; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = low;
(ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0;
} }
} else { } else {
loop mixLoop { loop mixLoop {
let sample = (i!(GesBufferOffset + 128*4) * envVol) >> 18; let sample = ((baseAddr + i)!(GesBufferOffset + 128*4) * envVol) >> 18;
(i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((sample * leftVol) >> 4);
(i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4);
branch_if (i := i + 4) < 64*4: mixLoop; branch_if (i := i + 4) < 64*4: mixLoop;
(ch * 8)!(GesStateOffset + GesState.Filter) = sample; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = sample;
(ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0;
} }
} }
} else { } else {
filter = filter - 2; filter = filter - 2;
let ctrl = filter?0x6a; let ctrl = (baseAddr + filter)?26;
let note = i32.load16_u(filter * 2, 0x6c); let note = i32.load16_u(baseAddr + filter * 2, 28);
let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32); let inline freq = 440 as f32 * pow(2.0, (note - 69*256) as f32 / (12*256) as f32);
let F = (8192 as f32 * sin(min(0.25, freq / 44100 as f32) * 3.1415)) as i32; let F = (8192 as f32 * sin(min(0.25, freq / 44100 as f32) * 3.1415)) as i32;
let Q = 8192 - (ctrl >> 4) * (7000/15); let Q = 8192 - (ctrl >> 4) * (7000/15);
@@ -190,28 +191,28 @@ export fn gesSnd(t: i32) -> f32 {
let low_out = ctrl & 1; let low_out = ctrl & 1;
let high_out = (ctrl >> 1) & 1; let high_out = (ctrl >> 1) & 1;
let band_out = (ctrl >> 2) & 1; let band_out = (ctrl >> 2) & 1;
let low = (ch * 8)!(GesStateOffset + GesState.Filter); let low = (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter);
let band = (ch * 8)!(GesStateOffset + GesState.Filter + 4); let band = (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4);
loop filterLoop { loop filterLoop {
let in = (i!(GesBufferOffset + 128*4) * envVol) >> 18; let in = ((baseAddr + i)!(GesBufferOffset + 128*4) * envVol) >> 18;
let high = in - low - ((band * Q) >> 12); let high = in - low - ((band * Q) >> 12);
band = band + ((F * high) >> 12); band = band + ((F * high) >> 12);
low = low + ((F * band) >> 12); low = low + ((F * band) >> 12);
let sample = low * low_out + high * high_out + band * band_out; let sample = low * low_out + high * high_out + band * band_out;
(i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((sample * leftVol) >> 4);
(i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4);
branch_if (i := i + 4) < 64*4: filterLoop; branch_if (i := i + 4) < 64*4: filterLoop;
(ch * 8)!(GesStateOffset + GesState.Filter) = low; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = low;
(ch * 8)!(GesStateOffset + GesState.Filter + 4) = band; (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = band;
} }
} }
branch_if (ch := ch + 1) < 4: channelLoop; branch_if (ch := ch + 1) < 4: channelLoop;
} }
} }
(((t & 127) * 4)!GesBufferOffset) as f32 / 32768 as f32 ((baseAddr + (t & 127) * 4)!GesBufferOffset) as f32 / 32768 as f32
} }
fn polyBlep(transientPhase: i32, invPhaseInc: f32, magnitude: i32) -> i32 { fn polyBlep(transientPhase: i32, invPhaseInc: f32, magnitude: i32) -> i32 {

View File

@@ -576,6 +576,10 @@ data 80 {
) )
} }
data 0x12c78 {
i32(80)
}
data 0x13000+192*4 { data 0x13000+192*4 {
i32( i32(
0x2c1c1a, 0x2c1c1a,

View File

@@ -19,10 +19,13 @@ The memory has to be imported as `env` `memory` and has a maximum size of 256kb
00040-00044: time since module start in ms 00040-00044: time since module start in ms
00044-0004c: gamepad state 00044-0004c: gamepad state
0004c-00050: reserved 0004c-00050: reserved
00050-00070: sound registers 00050-00070: sound data (synced to sound thread)
00070-00078: reserved 00070-00078: reserved
00078-12c78: frame buffer 00078-12c78: frame buffer
12c78-13000: reserved 12c78-12c7c: sound registers/work area base address (for sndGes function)
12c7c-12c80: reserved
12c80-12ca0: sound data (synced from sound thread)
12ca0-13000: reserved
13000-13400: palette 13000-13400: palette
13400-13c00: font 13400-13c00: font
13c00-14000: reserved 13c00-14000: reserved

File diff suppressed because one or more lines are too long