diff --git a/examples/curlywas/tim_ges.cwa b/examples/curlywas/tim_ges.cwa index c8a9e0e..d44ada8 100644 --- a/examples/curlywas/tim_ges.cwa +++ b/examples/curlywas/tim_ges.cwa @@ -55,6 +55,7 @@ data 80 { include "../../platform/src/ges.cwa" import "env.pow" fn pow(f32, f32) -> f32; +import "env.exp" fn exp(f32) -> f32; import "env.sin" fn sin(f32) -> f32; export fn snd(t: i32) -> f32 { diff --git a/platform/bin/platform.uw8 b/platform/bin/platform.uw8 index 1d57bdc..ed7a546 100644 Binary files a/platform/bin/platform.uw8 and b/platform/bin/platform.uw8 differ diff --git a/platform/src/ges.cwa b/platform/src/ges.cwa index b10f362..dc97114 100644 --- a/platform/src/ges.cwa +++ b/platform/src/ges.cwa @@ -7,21 +7,22 @@ const GesChannelState.Size = 8; const GesState.Filter = GesChannelState.Size * 4; const GesState.Size = GesState.Filter + 8*4; -const GesStateOffset = 112; -const GesBufferOffset = 112 + GesState.Size; +const GesStateOffset = 32; +const GesBufferOffset = 32 + GesState.Size; export fn gesSnd(t: i32) -> f32 { + let baseAddr = 0!0x12c78; if !(t & 127) { let i: i32; loop clearLoop { - i!GesBufferOffset = 0; + (baseAddr + i)!GesBufferOffset = 0; branch_if (i := i + 4) < 128*8: clearLoop; } let ch: i32; loop channelLoop { - let lazy channelState = GesStateOffset + ch * GesChannelState.Size; - let lazy channelReg = 80 + ch * 6; + let lazy channelState = baseAddr + GesStateOffset + ch * GesChannelState.Size; + let lazy channelReg = baseAddr + ch * 6; let envState = channelState?GesChannelState.EnvState; let envVol = i32.load16_u(channelState, GesChannelState.EnvVol); @@ -77,7 +78,7 @@ export fn gesSnd(t: i32) -> f32 { let saw2 = saw2 - polyBlep((p - pulsePhase1) >> 16, invPhaseInc, -saw) - polyBlep((p - pulsePhase2) >> 16, invPhaseInc, saw); - i!(GesBufferOffset + 128*4) = saw2; + (baseAddr + i)!(GesBufferOffset + 128*4) = saw2; phase = phase + phaseInc; branch_if (i := i + 4) < 64*4: sawLoop; } @@ -86,7 +87,7 @@ export fn gesSnd(t: i32) -> f32 { { let pulsePhase = 32768 + pulseWidth * 128; 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 - pulsePhase, invPhaseInc, 32767); phase = phase + phaseInc; @@ -101,7 +102,7 @@ export fn gesSnd(t: i32) -> f32 { s = (s ^ (s >> 31)); s = (s >> 8) * scale; s = (s ^ (s >> 31)); - i!(GesBufferOffset + 128*4) = (s >> 15) - 32768; + (baseAddr + i)!(GesBufferOffset + 128*4) = (s >> 15) - 32768; phase = phase + phaseInc; 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; s = s * 0x6746ba73; s = s ^ (s >> 15) * pulse; - i!(GesBufferOffset + 128*4) = (s * 0x835776c7) >> 16; + (baseAddr + i)!(GesBufferOffset + 128*4) = (s * 0x835776c7) >> 16; phase = phase + phaseInc; branch_if (i := i + 4) < 64*4: noiseLoop; } @@ -122,8 +123,8 @@ export fn gesSnd(t: i32) -> f32 { if ctrl & 32 { let lazy modSrc = (ch - 1) & 3; - let inline channelState = GesStateOffset + modSrc * GesChannelState.Size; - let inline channelReg = 80 + modSrc * 6; + let inline channelState = baseAddr + GesStateOffset + modSrc * GesChannelState.Size; + let inline channelReg = baseAddr + modSrc * 6; 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); @@ -138,13 +139,13 @@ export fn gesSnd(t: i32) -> f32 { loop ringLoop { let s = phase << 16; 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; 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; 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 { 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 { - let in = (i!(GesBufferOffset + 128*4) * envVol) >> 18; + let in = ((baseAddr + i)!(GesBufferOffset + 128*4) * envVol) >> 18; low = low + (((in - low) * f) >> 12); - (i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((low * leftVol) >> 4); - (i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((low * rightVol) >> 4); + (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((low * leftVol) >> 4); + (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((low * rightVol) >> 4); branch_if (i := i + 4) < 64*4: filterLoop; - (ch * 8)!(GesStateOffset + GesState.Filter) = low; - (ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = low; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; } } else { loop mixLoop { - let sample = (i!(GesBufferOffset + 128*4) * envVol) >> 18; - (i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); - (i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); + let sample = ((baseAddr + i)!(GesBufferOffset + 128*4) * envVol) >> 18; + (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); + (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); branch_if (i := i + 4) < 64*4: mixLoop; - (ch * 8)!(GesStateOffset + GesState.Filter) = sample; - (ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = sample; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = 0; } } } else { filter = filter - 2; - let ctrl = filter?0x6a; - let note = i32.load16_u(filter * 2, 0x6c); + let ctrl = (baseAddr + filter)?26; + 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 F = (8192 as f32 * sin(min(0.25, freq / 44100 as f32) * 3.1415)) as i32; let Q = 8192 - (ctrl >> 4) * (7000/15); @@ -190,28 +191,28 @@ export fn gesSnd(t: i32) -> f32 { let low_out = ctrl & 1; let high_out = (ctrl >> 1) & 1; let band_out = (ctrl >> 2) & 1; - let low = (ch * 8)!(GesStateOffset + GesState.Filter); - let band = (ch * 8)!(GesStateOffset + GesState.Filter + 4); + let low = (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter); + let band = (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4); 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); band = band + ((F * high) >> 12); low = low + ((F * band) >> 12); let sample = low * low_out + high * high_out + band * band_out; - (i * 2)!GesBufferOffset = (i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); - (i * 2)!(GesBufferOffset + 4) = (i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); + (baseAddr + i * 2)!GesBufferOffset = (baseAddr + i * 2)!GesBufferOffset + ((sample * leftVol) >> 4); + (baseAddr + i * 2)!(GesBufferOffset + 4) = (baseAddr + i * 2)!(GesBufferOffset + 4) + ((sample * rightVol) >> 4); branch_if (i := i + 4) < 64*4: filterLoop; - (ch * 8)!(GesStateOffset + GesState.Filter) = low; - (ch * 8)!(GesStateOffset + GesState.Filter + 4) = band; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter) = low; + (baseAddr + ch * 8)!(GesStateOffset + GesState.Filter + 4) = band; } } 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 { diff --git a/platform/src/platform.cwa b/platform/src/platform.cwa index 9b14afe..69e683e 100644 --- a/platform/src/platform.cwa +++ b/platform/src/platform.cwa @@ -576,6 +576,10 @@ data 80 { ) } +data 0x12c78 { + i32(80) +} + data 0x13000+192*4 { i32( 0x2c1c1a, diff --git a/site/content/docs.md b/site/content/docs.md index fdd3df0..f2cbec0 100644 --- a/site/content/docs.md +++ b/site/content/docs.md @@ -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 00044-0004c: gamepad state 0004c-00050: reserved -00050-00070: sound registers +00050-00070: sound data (synced to sound thread) 00070-00078: reserved 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 13400-13c00: font 13c00-14000: reserved diff --git a/src/run-web.html b/src/run-web.html index c8c4956..2a07e98 100644 --- a/src/run-web.html +++ b/src/run-web.html @@ -1 +1 @@ -