From e434b96ec2fe32acd10a7d38e9535e851b71f8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20J=C3=A4rvisalo?= Date: Thu, 23 May 2024 19:38:02 +0300 Subject: [PATCH] Initial commit --- .gitignore | 4 + 4kdemo.compofiller | 21 + 4klang.asm | 1758 +++++++++++++++++++++++++++++++ 4klang.h | 22 + 4klang.inc | 621 +++++++++++ BuildDLLs.script | 55 + BuildEXE.script | 31 + MinifyShader.script | 20 + RunEXE.script | 11 + base.config | 71 ++ common.script | 108 ++ debug_4klang_wrapper.asm | 35 + debug_audio.asm | 426 ++++++++ debug_audio.dll | Bin 0 -> 40168 bytes debug_visuals.asm | 1519 ++++++++++++++++++++++++++ debug_visuals.dll | Bin 0 -> 34572 bytes errormsg.inc | 210 ++++ exemain.asm | 944 +++++++++++++++++ final.config | 13 + glconstants.inc | 9 + map_features_to_use_defines.inc | 66 ++ minified.config | 11 + prod.nfo | 7 + shader.glsl | 314 ++++++ shader_code.asm | 16 + timings_and_texts.inc | 71 ++ winconstants.inc | 18 + 27 files changed, 6381 insertions(+) create mode 100644 .gitignore create mode 100644 4kdemo.compofiller create mode 100644 4klang.asm create mode 100644 4klang.h create mode 100644 4klang.inc create mode 100644 BuildDLLs.script create mode 100644 BuildEXE.script create mode 100644 MinifyShader.script create mode 100644 RunEXE.script create mode 100644 base.config create mode 100644 common.script create mode 100644 debug_4klang_wrapper.asm create mode 100644 debug_audio.asm create mode 100644 debug_audio.dll create mode 100644 debug_visuals.asm create mode 100644 debug_visuals.dll create mode 100644 errormsg.inc create mode 100644 exemain.asm create mode 100644 final.config create mode 100644 glconstants.inc create mode 100644 map_features_to_use_defines.inc create mode 100644 minified.config create mode 100644 prod.nfo create mode 100644 shader.glsl create mode 100644 shader_code.asm create mode 100644 timings_and_texts.inc create mode 100644 winconstants.inc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3905687 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.obj +*.exe +*.html +__temp*.* \ No newline at end of file diff --git a/4kdemo.compofiller b/4kdemo.compofiller new file mode 100644 index 0000000..a1db361 --- /dev/null +++ b/4kdemo.compofiller @@ -0,0 +1,21 @@ +# Compofiller Studio project file + +PROJECT_NAME=MyProject + +PROJECT_INFO_FILE=prod.nfo +PROJECT_SCREENSHOT= + +# Currently active config file name +ACTIVE_CONFIG=base.config + +# ------- GUI options/preferences -------- +# Automatically rebuild DLLs when things have changed? +AUTOREBUILD_DLLS=1 + +# Keep the previous audio buffer when rebuilding DLLs, allocating a new fresh buffer? +# Even if the previous audio is kept, a new audio rendering thread is started. +KEEP_AUDIO=1 + + +# ------ Timings and texts editor options/preferences ------ +AUTO_LOCATE_TO_ACTIVE_TEXT=1 diff --git a/4klang.asm b/4klang.asm new file mode 100644 index 0000000..abf9cc1 --- /dev/null +++ b/4klang.asm @@ -0,0 +1,1758 @@ +bits 32 + +%define WRK ebp ; // alias for unit workspace +%define VAL esi ; // alias for unit values (transformed/untransformed) +%define COM ebx ; // alias for instrument opcodes + +%include "4klang.inc" + +;// conditional defines + +%ifdef GO4K_USE_VCO_SHAPE + %define INCLUDE_WAVESHAPER +%endif +%ifdef GO4K_USE_DST + %define INCLUDE_WAVESHAPER +%endif + +%ifdef GO4K_USE_VCO_MOD_PM + %define PHASE_RENORMALIZE +%endif +%ifdef GO4K_USE_VCO_PHASE_OFFSET + %define PHASE_RENORMALIZE +%endif + +%ifdef GO4K_USE_ENVELOPE_RECORDINGS + %define GO4K_USE_BUFFER_RECORDINGS +%endif +%ifdef GO4K_USE_NOTE_RECORDINGS + %define GO4K_USE_BUFFER_RECORDINGS +%endif + +; //======================================================================================== +; // .bss section +; //======================================================================================== +%ifdef USE_SECTIONS +section .g4kbss1 bss align=1 +%else +section .bss +%endif + +; // the one and only synth object +%if MAX_VOICES > 1 +go4k_voiceindex resd 16 +%endif +go4k_transformed_values resd 16 +go4k_synth_wrk resb go4k_synth.size +global _go4k_delay_buffer_ofs +_go4k_delay_buffer_ofs resd 1 +global _go4k_delay_buffer +_go4k_delay_buffer resd 16*16*go4kDLL_wrk.size + +%ifdef AUTHORING +global __4klang_current_tick +__4klang_current_tick resd 0 +%endif + +%ifdef GO4K_USE_ENVELOPE_RECORDINGS +global __4klang_envelope_buffer +__4klang_envelope_buffer resd ((MAX_SAMPLES)/8) ; // samples every 256 samples and stores 16*2 = 32 values +%endif +%ifdef GO4K_USE_NOTE_RECORDINGS +global __4klang_note_buffer +__4klang_note_buffer resd ((MAX_SAMPLES)/8) ; // samples every 256 samples and stores 16*2 = 32 values +%endif + +; //======================================================================================== +; // .g4kdat section (initialized data for go4k) +; //======================================================================================== +%ifdef USE_SECTIONS +section .g4kdat1 data align=1 +%else +section .data +%endif + +; // some synth constants +go4k_synth_commands dd 0 + dd _go4kENV_func@0 + dd _go4kVCO_func@0 + dd _go4kVCF_func@0 + dd _go4kDST_func@0 + dd _go4kDLL_func@0 + dd _go4kFOP_func@0 + dd _go4kFST_func@0 + dd _go4kPAN_func@0 + dd _go4kOUT_func@0 + dd _go4kACC_func@0 + dd _go4kFLD_func@0 +%ifdef GO4K_USE_GLITCH + dd _go4kGLITCH_func@0 +%else + dd _go4kFLD_func@0 +%endif +%ifdef GO4K_USE_FSTG + dd _go4kFSTG_func@0 +%endif + +%ifdef USE_SECTIONS +section .g4kdat2 data align=1 +%else +section .data +%endif + +%ifdef GO4K_USE_16BIT_OUTPUT +c_32767 dd 32767.0 +%endif +c_i128 dd 0.0078125 +c_RandDiv dd 65536*32768 +c_0_5 dd 0.5 +%ifdef GO4K_USE_VCO_GATE +c_16 dd 16.0 +%endif +%ifdef GO4K_USE_DLL_CHORUS +DLL_DEPTH dd 1024.0 +%endif +%ifdef GO4K_USE_DLL_DC_FILTER +c_dc_const dd 0.99609375 ; R = 1 - (pi*2 * frequency /samplerate) +%else + %ifdef GO4K_USE_VCO_GATE +c_dc_const dd 0.99609375 ; R = 1 - (pi*2 * frequency /samplerate) + %endif +%endif +global _RandSeed +_RandSeed dd 1 +c_24 dd 24 +c_i12 dd 0x3DAAAAAA +FREQ_NORMALIZE dd 0.000092696138 ; // 220.0/(2^(69/12)) / 44100.0 +global _LFO_NORMALIZE +_LFO_NORMALIZE dd DEF_LFO_NORMALIZE +%ifdef GO4K_USE_GROOVE_PATTERN +go4k_groove_pattern dw 0011100111001110b +%endif + +; //======================================================================================== +; // .crtemui section (emulates crt functions) +; //======================================================================================== +%ifdef USE_SECTIONS +section .crtemui code align=1 +%else +section .text +%endif + +export_func FloatRandomNumber@0 + push eax + imul eax,dword [_RandSeed],16007 + mov dword [_RandSeed], eax + fild dword [_RandSeed] + fidiv dword [c_RandDiv] + pop eax + ret + +; //======================================================================================== +; // .g4kcod* sections (code for go4k) +; //======================================================================================== + +%ifdef INCLUDE_WAVESHAPER + +%ifdef USE_SECTIONS +section .g4kcod2 code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // Waveshaper function +; //---------------------------------------------------------------------------------------- +; // Input : st0 : shaping coeff +; // st1 : input +; // Output: st0 : result +; //---------------------------------------------------------------------------------------- + +go4kWaveshaper: +%ifdef GO4K_USE_WAVESHAPER_CLIP + fxch + fld1 ; // 1 val + fucomi st1 ; // 1 val + jbe short go4kWaveshaper_clip + fchs ; // -1 val + fucomi st1 ; // -1 val + fcmovb st0, st1 ; // val -1 (if val > -1) +go4kWaveshaper_clip: + fstp st1 ; // newval + fxch +%endif + fsub dword [c_0_5] + fadd st0 + fst dword [esp-4] ; // amnt in + fadd st0 ; // 2*amnt in + fld1 ; // 1 2*amnt in + fsub dword [esp-4] ; // 1-amnt 2*amnt in + fdivp st1, st0 ; // k in + fld st1 ; // sin k in + fabs ; // a(in) k in + fmul st1 ; // k*a(in) k in + fld1 + faddp st1, st0 ; // 1+k*a(in) k in + fxch st1 ; // k 1+k*a(in) in + fld1 + faddp st1, st0 ; // 1+k 1+k*a(in) in + fmulp st2 ; // 1+k*a(in) (1+k)*in + fdivp st1, st0 ; // out + ret + +%endif + +%ifdef USE_SECTIONS +section .g4kcod3 code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // unit values preparation/transform +; //---------------------------------------------------------------------------------------- +go4kTransformValues: + push ecx + xor ecx, ecx + xor eax, eax + mov edx, go4k_transformed_values +go4kTransformValues_loop: + lodsb + push eax + fild dword [esp] + fmul dword [c_i128] + fstp dword [edx+ecx*4] + pop eax + inc ecx + cmp ecx, dword [esp+8] + jl go4kTransformValues_loop + pop ecx + ret 4 + +%ifdef USE_SECTIONS +section .g4kcod4 code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // Envelope param mapping +; //---------------------------------------------------------------------------------------- +go4kENVMap: + fld dword [edx+eax*4] +%ifdef GO4K_USE_ENV_MOD_ADR + fadd dword [WRK+go4kENV_wrk.am+eax*4] +%endif + fimul dword [c_24] + fchs +; //---------------------------------------------------------------------------------------- +; // Power function (2^x) +; //---------------------------------------------------------------------------------------- +; // Input : st0 : base +; // st1 : exponent +; // Output: st0 : result +; //---------------------------------------------------------------------------------------- +export_func Power@0 ; // base exp + fld1 + fadd st0 + fyl2x ; // log2_base + fld1 ; // 1 log2_base + fld st1 ; // log2_base 1 log2_base + fprem ; // (frac)log2_base 1 log2_base + f2xm1 ; // 2 ^ '' - 1 1 log2_base + faddp st1, st0 ; // 2 ^ '' (int)log2_base + fscale + fstp st1 + ret + +%ifdef USE_SECTIONS +section .g4kcoda code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // ENV Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kENV_func@0 + push 5 + call go4kTransformValues +%ifdef GO4K_USE_ENV_CHECK +; check if current note still active + mov eax, dword [ecx-4] + test eax, eax + jne go4kENV_func_do + fldz + ret +%endif +go4kENV_func_do: + mov eax, dword [ecx-8] ; // is the instrument in release mode (note off)? + test eax, eax + je go4kENV_func_process + mov dword [WRK+go4kENV_wrk.state], ENV_STATE_RELEASE +go4kENV_func_process: + mov eax, dword [WRK+go4kENV_wrk.state] + fld dword [WRK+go4kENV_wrk.level] ; // val - +; // check for sustain state + cmp al, ENV_STATE_SUSTAIN + je short go4kENV_func_leave2 +go4kENV_func_attac: + cmp al, ENV_STATE_ATTAC + jne short go4kENV_func_decay + call go4kENVMap ; // newval + faddp st1, st0 +; // check for end of attac + fld1 ; // 1 newval + fucomi st1 ; // 1 newval + fcmovnb st0, st1 ; // newval 1 (if newval < 1) + jbe short go4kENV_func_statechange +go4kENV_func_decay: + cmp al, ENV_STATE_DECAY + jne short go4kENV_func_release + call go4kENVMap ; // newval + fsubp st1, st0 +; // check for end of decay + fld dword [edx+go4kENV_val.sustain] ; // sustain newval + fucomi st1 ; // sustain newval + fcmovb st0, st1 ; // newval sustain (if newval > sustain) + jnc short go4kENV_func_statechange +go4kENV_func_release: +; // release state? + cmp al, ENV_STATE_RELEASE + jne short go4kENV_func_leave + call go4kENVMap ; // newval + fsubp st1, st0 +; // check for end of release + fldz ; // 0 newval + fucomi st1 ; // 0 newval + fcmovb st0, st1 ; // newval 0 (if newval > 0) + jc short go4kENV_func_leave +go4kENV_func_statechange: ; // newval + inc dword [WRK+go4kENV_wrk.state] +go4kENV_func_leave: ; // newval bla + fstp st1 +; // store new env value + fst dword [WRK+go4kENV_wrk.level] +go4kENV_func_leave2: +; // mul by gain +%ifdef GO4K_USE_ENV_MOD_GM + fld dword [edx+go4kENV_val.gain] + fadd dword [WRK+go4kENV_wrk.gm] + fmulp st1, st0 +%else + fmul dword [edx+go4kENV_val.gain] +%endif + ret + + +; //---------------------------------------------------------------------------------------- +; // VCO Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +%ifdef USE_SECTIONS +section .g4kcodp code align=1 +%else +section .text +%endif +go4kVCO_pulse: + fucomi st1 ; // c p + fld1 + jnc short go4kVCO_func_pulse_up ; // +1 c p + fchs ; // -1 c p +go4kVCO_func_pulse_up: + fstp st1 ; // +-1 p + fstp st1 ; // +-1 + ret + +%ifdef USE_SECTIONS +section .g4kcodt code align=1 +%else +section .text +%endif +go4kVCO_trisaw: + fucomi st1 ; // c p + jnc short go4kVCO_func_trisaw_up + fld1 ; // 1 c p + fsubr st2, st0 ; // 1 c 1-p + fsubrp st1, st0 ; // 1-c 1-p +go4kVCO_func_trisaw_up: + fdivp st1, st0 ; // tp'/tc + fadd st0 ; // 2*'' + fld1 ; // 1 2*'' + fsubp st1, st0 ; // 2*''-1 + ret + +%ifdef USE_SECTIONS +section .g4kcods code align=1 +%else +section .text +%endif +go4kVCO_sine: + fucomi st1 ; // c p + jnc short go4kVCO_func_sine_do + fstp st1 + fsub st0, st0 ; // 0 + ret +go4kVCO_func_sine_do + fdivp st1, st0 ; // p/c + fldpi ; // pi p + fadd st0 ; // 2*pi p + fmulp st1, st0 ; // 2*pi*p + fsin ; // sin(2*pi*p) + ret + +%ifdef GO4K_USE_VCO_GATE +%ifdef USE_SECTIONS +section .g4kcodq code align=1 +%else +section .text +%endif +go4kVCO_gate: + fxch ; // p c + fstp st1 ; // p + fmul dword [c_16] ; // p' + push eax + push eax + fistp dword [esp] ; // - + fld1 ; // 1 + pop eax + and al, 0xf + bt word [VAL-5],ax + jc go4kVCO_gate_bit + fsub st0, st0 ; // 0 +go4kVCO_gate_bit: + fld dword [WRK+go4kVCO_wrk.cm] ; // f x + fsub st1 ; // f-x x + fmul dword [c_dc_const] ; // c(f-x) x + faddp st1, st0 ; // x' + fst dword [WRK+go4kVCO_wrk.cm] + pop eax + ret +%endif + +%ifdef USE_SECTIONS +section .g4kcodb code align=1 +%else +section .text +%endif +export_func go4kVCO_func@0 +%ifdef GO4K_USE_VCO_PHASE_OFFSET + %ifdef GO4K_USE_VCO_SHAPE + %ifdef GO4K_USE_VCO_GATE + push 8 + %else + push 7 + %endif + %else + %ifdef GO4K_USE_VCO_GATE + push 7 + %else + push 6 + %endif + %endif +%else + %ifdef GO4K_USE_VCO_SHAPE + %ifdef GO4K_USE_VCO_GATE + push 7 + %else + push 6 + %endif + %else + %ifdef GO4K_USE_VCO_GATE + push 6 + %else + push 5 + %endif + %endif +%endif + call go4kTransformValues +%ifdef GO4K_USE_VCO_CHECK +; check if current note still active + mov eax, dword [ecx-4] + test eax, eax + jne go4kVCO_func_do +%ifdef GO4K_USE_VCO_STEREO + movzx eax, byte [VAL-1] ; // get flags and check for stereo + test al, byte VCO_STEREO + jz short go4kVCO_func_nostereoout + fldz +go4kVCO_func_nostereoout: +%endif + fldz + ret +go4kVCO_func_do: +%endif + movzx eax, byte [VAL-1] ; // get flags +%ifdef GO4K_USE_VCO_STEREO + test al, byte VCO_STEREO + jz short go4kVCO_func_nopswap + fld dword [WRK+go4kVCO_wrk.phase] ;// swap left/right phase values for first stereo run + fld dword [WRK+go4kVCO_wrk.phase2] + fstp dword [WRK+go4kVCO_wrk.phase] + fstp dword [WRK+go4kVCO_wrk.phase2] +go4kVCO_func_nopswap: +%endif +go4kVCO_func_process: + fld dword [edx+go4kVCO_val.transpose] + fsub dword [c_0_5] +%ifdef GO4K_USE_VCO_MOD_TM + fadd dword [WRK+go4kVCO_wrk.tm] +%endif + fdiv dword [c_i128] + fld dword [edx+go4kVCO_val.detune] + fsub dword [c_0_5] + fadd st0 +%ifdef GO4K_USE_VCO_STEREO + test al, byte VCO_STEREO + jz short go4kVCO_func_nodswap + fchs ;// negate detune for stereo +go4kVCO_func_nodswap: +%endif + faddp st1 +%ifdef GO4K_USE_VCO_MOD_DM + fadd dword [WRK+go4kVCO_wrk.dm] +%endif + ; // st0 now contains the transpose+detune offset + test al, byte LFO + jnz go4kVCO_func_skipnote + fiadd dword [ecx-4] ; // st0 is note, st1 is t+d offset +go4kVCO_func_skipnote: + fmul dword [c_i12] + call _Power@0 + test al, byte LFO + jz short go4kVCO_func_normalize_note + fmul dword [_LFO_NORMALIZE] ; // st0 is now frequency for lfo + jmp short go4kVCO_func_normalized +go4kVCO_func_normalize_note: + fmul dword [FREQ_NORMALIZE] ; // st0 is now frequency +go4kVCO_func_normalized: + fadd dword [WRK+go4kVCO_wrk.phase] +%ifdef GO4K_USE_VCO_MOD_FM + fadd dword [WRK+go4kVCO_wrk.fm] +%endif + fld1 + fadd st1, st0 + fxch + fprem + fstp st1 + fst dword [WRK+go4kVCO_wrk.phase] +%ifdef GO4K_USE_VCO_MOD_PM + fadd dword [WRK+go4kVCO_wrk.pm] +%endif +%ifdef GO4K_USE_VCO_PHASE_OFFSET + fadd dword [edx+go4kVCO_val.phaseofs] +%endif +%ifdef PHASE_RENORMALIZE + fld1 + fadd st1, st0 + fxch + fprem + fstp st1 ; // p +%endif + fld dword [edx+go4kVCO_val.color] ; // c p +%ifdef GO4K_USE_VCO_MOD_CM + fadd dword [WRK+go4kVCO_wrk.cm] ; // c p +%endif +go4kVCO_func_sine: + test al, byte SINE + jz short go4kVCO_func_trisaw + call go4kVCO_sine +go4kVCO_func_trisaw: + test al, byte TRISAW + jz short go4kVCO_func_pulse + call go4kVCO_trisaw +go4kVCO_func_pulse: + test al, byte PULSE +%ifdef GO4K_USE_VCO_GATE + jz short go4kVCO_func_gate +%else + jz short go4kVCO_func_noise +%endif + call go4kVCO_pulse +%ifdef GO4K_USE_VCO_GATE +go4kVCO_func_gate: + test al, byte GATE + jz short go4kVCO_func_noise + call go4kVCO_gate +%endif +go4kVCO_func_noise: + test al, byte NOISE + jz short go4kVCO_func_end + call _FloatRandomNumber@0 + fstp st1 + fstp st1 +go4kVCO_func_end: +%ifdef GO4K_USE_VCO_SHAPE + fld dword [edx+go4kVCO_val.shape] +%ifdef GO4K_USE_VCO_MOD_SM + fadd dword [WRK+go4kVCO_wrk.sm] +%endif + call go4kWaveshaper +%endif + fld dword [edx+go4kVCO_val.gain] +%ifdef GO4K_USE_VCO_MOD_GM + fadd dword [WRK+go4kVCO_wrk.gm] +%endif + fmulp st1, st0 + +%ifdef GO4K_USE_VCO_STEREO + test al, byte VCO_STEREO + jz short go4kVCO_func_stereodone + sub al, byte VCO_STEREO + fld dword [WRK+go4kVCO_wrk.phase] ;// swap left/right phase values again for second stereo run + fld dword [WRK+go4kVCO_wrk.phase2] + fstp dword [WRK+go4kVCO_wrk.phase] + fstp dword [WRK+go4kVCO_wrk.phase2] + jmp go4kVCO_func_process +go4kVCO_func_stereodone: +%endif + ret + +%ifdef USE_SECTIONS +section .g4kcodc code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // VCF Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kVCF_func@0 + push 3 + call go4kTransformValues +%ifdef GO4K_USE_VCF_CHECK +; check if current note still active + mov eax, dword [ecx-4] + test eax, eax + jne go4kVCF_func_do + ret +go4kVCF_func_do: +%endif + movzx eax, byte [VAL-1] ; // get type flag + + fld dword [edx+go4kVCF_val.res] ; // r in +%ifdef GO4K_USE_VCF_MOD_RM + fadd dword [WRK+go4kVCF_wrk.rm] +%endif + fstp dword [esp-8] + + fld dword [edx+go4kVCF_val.freq] ; // f in +%ifdef GO4K_USE_VCF_MOD_FM + fadd dword [WRK+go4kVCF_wrk.fm] +%endif + fmul st0, st0 ; // square the input so we never get negative and also have a smoother behaviour in the lower frequencies + fstp dword [esp-4] ; // in + +%ifdef GO4K_USE_VCF_STEREO + test al, byte STEREO + jz short go4kVCF_func_process + add WRK, go4kVCF_wrk.low2 +go4kVCF_func_stereoloop: ; // switch channels + fxch st1 ; // inr inl +%endif + +go4kVCF_func_process: + fld dword [esp-8] + fld dword [esp-4] + fmul dword [WRK+go4kVCF_wrk.band] ; // f*b r in + fadd dword [WRK+go4kVCF_wrk.low] ; // l' r in + fst dword [WRK+go4kVCF_wrk.low] ; // l' r in + fsubp st2, st0 ; // r in-l' + fmul dword [WRK+go4kVCF_wrk.band] ; // r*b in-l' + fsubp st1, st0 ; // h' + fst dword [WRK+go4kVCF_wrk.high] ; // h' + fmul dword [esp-4] ; // h'*f + fadd dword [WRK+go4kVCF_wrk.band] ; // b' + fstp dword [WRK+go4kVCF_wrk.band] + fldz +go4kVCF_func_low: + test al, byte LOWPASS + jz short go4kVCF_func_high + fadd dword [WRK+go4kVCF_wrk.low] +go4kVCF_func_high: +%ifdef GO4K_USE_VCF_HIGH + test al, byte HIGHPASS + jz short go4kVCF_func_band + fadd dword [WRK+go4kVCF_wrk.high] +%endif +go4kVCF_func_band: +%ifdef GO4K_USE_VCF_BAND + test al, byte BANDPASS + jz short go4kVCF_func_peak + fadd dword [WRK+go4kVCF_wrk.band] +%endif +go4kVCF_func_peak: +%ifdef GO4K_USE_VCF_PEAK + test al, byte PEAK + jz short go4kVCF_func_processdone + fadd dword [WRK+go4kVCF_wrk.low] + fsub dword [WRK+go4kVCF_wrk.high] +%endif +go4kVCF_func_processdone: + +%ifdef GO4K_USE_VCF_STEREO + test al, byte STEREO ; // outr inl + jz short go4kVCF_func_end + sub al, byte STEREO + sub WRK, go4kVCF_wrk.low2 + jmp go4kVCF_func_stereoloop +%endif + +go4kVCF_func_end: ; // value - - - - + ret + +%ifdef USE_SECTIONS +section .g4kcodd code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // DST Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kDST_func@0 +%ifdef GO4K_USE_DST +%ifdef GO4K_USE_DST_SH + %ifdef GO4K_USE_DST_STEREO + push 3 + %else + push 2 + %endif +%else + %ifdef GO4K_USE_DST_STEREO + push 2 + %else + push 1 + %endif +%endif + call go4kTransformValues +%ifdef GO4K_USE_DST_CHECK +; check if current note still active + mov eax, dword [ecx-4] + test eax, eax + jne go4kDST_func_do + ret +go4kDST_func_do: +%endif + movzx eax, byte [VAL-1] ; // get type flag +%ifdef GO4K_USE_DST_SH + fld dword [edx+go4kDST_val.snhfreq] ; // snh in (inr) +%ifdef GO4K_USE_DST_MOD_SH + fadd dword [WRK+go4kDST_wrk.sm] ; // snh' in (inr) +%endif + fmul st0, st0 ; // square the input so we never get negative and also have a smoother behaviour in the lower frequencies + fchs + fadd dword [WRK+go4kDST_wrk.snhphase]; // snh' in (inr) + fst dword [WRK+go4kDST_wrk.snhphase] + fldz ; // 0 snh' in (inr) + fucomip st1 ; // snh' in (inr) + fstp dword [esp-4] ; // in (inr) + jc short go4kDST_func_hold + fld1 ; // 1 in (inr) + fadd dword [esp-4] ; // 1+snh' in (inr) + fstp dword [WRK+go4kDST_wrk.snhphase]; // in (inr) +%endif +; // calc pregain and postgain +%ifdef GO4K_USE_DST_STEREO + test al, byte STEREO + jz short go4kDST_func_mono + fxch st1 ; // inr inl + fld dword [edx+go4kDST_val.drive] ; // drive inr inl +%ifdef GO4K_USE_DST_MOD_DM + fadd dword [WRK+go4kDST_wrk.dm] +%endif + call go4kWaveshaper ; // outr inl +%ifdef GO4K_USE_DST_SH + fst dword [WRK+go4kDST_wrk.out2] ; // outr inl +%endif + fxch st1 ; // inl outr +go4kDST_func_mono: +%endif + fld dword [edx+go4kDST_val.drive] ; // drive in (outr) +%ifdef GO4K_USE_DST_MOD_DM + fadd dword [WRK+go4kDST_wrk.dm] +%endif + call go4kWaveshaper ; // out (outr) +%ifdef GO4K_USE_DST_SH + fst dword [WRK+go4kDST_wrk.out] ; // out' (outr) +%endif + ret ; // out' (outr) +%ifdef GO4K_USE_DST_SH +go4kDST_func_hold: ; // in (inr) + fstp st0 ; // (inr) +%ifdef GO4K_USE_DST_STEREO + test al, byte STEREO + jz short go4kDST_func_monohold ; // (inr) + fstp st0 ; // + fld dword [WRK+go4kDST_wrk.out2] ; // outr +go4kDST_func_monohold: +%endif + fld dword [WRK+go4kDST_wrk.out] ; // out (outr) + ret +%endif + +%endif + +%ifdef USE_SECTIONS +section .g4kcodf code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // DLL Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kDLL_func@0 +%ifdef GO4K_USE_DLL +%ifdef GO4K_USE_DLL_CHORUS + %ifdef GO4K_USE_DLL_DAMP + push 8 + %else + push 7 + %endif +%else + %ifdef GO4K_USE_DLL_DAMP + push 6 + %else + push 5 + %endif +%endif + call go4kTransformValues + pushad + movzx ebx, byte [VAL-(go4kDLL_val.size-go4kDLL_val.delay)/4] ;// delay length index +%ifdef GO4K_USE_DLL_NOTE_SYNC + test ebx, ebx + jne go4kDLL_func_process + fld1 + fild dword [ecx-4] ; // load note freq + fmul dword [c_i12] + call _Power@0 + fmul dword [FREQ_NORMALIZE] ; // normalize + fdivp st1, st0 ; // invert to get numer of samples + fistp word [_go4k_delay_times+ebx*2] ; store current comb size +%endif +go4kDLL_func_process: + mov ecx, eax ;// ecx is delay counter +%ifdef GO4K_USE_DLL_MOD + mov edi, WRK ;// edi is modulation workspace +%endif + mov WRK, dword [_go4k_delay_buffer_ofs] ;// ebp is current delay + fld st0 ;// in in +%ifdef GO4K_USE_DLL_MOD_IM + fld dword [edx+go4kDLL_val.dry] ;// dry in in + fadd dword [edi+go4kDLL_wrk2.im] ;// dry' in in + fmulp st1, st0 ;// out in +%else + fmul dword [edx+go4kDLL_val.dry] ;// out in +%endif + fxch ;// in out +%ifdef GO4K_USE_DLL_MOD_PM + fld dword [edx+go4kDLL_val.pregain] ;// pg in out + fadd dword [edi+go4kDLL_wrk2.pm] ;// pg' in out + fmul st0, st0 ;// pg'' in out + fmulp st1, st0 ;// in' out +%else + fmul dword [edx+go4kDLL_val.pregain] ;// in' out + fmul dword [edx+go4kDLL_val.pregain] ;// in' out +%endif + +%ifdef GO4K_USE_DLL_CHORUS +;// update saw lfo for chorus/flanger + fld dword [edx+go4kDLL_val.freq] ;// f in' out +%ifdef GO4K_USE_DLL_MOD_SM + fadd dword [edi+go4kDLL_wrk2.sm] ;// f' in' out +%endif + fmul st0, st0 + fmul st0, st0 + fdiv dword [DLL_DEPTH] + fadd dword [WRK+go4kDLL_wrk.phase] ;// p' in' out +;// clamp phase to 0,1 (only in editor, since delay can be active quite long) +%ifdef GO4K_USE_DLL_CHORUS_CLAMP + fld1 ;// 1 p' in' out + fadd st1, st0 ;// 1 1+p' in' out + fxch ;// 1+p' 1 in' out + fprem ;// p'' 1 in' out + fstp st1 ;// p'' in' out +%endif + fst dword [WRK+go4kDLL_wrk.phase] +;// get current sine value + fldpi ; // pi p in' out + fadd st0 ; // 2*pi p in' out + fmulp st1, st0 ; // 2*pi*p in' out + fsin ; // sin in' out + fld1 ; // 1 sin in' out + faddp st1, st0 ; // 1+sin in' out +;// mul with depth and convert to samples + fld dword [edx+go4kDLL_val.depth] ; // d 1+sin in' out +%ifdef GO4K_USE_DLL_MOD_AM + fadd dword [edi+go4kDLL_wrk2.am] ; // d' 1+sin in' out +%endif + fmul st0, st0 + fmul st0, st0 + fmul dword [DLL_DEPTH] + fmulp st1, st0 + fistp dword [esp-4] ; // in' out +%endif + +go4kDLL_func_loop: + movzx esi, word [_go4k_delay_times+ebx*2] ; fetch comb size + mov eax, dword [WRK+go4kDLL_wrk.index] ;// eax is current comb index + +%ifdef GO4K_USE_DLL_CHORUS + ;// add lfo offset and wrap buffer + add eax, dword [esp-4] + cmp eax, esi + jl short go4kDLL_func_buffer_nowrap1 + sub eax, esi +go4kDLL_func_buffer_nowrap1: +%endif + + fld dword [WRK+eax*4+go4kDLL_wrk.buffer];// cout in' out + +%ifdef GO4K_USE_DLL_CHORUS + mov eax, dword [WRK+go4kDLL_wrk.index] +%endif + + ;// add comb output to current output + fadd st2, st0 ;// cout in' out' +%ifdef GO4K_USE_DLL_DAMP + fld1 ;// 1 cout in' out' + fsub dword [edx+go4kDLL_val.damp] ;// 1-damp cout in' out' +%ifdef GO4K_USE_DLL_MOD_DM + fsub dword [edi+go4kDLL_wrk2.dm] ;// 1-damp' cout in' out' +%endif + fmulp st1, st0 ;// cout*d2 in' out' + fld dword [edx+go4kDLL_val.damp] ;// d1 cout*d2 in' out' +%ifdef GO4K_USE_DLL_MOD_DM + fadd dword [edi+go4kDLL_wrk2.dm] ;// d1' cout*d2 in' out' +%endif + fmul dword [WRK+go4kDLL_wrk.store] ;// store*d1 cout*d2 in' out' + faddp st1, st0 ;// store' in' out' + fst dword [WRK+go4kDLL_wrk.store] ;// store' in' out' +%endif +%ifdef GO4K_USE_DLL_MOD_FM + fld dword [edx+go4kDLL_val.feedback] ;// fb cout in' out' + fadd dword [edi+go4kDLL_wrk2.fm] ;// fb' cout in' out' + fmulp st1, st0 ;// cout*fb' in' out' +%else + fmul dword [edx+go4kDLL_val.feedback] ;// cout*fb in' out' +%endif +%ifdef GO4K_USE_DLL_DC_FILTER + fadd st0, st1 ;// store in' out' + fstp dword [WRK+eax*4+go4kDLL_wrk.buffer];// in' out' +%else + fsub st0, st1 ;// store in' out' + fstp dword [WRK+eax*4+go4kDLL_wrk.buffer];// in' out' + fneg +%endif + ;// wrap comb buffer pos + inc eax + cmp eax, esi + jl short go4kDLL_func_buffer_nowrap2 +%ifdef GO4K_USE_DLL_CHORUS + sub eax, esi +%else + xor eax, eax +%endif +go4kDLL_func_buffer_nowrap2: + mov dword [WRK+go4kDLL_wrk.index], eax + ;// increment buffer pointer to next buffer + inc ebx ;// go to next delay length index + add WRK, go4kDLL_wrk.size ;// go to next delay + mov dword [_go4k_delay_buffer_ofs], WRK ;// store next delay offset + loopne go4kDLL_func_loop + fstp st0 ;// out' + ;// process a dc filter to prevent heavy offsets in reverb +%ifdef GO4K_USE_DLL_DC_FILTER +; y(n) = x(n) - x(n-1) + R * y(n-1) + sub WRK, go4kDLL_wrk.size + fld dword [WRK+go4kDLL_wrk.dcout] ;// dco out' + fmul dword [c_dc_const] ;// dcc*dco out' + fsub dword [WRK+go4kDLL_wrk.dcin] ;// dcc*dco-dci out' + fxch ;// out' dcc*dco-dci + fst dword [WRK+go4kDLL_wrk.dcin] ;// out' dcc*dco-dci + faddp st1 ;// out' +%ifdef GO4K_USE_UNDENORMALIZE + fadd dword [c_0_5] ;// add and sub small offset to prevent denormalization + fsub dword [c_0_5] +%endif + fst dword [WRK+go4kDLL_wrk.dcout] +%endif + popad + ret +%endif + + +%ifdef USE_SECTIONS +section .g4kcodu code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // GLITCH Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kGLITCH_func@0 +%ifdef GO4K_USE_GLITCH + push 5 + call go4kTransformValues + pushad + + mov edi, WRK + mov WRK, dword [_go4k_delay_buffer_ofs] ;// ebp is current delay + +; mov eax, dword [edx+go4kGLITCH_val.active] +; or eax, dword [edi+go4kGLITCH_wrk2.am] +; test eax, eax +; je go4kGLITCH_func_notactive ;// out + + fld dword [edx+go4kGLITCH_val.active] ;// a in + fadd dword [edi+go4kGLITCH_wrk2.am] ;// a' in + ; // check for activity + fldz ;// 0 a' in + fucomip st1 ;// a' in + fstp st0 ;// in + jnc go4kGLITCH_func_notactive ;// out + + ;// check for first call and init if so init (using slizesize slot) + mov eax, dword [WRK+go4kGLITCH_wrk.slizesize] + and eax, eax + jnz go4kGLITCH_func_process + mov dword [WRK+go4kGLITCH_wrk.index], eax + mov dword [WRK+go4kGLITCH_wrk.store], eax + movzx ebx, byte [VAL-(go4kGLITCH_val.size-go4kGLITCH_val.slicesize)/4] ;// slicesize index + movzx eax, word [_go4k_delay_times+ebx*2] ;// fetch slicesize + push eax + fld1 + fild dword [esp] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] + pop eax +go4kGLITCH_func_process: + ;// fill buffer until full + mov eax, dword [WRK+go4kGLITCH_wrk.store] + cmp eax, MAX_DELAY + jae go4kGLITCH_func_filldone + fst dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// in + inc dword [WRK+go4kGLITCH_wrk.store] +go4kGLITCH_func_filldone: + ;// save input + push eax + fstp dword [esp] ;// - + + ;// read from buffer + push eax + fld dword [WRK+go4kGLITCH_wrk.index] ;// idx + fist dword [esp] + pop eax + fld dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// out idx + fxch ;// idx out + ;// progress readindex with current play speed + fadd dword [WRK+go4kGLITCH_wrk.slicepitch] ;// idx' out + fst dword [WRK+go4kGLITCH_wrk.index] + + ;// check for slice done + fld dword [WRK+go4kGLITCH_wrk.slizesize] ;// size idx' out + fxch ;// idx' size out + fucomip st1 ;// idx' out + fstp st0 ;// out + jc go4kGLITCH_func_process_done + ;// reinit for next loop + xor eax, eax + mov dword [WRK+go4kGLITCH_wrk.index], eax + + fld dword [edx+go4kGLITCH_val.dsize] + fadd dword [edi+go4kGLITCH_wrk2.sm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + + fld dword [edx+go4kGLITCH_val.dpitch] + fadd dword [edi+go4kGLITCH_wrk2.pm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slicepitch] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] +go4kGLITCH_func_process_done: + + ;// dry wet mix + fld dword [edx+go4kGLITCH_val.dry] ;// dry out + fadd dword [edi+go4kGLITCH_wrk2.dm] ;// dry' out + fld1 ;// 1 dry' out + fsub st1 ;// 1-dry' dry' out + fmulp st2 ;// dry' out' + fmul dword [esp] ;// in' out' + faddp st1, st0 ;// out' + + pop eax + jmp go4kGLITCH_func_leave +go4kGLITCH_func_notactive: + ;// mark as uninitialized again (using slizesize slot) + xor eax,eax + mov dword [WRK+go4kGLITCH_wrk.slizesize], eax +go4kGLITCH_func_leave: + add WRK, go4kDLL_wrk.size ;// go to next delay + mov dword [_go4k_delay_buffer_ofs], WRK ;// store next delay offset + popad + ret +%endif + +%ifdef USE_SECTIONS +section .g4kcodg code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // FOP Tick (various fp stack based operations) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kFOP_func@0 + push 1 + call go4kTransformValues +go4kFOP_func_pop: + dec eax + jnz go4kFOP_func_addp + fstp st0 + ret +go4kFOP_func_addp: + dec eax + jnz go4kFOP_func_mulp + faddp st1, st0 + ret +go4kFOP_func_mulp: + dec eax + jnz go4kFOP_func_push + fmulp st1, st0 + ret +go4kFOP_func_push: + dec eax + jnz go4kFOP_func_xch + fld st0 + ret +go4kFOP_func_xch: + dec eax + jnz go4kFOP_func_add + fxch + ret +go4kFOP_func_add: + dec eax + jnz go4kFOP_func_mul + fadd st1 + ret +go4kFOP_func_mul: + dec eax + jnz go4kFOP_func_addp2 + fmul st1 + ret +go4kFOP_func_addp2: + dec eax + jnz go4kFOP_func_loadnote + faddp st2, st0 + faddp st2, st0 + ret +go4kFOP_func_loadnote: + dec eax + jnz go4kFOP_func_mulp2 + fild dword [ecx-4] + fmul dword [c_i128] + ret +go4kFOP_func_mulp2: + fmulp st2, st0 + fmulp st2, st0 + ret + +%ifdef USE_SECTIONS +section .g4kcodh code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // FST Tick (stores a value somewhere in the local workspace) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kFST_func@0 + push 1 + call go4kTransformValues + fld dword [edx+go4kFST_val.amount] + fsub dword [c_0_5] + fadd st0 + fmul st1 + lodsw + and eax, 0x00003fff ; // eax is destination slot + test word [VAL-2], FST_ADD + jz go4kFST_func_set + fadd dword [ecx+eax*4] +go4kFST_func_set: + fstp dword [ecx+eax*4] + test word [VAL-2], FST_POP + jz go4kFST_func_done + fstp st0 +go4kFST_func_done: + ret + +%ifdef USE_SECTIONS +section .g4kcodm code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // FLD Tick (load a value on stack, optionally add a modulation signal beforehand) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : signal-signal*pan , signal*pan +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kFLD_func@0 ;// in main env +%ifdef GO4K_USE_FLD + push 1 + call go4kTransformValues + fld dword [edx+go4kFLD_val.value] ;// value in + fsub dword [c_0_5] + fadd st0 +%ifdef GO4K_USE_FLD_MOD_VM + fadd dword [WRK+go4kFLD_wrk.vm] ;// value' in +%endif +%endif + ret + +%ifdef GO4K_USE_FSTG +%ifdef USE_SECTIONS +section .g4kcodi code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // FSTG Tick (stores a value anywhere in the synth (and in each voice)) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kFSTG_func@0 + push 1 + call go4kTransformValues +%ifdef GO4K_USE_FSTG_CHECK +; check if current note still active + mov eax, dword [ecx-4] + test eax, eax + jne go4kFSTG_func_do + lodsw + jmp go4kFSTG_func_testpop +go4kFSTG_func_do: +%endif + fld dword [edx+go4kFST_val.amount] + fsub dword [c_0_5] + fadd st0 + fmul st1 + lodsw + and eax, 0x00003fff ; // eax is destination slot + test word [VAL-2], FST_ADD + jz go4kFSTG_func_set + fadd dword [go4k_synth_wrk+eax*4] +go4kFSTG_func_set: +%if MAX_VOICES > 1 + fst dword [go4k_synth_wrk+eax*4] + fstp dword [go4k_synth_wrk+eax*4+go4k_instrument.size] +%else + fstp dword [go4k_synth_wrk+eax*4] +%endif +go4kFSTG_func_testpop: + test word [VAL-2], FST_POP + jz go4kFSTG_func_done + fstp st0 +go4kFSTG_func_done: + ret +%endif + +%ifdef USE_SECTIONS +section .g4kcodj code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // PAN Tick (multiplies signal with main envelope and converts to stereo) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : signal-signal*pan , signal*pan +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kPAN_func@0 ;// in main env +%ifdef GO4K_USE_PAN + push 1 + call go4kTransformValues + fld dword [edx+go4kPAN_val.panning] ;// pan in +%ifdef GO4K_USE_PAN_MOD + fadd dword [WRK+go4kPAN_wrk.pm] ;// pan in +%endif + fmul st1 ;// r in + fsub st1, st0 ;// r l + fxch ;// l r +%else + fmul dword [c_0_5] + fld st0 +%endif + ret + +%ifdef USE_SECTIONS +section .g4kcodk code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // OUT Tick ( stores stereo signal pair in temp buffers of the instrument) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +export_func go4kOUT_func@0 ;// l r +%ifdef GO4K_USE_GLOBAL_DLL + push 2 + call go4kTransformValues + pushad + lea edi, [ecx+MAX_UNITS*MAX_UNIT_SLOTS*4] + fld st1 ;// r l r + fld st1 ;// l r l r + fld dword [edx+go4kOUT_val.auxsend] ;// as l r l r +%ifdef GO4K_USE_OUT_MOD_AM + fadd dword [WRK+go4kOUT_wrk.am] ;// am l r l r +%endif + fmulp st1, st0 ;// l' r l r + fstp dword [edi] ;// r l r + scasd + fld dword [edx+go4kOUT_val.auxsend] ;// as r l r +%ifdef GO4K_USE_OUT_MOD_AM + fadd dword [WRK+go4kOUT_wrk.am] ;// am r l r +%endif + fmulp st1, st0 ;// r' l r + fstp dword [edi] ;// l r + scasd + fld dword [edx+go4kOUT_val.gain] ;// g l r +%ifdef GO4K_USE_OUT_MOD_GM + fadd dword [WRK+go4kOUT_wrk.gm] ;// gm l r +%endif + fmulp st1, st0 ;// l' r + fstp dword [edi] ;// r + scasd + fld dword [edx+go4kOUT_val.gain] ;// g r +%ifdef GO4K_USE_OUT_MOD_GM + fadd dword [WRK+go4kOUT_wrk.gm] ;// gm r +%endif + fmulp st1, st0 ;// r' + fstp dword [edi] ;// - + scasd + popad +%else + push 1 + call go4kTransformValues + + fld dword [edx+go4kOUT_val.gain] ;// g l r +%ifdef GO4K_USE_OUT_MOD_GM + fadd dword [WRK+go4kOUT_wrk.gm] ;// gm l r +%endif + fmulp st1, st0 ;// l' r + fstp dword [ecx+MAX_UNITS*MAX_UNIT_SLOTS*4+0] ;// r + fld dword [edx+go4kOUT_val.gain] ;// g r +%ifdef GO4K_USE_OUT_MOD_GM + fadd dword [WRK+go4kOUT_wrk.gm] ;// gm r +%endif + fmulp st1, st0 ;// r' + fstp dword [ecx+MAX_UNITS*MAX_UNIT_SLOTS*4+4] ;// - + +%endif + ret + +%ifdef USE_SECTIONS +section .g4kcodl code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // ACC Tick (stereo signal accumulation for synth commands only -> dont use in instrument commands) +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kACC_func@0 + push 1 + call go4kTransformValues + pushad + mov edi, go4k_synth_wrk + add edi, go4k_instrument.size + sub edi, eax ; // eax already contains the accumulation offset from the go4kTransformValues call + mov cl, MAX_INSTRUMENTS*MAX_VOICES + fldz ;// 0 + fldz ;// 0 0 +go4kACC_func_loop: + fadd dword [edi-8] ;// l 0 + fxch ;// 0 l + fadd dword [edi-4] ;// r l + fxch ;// l r + add edi, go4k_instrument.size + dec cl + jnz go4kACC_func_loop + popad + ret + +%ifdef USE_SECTIONS +section .g4kcodw code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // Update Instrument (allocate voices, set voice to release) +; //---------------------------------------------------------------------------------------- +; // IN : +; // IN : +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +go4kUpdateInstrument: +; // get new note + mov eax, dword [esp+4+4] ; // eax = current tick + shr eax, PATTERN_SIZE_SHIFT ; // eax = current pattern + imul edx, ecx, dword MAX_PATTERNS ; // edx = instrument pattern list index + movzx edx, byte [edx+eax+go4k_pattern_lists] ; // edx = pattern index + mov eax, dword [esp+4+4] ; // eax = current tick + shl edx, PATTERN_SIZE_SHIFT + and eax, PATTERN_SIZE-1 + movzx edx, byte [edx+eax+go4k_patterns] ; // edx = requested note in new patterntick +; // apply note changes + cmp dl, HLD ; // anything but hold causes action + je short go4kUpdateInstrument_done + inc dword [edi] ; // set release flag if needed +%if MAX_VOICES > 1 + inc dword [edi+go4k_instrument.size] ; // set release flag if needed +%endif + cmp dl, HLD ; // check for new note + jl short go4kUpdateInstrument_done +%if MAX_VOICES > 1 + pushad + xchg eax, dword [go4k_voiceindex + ecx*4] + test eax, eax + je go4kUpdateInstrument_newNote + add edi, go4k_instrument.size +go4kUpdateInstrument_newNote: + xor al,1 + xchg dword [go4k_voiceindex + ecx*4], eax +%endif + pushad + xor eax, eax + mov ecx, (8+MAX_UNITS*MAX_UNIT_SLOTS*4)/4 ; // clear only relase, note and workspace + rep stosd + popad + mov dword [edi+4], edx ; // set requested note as current note +%if MAX_VOICES > 1 + popad +%endif + jmp short go4kUpdateInstrument_done +go4kUpdateInstrument_done: + ret + +%ifdef USE_SECTIONS +section .g4kcodx code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // Render Voices +; //---------------------------------------------------------------------------------------- +; // IN : +; // IN : +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +go4kRenderVoices: + push ecx ; // save current instrument counter +%if MAX_VOICES > 1 + push COM ; // save current instrument command index + push VAL ; // save current instrument values index +%endif + call go4k_VM_process ; // call synth vm for instrument voices + mov eax, dword [ecx+go4kENV_wrk.state] + cmp al, byte ENV_STATE_OFF + jne go4kRenderVoices_next + xor eax, eax + mov dword [ecx-4], eax ; // kill note if voice is done +go4kRenderVoices_next: +%if MAX_VOICES > 1 + pop VAL ; // restore instrument value index + pop COM ; // restore instrument command index +%endif + +%ifdef GO4K_USE_BUFFER_RECORDINGS + mov eax, dword [esp+16] ; // get current tick + shr eax, 8 ; // every 256th sample = ~ 172 hz + shl eax, 5 ; // for 16 instruments a 2 voices + add eax, dword [esp] + add eax, dword [esp] ; // + 2*currentinstrument+0 +%ifdef GO4K_USE_ENVELOPE_RECORDINGS + mov edx, dword [ecx+go4kENV_wrk.level] + mov dword [__4klang_envelope_buffer+eax*4], edx +%endif +%ifdef GO4K_USE_NOTE_RECORDINGS + mov edx, dword [ecx-4] + mov dword [__4klang_note_buffer+eax*4], edx +%endif +%endif + +%if MAX_VOICES > 1 + call go4k_VM_process ; // call synth vm for instrument voices + mov eax, dword [ecx+go4kENV_wrk.state] + cmp al, byte ENV_STATE_OFF + jne go4k_render_instrument_next2 + xor eax, eax + mov dword [ecx-4], eax ; // kill note if voice is done +go4k_render_instrument_next2: + +%ifdef GO4K_USE_BUFFER_RECORDINGS + mov eax, dword [esp+16] ; // get current tick + shr eax, 8 ; // every 256th sample = ~ 172 hz + shl eax, 5 ; // for 16 instruments a 2 voices + add eax, dword [esp] + add eax, dword [esp] ; // + 2*currentinstrument+0 +%ifdef GO4K_USE_ENVELOPE_RECORDINGS + mov edx, dword [ecx+go4kENV_wrk.level] + mov dword [__4klang_envelope_buffer+eax*4+4], edx +%endif +%ifdef GO4K_USE_NOTE_RECORDINGS + mov edx, dword [ecx-4] + mov dword [__4klang_note_buffer+eax*4+4], edx +%endif +%endif + +%endif + pop ecx ; // restore instrument counter + ret + +%ifdef USE_SECTIONS +section .g4kcody code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // the entry point for the synth +; //---------------------------------------------------------------------------------------- +%ifdef USE_SECTIONS +export_func _4klang_render@4 +%else +export_func _4klang_render +%endif + pushad + xor ecx, ecx +%ifdef GO4K_USE_BUFFER_RECORDINGS + push ecx +%endif +; loop all ticks +go4k_render_tickloop: + push ecx + xor ecx, ecx +; loop all samples per tick +go4k_render_sampleloop: + push ecx + xor ecx, ecx + mov ebx, go4k_synth_instructions ; // ebx = instrument command index + mov VAL, go4k_synth_parameter_values; // VAL = instrument values index + mov edi, _go4k_delay_buffer ; // get offset of first delay buffer + mov dword [_go4k_delay_buffer_ofs], edi ; // store offset in delaybuffer offset variable + mov edi, go4k_synth_wrk ; // edi = first instrument +; loop all instruments +go4k_render_instrumentloop: + mov eax, dword [esp] ; // eax = current tick sample + and eax, eax + jnz go4k_render_instrument_process ; // tick change? (first sample in current tick) + call go4kUpdateInstrument ; // update instrument state +; process instrument +go4k_render_instrument_process: + call go4kRenderVoices + inc ecx + cmp cl, byte MAX_INSTRUMENTS + jl go4k_render_instrumentloop + mov dword [edi+4], ecx ; // move a value != 0 into note slot, so processing will be done + call go4k_VM_process ; // call synth vm for synth +go4k_render_output_sample: +%ifdef GO4K_USE_BUFFER_RECORDINGS + inc dword [esp+8] + xchg esi, dword [esp+48] ; // edx = destbuffer +%else + xchg esi, dword [esp+44] ; // edx = destbuffer +%endif +%ifdef GO4K_CLIP_OUTPUT + fld dword [edi-8] + fld1 ; // 1 val + fucomi st1 ; // 1 val + jbe short go4k_render_clip1 + fchs ; // -1 val + fucomi st1 ; // -1 val + fcmovb st0, st1 ; // val -1 (if val > -1) +go4k_render_clip1: + fstp st1 ; // newval +%ifdef GO4K_USE_16BIT_OUTPUT + push eax + fmul dword [c_32767] + fistp dword [esp] + pop eax + mov word [esi],ax ; // store integer converted left sample + lodsw +%else + fstp dword [esi] ; // store left sample + lodsd +%endif + fld dword [edi-4] + fld1 ; // 1 val + fucomi st1 ; // 1 val + jbe short go4k_render_clip2 + fchs ; // -1 val + fucomi st1 ; // -1 val + fcmovb st0, st1 ; // val -1 (if val > -1) +go4k_render_clip2: + fstp st1 ; // newval +%ifdef GO4K_USE_16BIT_OUTPUT + push eax + fmul dword [c_32767] + fistp dword [esp] + pop eax + mov word [esi],ax ; // store integer converted right sample + lodsw +%else + fstp dword [esi] ; // store right sample + lodsd +%endif +%else + fld dword [edi-8] +%ifdef GO4K_USE_16BIT_OUTPUT + push eax + fmul dword [c_32767] + fistp dword [esp] + pop eax + mov word [esi],ax ; // store integer converted left sample + lodsw +%else + fstp dword [esi] ; // store left sample + lodsd +%endif + fld dword [edi-4] +%ifdef GO4K_USE_16BIT_OUTPUT + push eax + fmul dword [c_32767] + fistp dword [esp] + pop eax + mov word [esi],ax ; // store integer converted right sample + lodsw +%else + fstp dword [esi] ; // store right sample + lodsd +%endif +%endif +%ifdef GO4K_USE_BUFFER_RECORDINGS + xchg esi, dword [esp+48] +%else + xchg esi, dword [esp+44] +%endif + pop ecx + inc ecx +%ifdef GO4K_USE_GROOVE_PATTERN + mov ebx, dword SAMPLES_PER_TICK + mov eax, dword [esp] + and eax, 0x0f + bt dword [go4k_groove_pattern],eax + jnc go4k_render_nogroove + sub ebx, dword 3000 +go4k_render_nogroove: + cmp ecx, ebx +%else + cmp ecx, dword SAMPLES_PER_TICK +%endif + jl go4k_render_sampleloop + pop ecx + inc ecx +%ifdef AUTHORING + mov dword[__4klang_current_tick], ecx +%endif + cmp ecx, dword MAX_TICKS + jl go4k_render_tickloop +%ifdef GO4K_USE_BUFFER_RECORDINGS + pop ecx +%endif + popad + ret 4 + +%ifdef USE_SECTIONS +section .g4kcodz code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // the magic behind it :) +; //---------------------------------------------------------------------------------------- +; // IN : edi = instrument pointer +; // IN : esi = instrumet values +; // IN : ebx = instrument instructions +; // OUT : +; // DIRTY : +; //---------------------------------------------------------------------------------------- +go4k_VM_process: + lea WRK, [edi+8] ; // get current workspace pointer + mov ecx, WRK ; // ecx = workspace start +go4k_VM_process_loop: + movzx eax, byte [ebx] ; // get command byte + inc ebx + test eax, eax + je go4k_VM_process_done ; // command byte = 0? so done + call dword [eax*4+go4k_synth_commands] + add WRK, MAX_UNIT_SLOTS*4 ; // go to next workspace slot + jmp short go4k_VM_process_loop +go4k_VM_process_done: + add edi, go4k_instrument.size ; // go to next instrument voice + ret \ No newline at end of file diff --git a/4klang.h b/4klang.h new file mode 100644 index 0000000..6f477e5 --- /dev/null +++ b/4klang.h @@ -0,0 +1,22 @@ +// some useful song defines for 4klang +#define SAMPLE_RATE 44100 +#define BPM 120.000000 +#define MAX_INSTRUMENTS 3 +#define MAX_PATTERNS 50 +#define PATTERN_SIZE_SHIFT 4 +#define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT) +#define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE) +#define SAMPLES_PER_TICK 5512 +#define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS) +#define POLYPHONY 1 +#define INTEGER_16BIT +#define SAMPLE_TYPE short + +#define WINDOWS_OBJECT + +// declaration of the external synth render function, you'll always need that +extern "C" void __stdcall _4klang_render(void*); +// declaration of the external envelope buffer. access only if you're song was exported with that option +extern "C" float _4klang_envelope_buffer; +// declaration of the external note buffer. access only if you're song was exported with that option +extern "C" int _4klang_note_buffer; diff --git a/4klang.inc b/4klang.inc new file mode 100644 index 0000000..84cc72f --- /dev/null +++ b/4klang.inc @@ -0,0 +1,621 @@ +%macro export_func 1 + global _%1 + _%1: +%endmacro +%define USE_SECTIONS +%define SAMPLE_RATE 44100 +%define MAX_INSTRUMENTS 3 +%define MAX_VOICES 1 +%define HLD 1 +%define BPM 120.000000 +%define MAX_PATTERNS 50 +%define PATTERN_SIZE_SHIFT 4 +%define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT) +%define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE) +%define SAMPLES_PER_TICK 5512 +%define DEF_LFO_NORMALIZE 0.0000453515 +%define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS) +%define GO4K_USE_16BIT_OUTPUT +;%define GO4K_USE_GROOVE_PATTERN +;%define GO4K_USE_ENVELOPE_RECORDINGS +;%define GO4K_USE_NOTE_RECORDINGS +%define GO4K_CLIP_OUTPUT +%define GO4K_USE_DLL +%define GO4K_USE_GLOBAL_DLL +%define GO4K_USE_ENV_CHECK +%define GO4K_USE_VCO_CHECK +%define GO4K_USE_VCO_SHAPE +%define GO4K_USE_VCF_CHECK +%define GO4K_USE_VCF_MOD_FM +%define GO4K_USE_VCF_HIGH +%define GO4K_USE_VCF_BAND +%define GO4K_USE_VCF_PEAK +%define GO4K_USE_DST_CHECK +%define GO4K_USE_DLL_CHORUS +%define GO4K_USE_DLL_CHORUS_CLAMP +%define GO4K_USE_DLL_DAMP +%define GO4K_USE_DLL_DC_FILTER +%define GO4K_USE_FSTG_CHECK +%define GO4K_USE_WAVESHAPER_CLIP +%define MAX_DELAY 65536 +%define MAX_UNITS 64 +%define MAX_UNIT_SLOTS 16 +%define GO4K_BEGIN_CMDDEF(def_name) +%define GO4K_END_CMDDEF db 0 +%define GO4K_BEGIN_PARAMDEF(def_name) +%define GO4K_END_PARAMDEF +GO4K_ENV_ID equ 1 +%macro GO4K_ENV 5 + db %1 + db %2 + db %3 + db %4 + db %5 +%endmacro +%define ATTAC(val) val +%define DECAY(val) val +%define SUSTAIN(val) val +%define RELEASE(val) val +%define GAIN(val) val +struc go4kENV_val + .attac resd 1 + .decay resd 1 + .sustain resd 1 + .release resd 1 + .gain resd 1 + .size +endstruc +struc go4kENV_wrk + .state resd 1 + .level resd 1 + .gm resd 1 + .am resd 1 + .dm resd 1 + .sm resd 1 + .rm resd 1 + .size +endstruc +%define ENV_STATE_ATTAC 0 +%define ENV_STATE_DECAY 1 +%define ENV_STATE_SUSTAIN 2 +%define ENV_STATE_RELEASE 3 +%define ENV_STATE_OFF 4 +GO4K_VCO_ID equ 2 +%macro GO4K_VCO 8 + db %1 + db %2 +%ifdef GO4K_USE_VCO_PHASE_OFFSET + db %3 +%endif +%ifdef GO4K_USE_VCO_GATE + db %4 +%endif + db %5 +%ifdef GO4K_USE_VCO_SHAPE + db %6 +%endif + db %7 + db %8 +%endmacro +%define TRANSPOSE(val) val +%define DETUNE(val) val +%define PHASE(val) val +%define GATES(val) val +%define COLOR(val) val +%define SHAPE(val) val +%define FLAGS(val) val +%define SINE 0x01 +%define TRISAW 0x02 +%define PULSE 0x04 +%define NOISE 0x08 +%define LFO 0x10 +%define GATE 0x20 +%define VCO_STEREO 0x40 +struc go4kVCO_val + .transpose resd 1 + .detune resd 1 +%ifdef GO4K_USE_VCO_PHASE_OFFSET + .phaseofs resd 1 +%endif +%ifdef GO4K_USE_VCO_GATE + .gate resd 1 +%endif + .color resd 1 +%ifdef GO4K_USE_VCO_SHAPE + .shape resd 1 +%endif + .gain resd 1 + .flags resd 1 + .size +endstruc +struc go4kVCO_wrk + .phase resd 1 + .tm resd 1 + .dm resd 1 + .fm resd 1 + .pm resd 1 + .cm resd 1 + .sm resd 1 + .gm resd 1 + .phase2 resd 1 + .size +endstruc +GO4K_VCF_ID equ 3 +%macro GO4K_VCF 3 + db %1 + db %2 + db %3 +%endmacro +%define LOWPASS 0x1 +%define HIGHPASS 0x2 +%define BANDPASS 0x4 +%define BANDSTOP 0x3 +%define ALLPASS 0x7 +%define PEAK 0x8 +%define STEREO 0x10 +%define FREQUENCY(val) val +%define RESONANCE(val) val +%define VCFTYPE(val) val +struc go4kVCF_val + .freq resd 1 + .res resd 1 + .type resd 1 + .size +endstruc +struc go4kVCF_wrk + .low resd 1 + .high resd 1 + .band resd 1 + .freq resd 1 + .fm resd 1 + .rm resd 1 + .low2 resd 1 + .high2 resd 1 + .band2 resd 1 + .size +endstruc +GO4K_DST_ID equ 4 +%macro GO4K_DST 3 + db %1 +%ifdef GO4K_USE_DST_SH + db %2 +%ifdef GO4K_USE_DST_STEREO + db %3 +%endif +%else +%ifdef GO4K_USE_DST_STEREO + db %3 +%endif +%endif +%endmacro +%define DRIVE(val) val +%define SNHFREQ(val) val +%define FLAGS(val) val +struc go4kDST_val + .drive resd 1 +%ifdef GO4K_USE_DST_SH + .snhfreq resd 1 +%endif + .flags resd 1 + .size +endstruc +struc go4kDST_wrk + .out resd 1 + .snhphase resd 1 + .dm resd 1 + .sm resd 1 + .out2 resd 1 + .size +endstruc +GO4K_DLL_ID equ 5 +%macro GO4K_DLL 8 + db %1 + db %2 + db %3 +%ifdef GO4K_USE_DLL_DAMP + db %4 +%endif +%ifdef GO4K_USE_DLL_CHORUS + db %5 + db %6 +%endif + db %7 + db %8 +%endmacro +%define PREGAIN(val) val +%define DRY(val) val +%define FEEDBACK(val) val +%define DEPTH(val) val +%define DAMP(val) val +%define DELAY(val) val +%define COUNT(val) val +struc go4kDLL_val + .pregain resd 1 + .dry resd 1 + .feedback resd 1 +%ifdef GO4K_USE_DLL_DAMP + .damp resd 1 +%endif +%ifdef GO4K_USE_DLL_CHORUS + .freq resd 1 + .depth +%endif + .delay resd 1 + .count resd 1 + .size +endstruc +struc go4kDLL_wrk + .index resd 1 + .store resd 1 + .dcin resd 1 + .dcout resd 1 +%ifdef GO4K_USE_DLL_CHORUS + .phase resd 1 +%endif + .buffer resd MAX_DELAY + .size +endstruc +struc go4kDLL_wrk2 + .pm resd 1 + .fm resd 1 + .im resd 1 + .dm resd 1 + .sm resd 1 + .am resd 1 + .size +endstruc +GO4K_FOP_ID equ 6 +%macro GO4K_FOP 1 + db %1 +%endmacro +%define OP(val) val +%define FOP_POP 0x1 +%define FOP_ADDP 0x2 +%define FOP_MULP 0x3 +%define FOP_PUSH 0x4 +%define FOP_XCH 0x5 +%define FOP_ADD 0x6 +%define FOP_MUL 0x7 +%define FOP_ADDP2 0x8 +%define FOP_LOADNOTE 0x9 +%define FOP_MULP2 0xa +struc go4kFOP_val + .flags resd 1 + .size +endstruc +struc go4kFOP_wrk + .size +endstruc +GO4K_FST_ID equ 7 +%macro GO4K_FST 2 + db %1 + dw %2 +%endmacro +%define AMOUNT(val) val +%define DEST(val) val +%define FST_SET 0x0000 +%define FST_ADD 0x4000 +%define FST_POP 0x8000 +struc go4kFST_val + .amount resd 1 + .op1 resd 1 + .size +endstruc +struc go4kFST_wrk + .size +endstruc +GO4K_PAN_ID equ 8 +%macro GO4K_PAN 1 +%ifdef GO4K_USE_PAN + db %1 +%endif +%endmacro +%define PANNING(val) val +struc go4kPAN_val +%ifdef GO4K_USE_PAN + .panning resd 1 +%endif + .size +endstruc +struc go4kPAN_wrk + .pm resd 1 + .size +endstruc +GO4K_OUT_ID equ 9 +%macro GO4K_OUT 2 + db %1 +%ifdef GO4K_USE_GLOBAL_DLL + db %2 +%endif +%endmacro +%define AUXSEND(val) val +struc go4kOUT_val + .gain resd 1 +%ifdef GO4K_USE_GLOBAL_DLL + .auxsend resd 1 +%endif + .size +endstruc +struc go4kOUT_wrk + .am resd 1 + .gm resd 1 + .size +endstruc +GO4K_ACC_ID equ 10 +%macro GO4K_ACC 1 + db %1 +%endmacro +%define OUTPUT 0 +%define AUX 8 +%define ACCTYPE(val) val +struc go4kACC_val + .acctype resd 1 + .size +endstruc +struc go4kACC_wrk + .size +endstruc +%ifdef GO4K_USE_FLD +GO4K_FLD_ID equ 11 +%macro GO4K_FLD 1 + db %1 +%endmacro +%define VALUE(val) val +struc go4kFLD_val + .value resd 1 + .size +endstruc +struc go4kFLD_wrk + .vm resd 1 + .size +endstruc +%endif +%ifdef GO4K_USE_GLITCH +GO4K_GLITCH_ID equ 12 +%macro GO4K_GLITCH 5 + db %1 + db %2 + db %3 + db %4 + db %5 +%endmacro +%define ACTIVE(val) val +%define SLICEFACTOR(val)val +%define PITCHFACTOR(val)val +%define SLICESIZE(val) val +struc go4kGLITCH_val + .active resd 1 + .dry resd 1 + .dsize resd 1 + .dpitch resd 1 + .slicesize resd 1 + .size +endstruc +struc go4kGLITCH_wrk + .index resd 1 + .store resd 1 + .slizesize resd 1 + .slicepitch resd 1 + .unused resd 1 + .buffer resd MAX_DELAY + .size +endstruc +struc go4kGLITCH_wrk2 + .am resd 1 + .dm resd 1 + .sm resd 1 + .pm resd 1 + .size +endstruc +%endif +%ifdef GO4K_USE_FSTG +GO4K_FSTG_ID equ 13 +%macro GO4K_FSTG 2 + db %1 + dw %2 +%endmacro +struc go4kFSTG_val + .amount resd 1 + .op1 resd 1 + .size +endstruc +struc go4kFSTG_wrk + .size +endstruc +%endif +struc go4k_instrument + .release resd 1 + .note resd 1 + .workspace resd MAX_UNITS*MAX_UNIT_SLOTS + .dlloutl resd 1 + .dlloutr resd 1 + .outl resd 1 + .outr resd 1 + .size +endstruc +struc go4k_synth + .instruments resb go4k_instrument.size * MAX_INSTRUMENTS * MAX_VOICES + .global resb go4k_instrument.size * MAX_VOICES + .size +endstruc +%ifdef USE_SECTIONS +section .g4kmuc1 data align=1 +%else +section .data align=1 +%endif +go4k_patterns + db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + db 48, HLD, HLD, 48, HLD, HLD, 43, HLD, 41, HLD, HLD, 41, 0, 0, 0, 0, + db 41, HLD, HLD, 41, HLD, HLD, 43, HLD, 48, HLD, HLD, 48, 0, 0, 0, 0, + db 43, HLD, HLD, 43, HLD, HLD, 46, HLD, 48, HLD, HLD, 48, 0, 0, 0, 0, + db 41, HLD, HLD, 41, HLD, HLD, 53, HLD, 41, HLD, HLD, 41, 0, 0, 0, 0, + db 48, HLD, HLD, 48, HLD, HLD, 60, HLD, 48, HLD, HLD, 48, 0, 0, 0, 0, + db 0, 0, 84, HLD, HLD, HLD, 79, 0, 82, 79, 0, 77, 0, 75, HLD, 0, + db 72, 0, 72, 0, 75, 0, 82, 79, HLD, HLD, 79, 0, 0, 0, 0, 0, + db 72, 0, 72, 0, 75, 0, 75, 72, HLD, HLD, 72, 0, 0, 0, 0, 0, + db 87, HLD, HLD, HLD, 0, 0, 84, 0, 0, 0, 84, 0, 84, 0, 0, 0, + db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 82, 0, 84, 82, 79, + db 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, HLD, 0, 89, 0, 87, 0, + db 89, HLD, HLD, HLD, 0, 0, 84, 0, 0, 0, 84, 0, 84, 0, 0, 0, + db 75, HLD, HLD, 75, HLD, HLD, 70, HLD, 68, HLD, HLD, 68, 0, 0, 0, 0, + db 68, HLD, HLD, 68, HLD, HLD, 70, HLD, 75, HLD, HLD, 75, 0, 0, 0, 0, + db 70, HLD, HLD, 70, HLD, HLD, 70, HLD, 75, HLD, HLD, 75, 0, 0, 0, 0, + db 68, HLD, HLD, 68, HLD, HLD, 70, HLD, HLD, 70, HLD, HLD, 70, HLD, 0, 0, + db 68, HLD, HLD, 68, HLD, HLD, 68, HLD, 70, HLD, HLD, 70, 0, 0, 70, HLD, + db 70, HLD, HLD, 70, HLD, HLD, 75, HLD, HLD, 75, HLD, HLD, 75, HLD, 0, 0, + db 70, HLD, HLD, 70, HLD, HLD, 70, HLD, 75, HLD, HLD, 75, 0, 0, 75, HLD, +go4k_patterns_end +%ifdef USE_SECTIONS +section .g4kmuc2 data align=1 +%else +section .data +%endif +go4k_pattern_lists +Instrument0List db 0, 0, 0, 0, 1, 2, 1, 3, 1, 2, 1, 3, 1, 2, 1, 3, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 0, 0, 0, 0, 1, 2, 1, 3, 1, 2, 1, 3, 1, 2, 1, 3, 0, 0, +Instrument1List db 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 8, 6, 7, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 9, 11, 12, 11, 12, 0, 6, 7, 6, 8, 6, 7, 6, 8, 9, 11, 9, 0, 6, 7, 6, 8, 0, 0, +Instrument2List db 13, 14, 13, 15, 13, 14, 13, 15, 13, 14, 13, 15, 13, 14, 13, 15, 16, 17, 18, 19, 16, 17, 18, 19, 16, 17, 18, 19, 16, 17, 18, 19, 13, 14, 13, 15, 13, 14, 13, 15, 13, 14, 13, 0, 13, 14, 13, 15, 0, 0, +go4k_pattern_lists_end +%ifdef USE_SECTIONS +section .g4kmuc3 data align=1 +%else +section .data +%endif +go4k_synth_instructions +GO4K_BEGIN_CMDDEF(Instrument0) + db GO4K_ENV_ID + db GO4K_ENV_ID + db GO4K_FST_ID + db GO4K_FOP_ID + db GO4K_VCO_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_PAN_ID + db GO4K_OUT_ID +GO4K_END_CMDDEF +GO4K_BEGIN_CMDDEF(Instrument1) + db GO4K_ENV_ID + db GO4K_ENV_ID + db GO4K_FST_ID + db GO4K_FOP_ID + db GO4K_VCO_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_DLL_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_DLL_ID + db GO4K_OUT_ID +GO4K_END_CMDDEF +GO4K_BEGIN_CMDDEF(Instrument2) + db GO4K_ENV_ID + db GO4K_VCO_ID + db GO4K_VCO_ID + db GO4K_FOP_ID + db GO4K_VCO_ID + db GO4K_FOP_ID + db GO4K_FOP_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_FOP_ID + db GO4K_VCF_ID + db GO4K_OUT_ID +GO4K_END_CMDDEF +GO4K_BEGIN_CMDDEF(Global) + db GO4K_ACC_ID + db GO4K_DLL_ID + db GO4K_FOP_ID + db GO4K_DLL_ID + db GO4K_FOP_ID + db GO4K_ACC_ID + db GO4K_FOP_ID + db GO4K_OUT_ID +GO4K_END_CMDDEF +go4k_synth_instructions_end +%ifdef USE_SECTIONS +section .g4kmuc4 data align=1 +%else +section .data +%endif +go4k_synth_parameter_values +GO4K_BEGIN_PARAMDEF(Instrument0) + GO4K_ENV ATTAC(5),DECAY(85),SUSTAIN(107),RELEASE(0),GAIN(128) + GO4K_ENV ATTAC(59),DECAY(95),SUSTAIN(0),RELEASE(64),GAIN(91) + GO4K_FST AMOUNT(80),DEST(6*MAX_UNIT_SLOTS+4+FST_SET) + GO4K_FOP OP(FOP_POP) + GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW) + GO4K_FOP OP(FOP_MULP) + GO4K_VCF FREQUENCY(20),RESONANCE(23),VCFTYPE(LOWPASS) + GO4K_PAN PANNING(64) + GO4K_OUT GAIN(64), AUXSEND(0) +GO4K_END_PARAMDEF +GO4K_BEGIN_PARAMDEF(Instrument1) + GO4K_ENV ATTAC(23),DECAY(66),SUSTAIN(20),RELEASE(64),GAIN(128) + GO4K_ENV ATTAC(75),DECAY(77),SUSTAIN(20),RELEASE(64),GAIN(128) + GO4K_FST AMOUNT(92),DEST(6*MAX_UNIT_SLOTS+4+FST_SET) + GO4K_FOP OP(FOP_POP) + GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(PULSE) + GO4K_FOP OP(FOP_MULP) + GO4K_VCF FREQUENCY(38),RESONANCE(45),VCFTYPE(BANDPASS) + GO4K_FOP OP(FOP_PUSH) + GO4K_VCF FREQUENCY(56),RESONANCE(80),VCFTYPE(BANDSTOP) + GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(35),DEPTH(57),DELAY(17),COUNT(1) + GO4K_FOP OP(FOP_XCH) + GO4K_VCF FREQUENCY(45),RESONANCE(94),VCFTYPE(BANDSTOP) + GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(8),DEPTH(61),DELAY(18),COUNT(1) + GO4K_OUT GAIN(64), AUXSEND(0) +GO4K_END_PARAMDEF +GO4K_BEGIN_PARAMDEF(Instrument2) + GO4K_ENV ATTAC(36),DECAY(75),SUSTAIN(0),RELEASE(64),GAIN(128) + GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(89),GAIN(128),FLAGS(TRISAW) + GO4K_VCO TRANSPOSE(68),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(89),GAIN(128),FLAGS(TRISAW) + GO4K_FOP OP(FOP_ADDP) + GO4K_VCO TRANSPOSE(71),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(85),GAIN(128),FLAGS(TRISAW) + GO4K_FOP OP(FOP_ADDP) + GO4K_FOP OP(FOP_MULP) + GO4K_FOP OP(FOP_PUSH) + GO4K_VCF FREQUENCY(36),RESONANCE(49),VCFTYPE(BANDPASS) + GO4K_FOP OP(FOP_XCH) + GO4K_VCF FREQUENCY(49),RESONANCE(28),VCFTYPE(BANDPASS) + GO4K_OUT GAIN(46), AUXSEND(0) +GO4K_END_PARAMDEF +GO4K_BEGIN_PARAMDEF(Global) + GO4K_ACC ACCTYPE(AUX) + GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(113),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(1),COUNT(8) + GO4K_FOP OP(FOP_XCH) + GO4K_DLL PREGAIN(40),DRY(128),FEEDBACK(103),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(9),COUNT(8) + GO4K_FOP OP(FOP_XCH) + GO4K_ACC ACCTYPE(OUTPUT) + GO4K_FOP OP(FOP_ADDP2) + GO4K_OUT GAIN(64), AUXSEND(16) +GO4K_END_PARAMDEF +go4k_synth_parameter_values_end +%ifdef USE_SECTIONS +section .g4kmuc5 data align=1 +%else +section .data +%endif +%ifdef GO4K_USE_DLL +global _go4k_delay_times +_go4k_delay_times + dw 0 + dw 1116 + dw 1188 + dw 1276 + dw 1356 + dw 1422 + dw 1492 + dw 1556 + dw 1618 + dw 1140 + dw 1212 + dw 1300 + dw 1380 + dw 1446 + dw 1516 + dw 1580 + dw 1642 + dw 22050 + dw 16537 +%endif diff --git a/BuildDLLs.script b/BuildDLLs.script new file mode 100644 index 0000000..57eabff --- /dev/null +++ b/BuildDLLs.script @@ -0,0 +1,55 @@ +# Compofiller Studio +# by Yzi +# +# BuildDLLs.script +# +# WE HAVE MANY TYPES OF SCRIPT FILES +# +# Build scripts +# * common variables/definitions script, which "bakes" stuff from configs into variables +# * DLL (test/debug) master script +# * EXE (run/release) master script +# +# Settings/configuration scripts +# * Project global script (which also serves as the project file?) +# * Configuration scripts (1 per configuration) +# +# SHADER_FILE + +# Explanation of automatically set target variables +# $@ expands to the target (i.e. text that's before the colon ':') +# $< expands to the first prerequisite (i.e. the first space-delimited string that's after the colon ':') +# $^ expands to all prerequisites (i.e. the whole text that's after the colon ':') + + + +include $(PROJECT_FILE) + +include $(CONFIG_FILE) + +include common.script + + + +# Audio debug/test DLL +debug_4klang.obj: debug_4klang_wrapper.asm 4klang.asm 4klang.inc + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(FORCED_4KLANG_OPTS) -o $@ $< + +debug_audio.obj: debug_audio.asm errormsg.inc + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) -o $@ $< + +debug_audio.dll: debug_audio.obj debug_4klang.obj + $(DEBUG_LINKER_EXE) $(DEBUG_LINKER_OPTS) -o $@ $^ $(DEBUG_LINKER_AUDIO_LIBS_PARAMS) + + +# Visuals debug/test DLL +#shader_code.obj: shader_code.asm $(SHADER_FILE) +# $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(VISUALS_ASM_OPTS) -o $@ $< + +debug_visuals.obj: debug_visuals.asm errormsg.inc + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(VISUALS_ASM_OPTS) -o $@ $< + +#debug_visuals.dll: debug_visuals.obj shader_code.obj +debug_visuals.dll: debug_visuals.obj + $(DEBUG_LINKER_EXE) $(DEBUG_LINKER_OPTS) -o $@ $^ $(DEBUG_LINKER_VISUALS_LIBS_PARAMS) + diff --git a/BuildEXE.script b/BuildEXE.script new file mode 100644 index 0000000..e0629e8 --- /dev/null +++ b/BuildEXE.script @@ -0,0 +1,31 @@ +# Compofiller Studio +# by Yzi +# +# BuildEXE.script + +include $(PROJECT_FILE) + +include $(CONFIG_FILE) + +include common.script + +PREPROCESS_SHADER_EXE="$(PROGRAM_DIR)\Tools\PreprocessShader.exe" + +TEMP_PROCESSED_SHADER_FILE=__temp_processed_shader.glsl + + +4klang.obj: 4klang.asm 4klang.inc + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(FORCED_4KLANG_OPTS) -o $@ $< + +$(TEMP_PROCESSED_SHADER_FILE): $(SHADER_FILE) + $(PREPROCESS_SHADER_EXE) $< $@ + +shader_code.obj: shader_code.asm $(TEMP_PROCESSED_SHADER_FILE) + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(VISUALS_ASM_OPTS) \ + -DTEMP_PROCESSED_SHADER_FILE=$(QUOTE)$(TEMP_PROCESSED_SHADER_FILE)$(QUOTE) -o $@ $< + +exemain.obj: exemain.asm + $(ASSEMBLER_EXE) $(ASSEMBLER_OPTS) $(VISUALS_ASM_OPTS) -o $@ $< + +$(OUTPUT_EXE_NAME): exemain.obj shader_code.obj 4klang.obj + $(FINAL_LINKER_EXE) $(FINAL_LINKER_OPTS) $(FINAL_LINKER_OUT_OPT)$@ $^ $(FINAL_LINKER_LIBS_PARAMS) diff --git a/MinifyShader.script b/MinifyShader.script new file mode 100644 index 0000000..6528831 --- /dev/null +++ b/MinifyShader.script @@ -0,0 +1,20 @@ +# Compofiller Studio +# by Yzi +# +# MinifyShader.script +# +# This script runs Shader Minifier +# +# Compofiller Studio provides this script with the SOURCE_FILE and DESTINATION_FILE variables + + +CLEAN_SHADER_EXE="$(PROGRAM_DIR)\Tools\CleanShader.exe" + +TEMP_CLEANED_SHADER_FILE=__temp_cleaned_shader.glsl + +# the clean-up tries to remove stuff that Shader Minifier can't handle +$(TEMP_CLEANED_SHADER_FILE): $(SOURCE_FILE) + $(CLEAN_SHADER_EXE) $< $@ + +$(DESTINATION_FILE): + "$(PROGRAM_DIR)\Tools\ShaderMinifier\shader_minifier.exe" $(TEMP_CLEANED_SHADER_FILE) -o $(DESTINATION_FILE) diff --git a/RunEXE.script b/RunEXE.script new file mode 100644 index 0000000..b91af77 --- /dev/null +++ b/RunEXE.script @@ -0,0 +1,11 @@ +# Compofiller Studio +# by Yzi +# +# RunEXE.script + +include $PROJECT_FILE + +include $CONFIG_FILE + +run: + $OUTPUT_EXE_NAME diff --git a/base.config b/base.config new file mode 100644 index 0000000..07ae4cd --- /dev/null +++ b/base.config @@ -0,0 +1,71 @@ +# Compofiller Studio by Yzi +# +# Base configuration file + +########### Music ############# +MUSIC_4KLANG_INC_FILE= +MUSIC_BEATS_PER_BAR=4.0 + +########### Visuals ############ +SHADER_FILE=shader.glsl +RESOLUTION_X=1920 +RESOLUTION_Y=1080 + +USE_TIME_UNIFORM=1 +TIME_UNIFORM_NAME='time' +USE_RESOLUTION_UNIFORM=1 +RESOLUTION_UNIFORM_NAME='resolution' + + +# Frame-to-texture, mipmaps +TWO_PASS_RENDERING=1 +FRAME_TO_TEXTURE=0 +USE_MIPMAP=0 +SECOND_PASS_NEGATIVE_TIME=1 + +# Texts +USE_TEXTS=1 +USE_TEXTS_UNIFORM=1 +TEXTS_UNIFORM_NAME='texts' +TEXT_BITMAP_RESOLUTION_X=1024 +TEXT_BITMAP_RESOLUTION_Y=1024 +TEXT_FONT_NAME='Arial' +TEXT_FONT_SIZE=120 +TEXT_FONT_STRIKEOUT=0 +TEXT_FONT_UNDERLINE=0 +TEXT_FONT_ITALIC=0 +TEXT_FONT_WEIGHT=256 +TEXT_FONT_ORIENTATION=0 +TEXT_FONT_ESCAPEMENT=0 +TEXT_FONT_WIDTH=0 +TEXT_CHARACTER_EXTRA_SPACING=0 +USE_WIDECHAR_TEXTS=0 + +########### Time base ########### +USE_TIME_DIVIDER_IN_X86_CODE=1 +TIME_DIVIDER=88200.000 +TIME_BASE=bars + +AUDIO_DELAY=2048 +PROD_END_TIME=4411648 + + +########### Final product ########### +# The name of the final EXE +OUTPUT_EXE_NAME=testing.exe + +# this is just the name/text of the GUI option, not the name of the linker executable +EXE_LINKER_PROGRAM=Crinkler + +QUOTE=\" + + +CRINKLER_ORDERTRIES=100 + + +AUDIO_BUFFER_ALLOCATED_LENGTH=4411648 +AUDIO_SAMPLING_RATE=44100 +LOOP_END=5.0 +LOOP_START=3.0 +LOOP_ENABLED=0 +TIME_DIVIDER_INT=88200 diff --git a/common.script b/common.script new file mode 100644 index 0000000..202b2a7 --- /dev/null +++ b/common.script @@ -0,0 +1,108 @@ +# Compofiller Studio by Yzi +# +# Parameter construction rules that both/all build scripts need, but can't reside in +# .config scripts, unless we support "deferred expansion". Which we don't, at least yet. + +# +# Note about spaces in path names: +# +# Any file name/path that includes $(PROGRAM_DIR) must be enclosed in quotes, like +# "$(PROGRAM_DIR)\Tools\Crinkler\crinkler.exe" or "$(PROGRAM_DIR)\Libs", because +# PROGRAM_DIR might contain spaces. +# +# Paths that are relative to the project directory, don't have to be enclosed in quotes, +# because Compofiller Studio changes the current directory to the project directory. +# All you have to do is make sure the file names don't contain spaces. +# + +VISUALS_USE_TIME_UNIFORM_DEFINE=-DUSE_TIME_UNIFORM=$(USE_TIME_UNIFORM) +VISUALS_TIME_UNIFORM_NAME_DEFINE=-DTIME_UNIFORM_NAME=$(TIME_UNIFORM_NAME) +VISUALS_USE_RESOLUTION_UNIFORM_DEFINE=-DUSE_RESOLUTION_UNIFORM=$(USE_RESOLUTION_UNIFORM) +VISUALS_RESOLUTION_UNIFORM_NAME_DEFINE=-DRESOLUTION_UNIFORM_NAME=$(RESOLUTION_UNIFORM_NAME) + + +VISUALS_ASM_OPTS=$(VISUALS_USE_TIME_UNIFORM_DEFINE) $(VISUALS_USE_RESOLUTION_UNIFORM_DEFINE) \ + $(VISUALS_TIME_UNIFORM_NAME_DEFINE) $(VISUALS_RESOLUTION_UNIFORM_NAME_DEFINE) \ + -DTWO_PASS_RENDERING=$(TWO_PASS_RENDERING) -DFRAME_TO_TEXTURE=$(FRAME_TO_TEXTURE) \ + -DUSE_MIPMAP=$(USE_MIPMAP) -DSECOND_PASS_NEGATIVE_TIME=$(SECOND_PASS_NEGATIVE_TIME) \ + -DRESOLUTION_X=$(RESOLUTION_X) -DRESOLUTION_Y=$(RESOLUTION_Y) \ + -DTIME_DIVIDER=$(TIME_DIVIDER) -DTIME_DIVIDER_INT=$(TIME_DIVIDER_INT) \ + -DAUDIO_SAMPLING_RATE=$(AUDIO_SAMPLING_RATE) \ + -DAUDIO_DELAY=$(AUDIO_DELAY) \ + -DAUDIO_BUFFER_ALLOCATED_LENGTH=$(AUDIO_BUFFER_ALLOCATED_LENGTH) \ + -DPROD_END_TIME=$(PROD_END_TIME) \ + -DTEXT_BITMAP_RESOLUTION_X=$(TEXT_BITMAP_RESOLUTION_X) -DTEXT_BITMAP_RESOLUTION_Y=$(TEXT_BITMAP_RESOLUTION_Y) \ + "-DTEXT_FONT_NAME=$(TEXT_FONT_NAME)" -DTEXT_FONT_SIZE=$(TEXT_FONT_SIZE) \ + -DTEXT_FONT_STRIKEOUT=$(TEXT_FONT_STRIKEOUT) \ + -DTEXT_FONT_UNDERLINE=$(TEXT_FONT_UNDERLINE) \ + -DTEXT_FONT_ITALIC=$(TEXT_FONT_ITALIC) \ + -DTEXT_FONT_WEIGHT=$(TEXT_FONT_WEIGHT) \ + -DTEXT_FONT_ORIENTATION=$(TEXT_FONT_ORIENTATION) \ + -DTEXT_FONT_ESCAPEMENT=$(TEXT_FONT_ESCAPEMENT) \ + -DTEXT_FONT_WIDTH=$(TEXT_FONT_WIDTH) \ + -DTEXT_CHARACTER_EXTRA_SPACING=$(TEXT_CHARACTER_EXTRA_SPACING) \ + -DTEXTS_UNIFORM_NAME=$(TEXTS_UNIFORM_NAME) \ + -DUSE_TEXTS=$(USE_TEXTS) -DUSE_TEXTS_UNIFORM=$(USE_TEXTS_UNIFORM) \ + -DUSE_WIDECHAR_TEXTS=$(USE_WIDECHAR_TEXTS) + + +# this doesn't need to go to the assembler anymore, because the shader goes via PreprocessShader.exe to a hard-coded file name +# -DSHADER_FILE=$(QUOTE)$(SHADER_FILE)$(QUOTE) + + +# We force 16 bit output. This prevents non-working audio and crash, when a 32 bit float format song is given. +FORCED_4KLANG_OPTS=-DGO4K_USE_16BIT_OUTPUT + + +ASSEMBLER_PROGRAM=yasm + +########### Tools ########### +ASSEMBLER_EXE="$(PROGRAM_DIR)\Tools\NASM\nasm.exe" +ASSEMBLER_OPTS=-f win32 -w-orphan-labels +# You could try this to get debug symbols, but it just doesn't seem to work. +#ASSEMBLER_OPTS=-w-orphan-labels -f win32 -F cv8 -g + + +# Linker for building the DLLs for testing in the GUI +DEBUG_LINKER_EXE="$(PROGRAM_DIR)\Tools\Linker\ld.exe" + +# Library path. Where are the .lib files located? +LIB_PATH="$(PROGRAM_DIR)\Libs" + + +######## Things for the debug DLL ######## +DEBUG_LINKER_OPTS=--dll -entry=DllMain@12 -L $(LIB_PATH) + +# Windows library import files needed for linking the DLL +DEBUG_LINKER_COMMON_LIBS_PARAMS=-l kernel32 -l user32 + +# for audio DLL +DEBUG_LINKER_AUDIO_LIBS_PARAMS=-l winmm $(DEBUG_LINKER_COMMON_LIBS_PARAMS) + +# for visuals DLL +DEBUG_LINKER_VISUALS_LIBS_PARAMS=$(DEBUG_LINKER_COMMON_LIBS_PARAMS) -l gdi32 -l opengl32 + + +########## EXE linker things ########### + +ifeq ($(EXE_LINKER_PROGRAM),Crinkler) +# Crinkler settings +# Linker for building standalone EXE files for running +FINAL_LINKER_EXE="$(PROGRAM_DIR)\Tools\Crinkler\crinkler.exe" +FINAL_LINKER_OPTS=/SUBSYSTEM:WINDOWS /ENTRY:t /COMPMODE:SLOW /HASHSIZE:200 /HASHTRIES:50 /ORDERTRIES:$(CRINKLER_ORDERTRIES) \ + /UNSAFEIMPORT /LIBPATH:$(LIB_PATH) /REPORT:crinkler_report.html /PROGRESSGUI +FINAL_LINKER_OUT_OPT=/OUT: +FINAL_LINKER_GENERAL_LIBS_PARAMS=kernel32.lib user32.lib +FINAL_LINKER_AUDIO_LIBS_PARAMS=winmm.lib +FINAL_LINKER_VISUALS_LIBS_PARAMS=gdi32.lib opengl32.lib +FINAL_LINKER_LIBS_PARAMS=$(FINAL_LINKER_GENERAL_LIBS_PARAMS) $(FINAL_LINKER_AUDIO_LIBS_PARAMS) $(FINAL_LINKER_VISUALS_LIBS_PARAMS) +else +# GNU ld settings +FINAL_LINKER_EXE="$(PROGRAM_DIR)\Tools\Linker\ld.exe" +FINAL_LINKER_OPTS=-e t -L $(LIB_PATH) +FINAL_LINKER_OUT_OPT=-o +FINAL_LINKER_GENERAL_LIBS_PARAMS=-l kernel32 -l user32 +FINAL_LINKER_AUDIO_LIBS_PARAMS=-l winmm +FINAL_LINKER_VISUALS_LIBS_PARAMS=-l gdi32 -l opengl32 +FINAL_LINKER_LIBS_PARAMS=$(FINAL_LINKER_GENERAL_LIBS_PARAMS) $(FINAL_LINKER_AUDIO_LIBS_PARAMS) $(FINAL_LINKER_VISUALS_LIBS_PARAMS) +endif diff --git a/debug_4klang_wrapper.asm b/debug_4klang_wrapper.asm new file mode 100644 index 0000000..d9e8e65 --- /dev/null +++ b/debug_4klang_wrapper.asm @@ -0,0 +1,35 @@ +; Compofiller Studio by Yzi +; Wrapper for 4klang.asm, so we can get our debug/test DLL to export the constants. + +%include "4klang.asm" + + +music_sample_rate: + dd SAMPLE_RATE + +music_bpm: + dd __float32__(%[BPM]) + +music_length_samples: + dd MAX_SAMPLES + +%macro EXPORT_FUNC 1 + export %1 + global _%1 + _%1: + %1: +%endmacro + +EXPORT_FUNC GetMusicSampleRate + mov eax, dword [music_sample_rate] + ret + +EXPORT_FUNC GetMusicBPM + ; mov eax, dword [music_bpm] + fld dword [music_bpm] + ret + +EXPORT_FUNC GetMusicLengthSamples + mov eax, dword [music_length_samples] + ret + diff --git a/debug_audio.asm b/debug_audio.asm new file mode 100644 index 0000000..d877e4e --- /dev/null +++ b/debug_audio.asm @@ -0,0 +1,426 @@ +; yasm -f win32 -o dlltest.obj dlltest.asm +; ld --dll -entry=DllMain@12 -L C:\utils -o dlltest.dll dlltest.obj -l user32 + +; Compofiller Studio by Yzi +; +; Debug DLL for music stuff +; + + +%include "errormsg.inc" + +section .text + +; .start: + +global DllMain@12 +DllMain@12: ; This code is required in .dll files + mov eax,1 + ret 12 + + +; extern _midiOutOpen@20 +; extern __imp__midiOutOpen@20 +; extern _midiOutShortMsg@8 +; extern __imp__midiOutShortMsg@8 +; extern _timeGetTime@0 +; extern __imp__timeGetTime@0 + + +loppu: + push 0 + call [__imp__ExitProcess@4] + + ret + +extern _MessageBeep@4 +extern __imp__MessageBeep@4 +beepquit: + push 0xFFFFFFFF + call [__imp__MessageBeep@4] + jmp loppu + + +; ------------------------------ STUFF FOR PCM/4KLANG MUSIC ------------------------- +;section .bss +; .bss declares an uninitialized data section +section .data + +; !!! TODO sampling rate is coded in two places now, here and 4klang.ini +audio_sampling_rate equ 44100 +;audio_length_seconds equ (2*60) +;audio_length_samples equ (audio_length_seconds*audio_sampling_rate*2) + + +audio_thread_handle: dd 0 + +; "rendered audio buffer" means the rendered audio length, +; as opposed to "playback buffer" which might be +; - shorter, if we start playback from the middle of rendered audio +; - longer, if we play all the way from start to end of demo, and there's a positive audio offset/delay +rendered_audio_buffer_ptr: dd 0 + + +; loop parameters +audio_loop_enabled: dd 0 + + ; resw audio_length_samples + +global hWaveOut +hWaveOut: dd 0 + +; Flags for WaveHDR.dwFlags +WHDR_BEGINLOOP equ 4 +WHDR_ENDLOOP equ 8 + +section .data + +global WaveHDR +WaveHDR: +audio_playback_buffer_ptr: +WaveHDR_lpData: dd 0 +audio_playback_length_bytes: +WaveHDR_dwBufferLength: dd 0 ; audio_length_samples*2 ; audio buffer length in bytes +WaveHDR_dwBytesRecorded: dd 0 +WaveHDR_dwUser: dd 0 +WaveHDR_dwFlags: dd 0 +WaveHDR_dwLoops: dd 0 +WaveHDR_lpNext: dd 0 +WaveHDR_reserved: dd 0 + +; long GetPosition() { +; static MMTIME MMTime = { TIME_SAMPLES, 0}; +; waveOutGetPosition(hWaveOut, &MMTime, sizeof(MMTIME)); +; return (MMTime.u.sample); +; } + +global pcmFormat +pcmFormat: +pcmFormat_wFormatTag: dw 1 ; WAVE_FORMAT_PCM +pcmFormat_nChannels: dw 2 ; stereo +pcmFormat_nSamplesPerSec: dd audio_sampling_rate +pcmFormat_nAvgBytesPerSec: dd audio_sampling_rate*4 ; for buffer estimation +pcmFormat_nBlockAlign: dw 4 ; block size of data +pcmFormat_wBitsPerSample: dw 16 +pcmFormat_cbSize: dw 0 + +; void Play() { +; static WAVEHDR WaveHDR = { (LPSTR)(myMuzik), MZK_NUMSAMPLESC * 2}; + +; // Define output format +; static WAVEFORMATEX pcmFormat = { +; WAVE_FORMAT_PCM, // WORD wFormatTag; /* format type */ +; 2, // WORD nChannels; /* number of channels (i.e. mono, stereo...) */ +; 44100, // DWORD nSamplesPerSec; /* sample rate */ +; 4 * 44100, // DWORD nAvgBytesPerSec; /* for buffer estimation */ +; 4, // WORD nBlockAlign; /* block size of data */ +; 16, // WORD wBitsPerSample; /* number of bits per sample of mono data */ +; 0, // WORD cbSize; /* the count in bytes of the size of */ +; }; + +global MMTime +; MMTIME is a "union" struct that can be used for many different contents based on the first +MMTime: dd 2 ; wType: TIME_SAMPLES = 2 +MMTime_sample: dd 0 ; actual position value + db 0, 0, 0, 0 ; some room for other cases + + + +; ----------------- + +section .text +; the __imp__ versions refer to the corresponding import address table entries + +; 4klang +extern __4klang_render@4 + +; General Windows stuff +extern _ExitProcess@4 +extern __imp__ExitProcess@4 +extern _CreateThread@24 +extern __imp__CreateThread@24 +extern _TerminateThread@8 +extern __imp__TerminateThread@8 +extern _Sleep@4 +extern __imp__Sleep@4 +extern _WaitForSingleObject@8 +extern __imp_WaitForSingleObject@8 + +; Windows Multimedia +extern _waveOutOpen@24 +extern __imp__waveOutOpen@24 +extern _waveOutPrepareHeader@12 +extern __imp__waveOutPrepareHeader@12 +extern _waveOutWrite@12 +extern __imp__waveOutWrite@12 +extern _waveOutGetPosition@12 +extern __imp__waveOutGetPosition@12 +extern _waveOutReset@4 +extern __imp__waveOutReset@4 +extern _waveOutClose@4 +extern __imp__waveOutClose@4 + +export GetRenderedAudioBufferPtr +global _GetRenderedAudioBufferPtr +_GetRenderedAudioBufferPtr: +GetRenderedAudioBufferPtr: + mov eax, dword [rendered_audio_buffer_ptr] + ret + + +export SetRenderedAudioBufferPtr +global _SetRenderedAudioBufferPtr +_SetRenderedAudioBufferPtr: +SetRenderedAudioBufferPtr: + mov eax, [esp+4] + mov [rendered_audio_buffer_ptr], eax + ret 4 + +export StartAudioRendererThread +global _StartAudioRendererThread +_StartAudioRendererThread +StartAudioRendererThread: + push 0 + push 0 + push dword [rendered_audio_buffer_ptr] + push __4klang_render@4 + push 0 + push 0 + ;call _CreateThread@24 + call [__imp__CreateThread@24] + mov [audio_thread_handle], eax + FAIL_ON_WINDOWS_ERROR CreateThread_string + + ret + + +export KillAudioRendererThread +global _KillAudioRendererThread +_KillAudioRendererThread +KillAudioRendererThread: + + ; already killed by this function, or never even started? + cmp dword [audio_thread_handle], 0 + je noeijuu + + push 0 + push dword [audio_thread_handle] + call _WaitForSingleObject@8 + cmp eax, 0 ; WAIT_OBJECT_0 = 0 + je already_died +; now we hope that the thread doesn't finish after windows told us it's "still alive" +; but before we get to call TerminateThread + + push 0 + push dword [audio_thread_handle] + call [__imp__TerminateThread@8] + FAIL_ON_WINDOWS_ERROR TerminateThread_string + + ; short sleep and let's hope for the best + push 50 + call [__imp__Sleep@4] + +already_died: + mov dword [audio_thread_handle], 0 +noeijuu: + ret + + +export GetWaveOutHandle +global _GetWaveOutHandle +_GetWaveOutHandle +GetWaveOutHandle: + mov eax, [hWaveOut] + ret + +export GetAudioRendererThreadHandle +global _GetAudioRendererThreadHandle +_GetAudioRendererThreadHandle +GetAudioRendererThreadHandle: + mov eax, [audio_thread_handle] + ret + + +export GetAudioPlaybackBufferPtr +global _GetAudioPlaybackBufferPtr +_GetAudioPlaybackBufferPtr: +GetAudioPlaybackBufferPtr: + mov eax, dword [audio_playback_buffer_ptr] + ret + + +export SetAudioPlaybackBufferPtr +global _SetAudioPlaybackBufferPtr +_SetAudioPlaybackBufferPtr: +SetAudioPlaybackBufferPtr: + mov eax, [esp+4] + mov [audio_playback_buffer_ptr], eax + ret 4 + + +export GetAudioPlaybackBufferLengthBytes +global _GetAudioPlaybackBufferLengthBytes +_GetAudioPlaybackBufferLengthBytes: +GetAudioPlaybackBufferLengthBytes: + mov eax, [audio_playback_length_bytes] + ret + +export SetAudioPlaybackBufferLengthBytes +global _SetAudioPlaybackBufferLengthBytes +_SetAudioPlaybackBufferLengthBytes: +SetAudioPlaybackBufferLengthBytes: + mov eax, [esp+4] + mov [audio_playback_length_bytes], eax + ret 4 + + +; For GNU ld to be able to create a DLL from our object code, it has to +; have both _Play and Play symbols and _Play as global. +;export Play +;global _Play +; _Play: +;Play: + ;call StartAudioRendererThread + + + ; Wait a bit so that the 4klang's renderer thread gets well ahead of playback position +; push 200 +; call [__imp__Sleep@4] + + ;call StartAudio + +; mov eax, 1 +; ret + + +section .data + + +global CreateThread_string +CreateThread_string db 'CreateThread', 0 + +global TerminateThread_string +TerminateThread_string db 'TerminateThread', 0 + +global waveOutOpen_string +waveOutOpen_string db 'waveOutOpen', 0 + +global waveOutPrepareHeader_string +waveOutPrepareHeader_string db 'waveOutPrepareHeader', 0 + +global waveOutWrite_string +waveOutWrite_string db 'waveOutWrite', 0 + +global waveOutReset_string +waveOutReset_string db 'waveOutReset', 0 + +global waveOutClose_string +waveOutClose_string db 'waveOutClose', 0 + +global waveOutGetPosition_string +waveOutGetPosition_string db 'waveOutGetPosition', 0 + + +section .text + +export StartAudio +global _StartAudio +_StartAudio: +StartAudio: + mov dword [WaveHDR_dwFlags], 0 + mov dword [WaveHDR_dwLoops], 0 + + cmp dword [audio_loop_enabled], 0 + je no_looping + + mov dword [WaveHDR_dwFlags], WHDR_BEGINLOOP + WHDR_ENDLOOP + mov dword [WaveHDR_dwLoops], -1 +no_looping: + + push 0 + push 0 + push 0 + push pcmFormat + push -1 + push hWaveOut + call [__imp__waveOutOpen@24] + FAIL_ON_WINMM_ERROR waveOutOpen_string + + push 32 ; sizeof(WaveHDR) + push WaveHDR + push DWORD [hWaveOut] + call [__imp__waveOutPrepareHeader@12] + FAIL_ON_WINMM_ERROR waveOutPrepareHeader_string + + push 32 ; sizeof(WaveHDR) + push WaveHDR + push DWORD [hWaveOut] + call [__imp__waveOutWrite@12] + FAIL_ON_WINMM_ERROR waveOutWrite_string + + mov eax, 1 + ret + + +export StopAudio +global _StopAudio +_StopAudio: +StopAudio: + push DWORD [hWaveOut] + call [__imp__waveOutReset@4] + FAIL_ON_WINMM_ERROR waveOutReset_string + + push DWORD [hWaveOut] + call [__imp__waveOutClose@4] + FAIL_ON_WINMM_ERROR waveOutClose_string + + mov DWORD [hWaveOut], 0 + + mov eax, 1 + ret + + +; // _4klang_render(myMuzik); +; CreateThread(0, 0, (LPTHREAD_START_ROUTINE)_4klang_render, myMuzik, 0, 0); + +; Sleep(200); +; waveOutOpen( &hWaveOut, WAVE_MAPPER, &pcmFormat, NULL, 0, CALLBACK_NULL ); +; waveOutPrepareHeader( hWaveOut, &WaveHDR, sizeof(WaveHDR) ); +; waveOutWrite ( hWaveOut, &WaveHDR, sizeof(WaveHDR) ); +;} + +; ---- GetPosition returns the current audio playback position ---- +export GetCurrentAudioPosition +global _GetCurrentAudioPosition +_GetCurrentAudioPosition: +GetCurrentAudioPosition: + push 12 ; sizeof MMTIME struct + push MMTime + push DWORD [hWaveOut] + call [__imp__waveOutGetPosition@12] + + FAIL_ON_WINMM_ERROR waveOutGetPosition_string + + mov eax, [MMTime_sample] + ret + +;export SetPosition +;global _SetPosition +;_SetPosition: +;SetPosition: +; TODO + +; ret 4 + +; This isn't actually used, using Winmm audio for seamless looping is too much trouble + +export SetAudioLoopEnabled +global _SetAudioLoopEnabled +_SetAudioLoopEnabled: +SetAudioLoopEnabled: + mov eax, [esp+4] + mov [audio_loop_enabled], eax + ret 4 + + +; -------------------- ^^^^^ END OF MUSIC / AUDIO DATA STUFF ^^^^^ -------------------- diff --git a/debug_audio.dll b/debug_audio.dll new file mode 100644 index 0000000000000000000000000000000000000000..93f604d98f4e11146e2c4ce0cea06920316750f3 GIT binary patch literal 40168 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 literal 0 HcmV?d00001 diff --git a/debug_visuals.asm b/debug_visuals.asm new file mode 100644 index 0000000..1aab1d5 --- /dev/null +++ b/debug_visuals.asm @@ -0,0 +1,1519 @@ +; yasm -f win32 -o dlltest.obj dlltest.asm +; ld --dll -entry=DllMain@12 -L C:\utils -o dlltest.dll dlltest.obj -l user32 + +; Compofiller Studio by Yzi +; +; Debug DLL for visuals +; +; ------------------------------------------------- map individual features to needed USE_... stuff +%include "map_features_to_use_defines.inc" + +%include "errormsg.inc" + +%ifdef USE_TEXTS +%include "timings_and_texts.inc" +%endif + +; ..start: + + + extern _Beep@8 + extern __imp__Beep@8 + +DLL_PROCESS_ATTACH equ 1 +DLL_PROCESS_DETACH equ 0 +DLL_THREAD_ATTACH equ 2 +DLL_THREAD_DETACH equ 3 + +global DllMain@12 +DllMain@12: ; This code is required in .dll files + mov eax, 1 + ret 12 + +; debugging code: comment out the above to hear beeps when the dll is loaded and unloaded + cmp dword [esp+8], DLL_PROCESS_ATTACH + je msg_DLL_PROCESS_ATTACH + + cmp dword [esp+8], DLL_PROCESS_DETACH + je msg_DLL_PROCESS_DETACH + + cmp dword [esp+8], DLL_THREAD_ATTACH + je msg_DLL_THREAD_ATTACH + + cmp dword [esp+8], DLL_THREAD_DETACH + je msg_DLL_THREAD_DETACH + +; push 5000 ; dwDuration +; push 200 ; dwFreq (Hz) +; call [__imp__Beep@8] + + +exitDllMain: +; https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx +; "When the system calls the DllMain function with the DLL_PROCESS_ATTACH value, +; the function returns TRUE if it succeeds or FALSE if initialization fails. If the return +; value is FALSE when DllMain is called because the process uses the LoadLibrary +; function, LoadLibrary returns NULL. (The system immediately calls your entry-point +; function with DLL_PROCESS_DETACH and unloads the DLL.)" + mov eax, 1 + ret 12 + +msg_DLL_PROCESS_ATTACH: +; DllMain shouldn't call things in User32, so we're using Beep() from Kernel32 + push 500 ; dwDuration + push 400 ; dwFreq (Hz) + call [__imp__Beep@8] + +; push msgstr_DLL_PROCESS_ATTACH +; call ShowErrorMessage + jmp exitDllMain + +msg_DLL_PROCESS_DETACH: +; push msgstr_DLL_PROCESS_DETACH +; call ShowErrorMessage + push 500 ; dwDuration + push 100 ; dwFreq (Hz) + call [__imp__Beep@8] + jmp exitDllMain + +msg_DLL_THREAD_ATTACH: +; push msgstr_DLL_THREAD_ATTACH +; call ShowErrorMessage + push 50 ; dwDuration + push 400 ; dwFreq (Hz) + call [__imp__Beep@8] + jmp exitDllMain + +msg_DLL_THREAD_DETACH: +; push msgstr_DLL_THREAD_DETACH +; call ShowErrorMessage + push 50 ; dwDuration + push 100 ; dwFreq (Hz) + call [__imp__Beep@8] + jmp exitDllMain + + +;msgstr_DLL_PROCESS_ATTACH: db "debug_visuals.dll / DllMain(... DLL_PROCESS_ATTACH ...)", 0 +;msgstr_DLL_PROCESS_DETACH: db "debug_visuals.dll / DllMain(... DLL_PROCESS_DETACH ...)", 0 +;msgstr_DLL_THREAD_ATTACH: db "debug_visuals.dll / DllMain(... DLL_THREAD_ATTACH ...)", 0 +;msgstr_DLL_THREAD_DETACH: db "debug_visuals.dll / DllMain(... DLL_THREAD_DETACH ...)", 0 + + +; screenvariables +section .data + +PFD_DOUBLEBUFFER equ 0x00000001 +PFD_DRAW_TO_WINDOW equ 0x00000004 +PFD_DRAW_TO_BITMAP equ 0x00000008 +PFD_SUPPORT_OPENGL equ 0x00000020 + +global pfd +pfd: + db 0x00, 0x00 ; nSize + db 0x00, 0x00 ; nVersion + ; dwFlags: + db PFD_DOUBLEBUFFER + PFD_SUPPORT_OPENGL + PFD_DRAW_TO_BITMAP ; 0x21 + db 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00 +DMSCREENSETTINGS: + db 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00 + db 0xD0, 0x02 + + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + + +global WindowHandle +WindowHandle: dd 0 + +global WindowDC +WindowDC: dd 0 + +global glContext +glContext: dd 0 + + +%include "glconstants.inc" + + + +SHADER_INFO_LOG_MAX_LENGTH equ 1000 +shader_info_log_length: dd 0 +shader_info_log: times SHADER_INFO_LOG_MAX_LENGTH dd 0 + +section .text +EXPORT_FUNC GetShaderInfoLog + mov eax, shader_info_log + ret + +; getters for those +section .text + +export GetGLContext +global _GetGLContext +_GetGLContext: +GetGLContext: + mov eax, [glContext] + ret + +export GetWindowHandle +global _GetWindowHandle +_GetWindowHandle: +GetWindowHandle: + mov eax, [WindowHandle] + ret + +export GetWindowDC +global _GetWindowDC +_GetWindowDC: +GetWindowDC: + mov eax, [WindowDC] + ret + + +section .data + +; extern shader_glsl + +global seireripointteri +; seireripointteri: dd shader_glsl +seireripointteri: dd 0 + + +global glCreateProgram_string +glCreateProgram_string: db 'glCreateProgram', 0 + +global glDeleteProgram_string +glDeleteProgram_string: db 'glDeleteProgram', 0 + +global glCreateShader_string +glCreateShader_string: db 'glCreateShader', 0 + +global glDeleteShader_string +glDeleteShader_string: db 'glDeleteShader', 0 + +global glDetachShader_string +glDetachShader_string: db 'glDetachShader', 0 + +global glShaderSource_string +glShaderSource_string: db 'glShaderSource', 0 + +global glCompileShader_string +glCompileShader_string: db 'glCompileShader', 0 + +global glAttachShader_string +glAttachShader_string: db 'glAttachShader', 0 + +global glIsShader_string +glIsShader_string: db 'glIsShader', 0 + +global glGetShaderInfoLog_string +glGetShaderInfoLog_string: db 'glGetShaderInfoLog', 0 + +global glLinkProgram_string +glLinkProgram_string: db 'glLinkProgram', 0 + +global glUseProgram_string +glUseProgram_string: db 'glUseProgram', 0 + +global glCreateShaderProgramv_string +glCreateShaderProgramv_string: db 'glCreateShaderProgramv', 0 + +%ifdef USE_UNIFORMS +global glUniform1f_string +glUniform1f_string: db 'glUniform1f', 0 + +global glUniform1i_string +glUniform1i_string: db 'glUniform1i', 0 + +global glUniform2f_string +glUniform2f_string: db 'glUniform2f', 0 + +global glGetUniformLocation_string +glGetUniformLocation_string: db 'glGetUniformLocation', 0 +%endif + +global glActiveTexture_string +glActiveTexture_string: db 'glActiveTexture', 0 + +global glBindTexture_string +glBindTexture_string: db 'glBindTexture', 0 + +global glTexParameteri_string +glTexParameteri_string: db 'glTexParameteri', 0 + +global glCopyTexImage2D_string +glCopyTexImage2D_string: db 'glCopyTexImage2D', 0 + +global glGenerateMipmap_string +glGenerateMipmap_string: db 'glGenerateMipmap', 0 + + ; User32 +global CreateWindowEx_string +CreateWindowEx_string db 'CreateWindowEx', 0 + +; User32 +global ChangeDisplaySettings_string +ChangeDisplaySettings_string db 'ChangeDisplaySettings', 0 + +; User32 +global GetDC_string +GetDC_string db 'GetDC', 0 + +; User32 +global ReleaseDC_string +ReleaseDC_string db 'ReleaseDC', 0 + +; Gdi32 +global ChoosePixelFormat_string +ChoosePixelFormat_string db 'ChoosePixelFormat', 0 + +; Gdi32 +global SetPixelFormat_string +SetPixelFormat_string db 'SetPixelFormat', 0 + +; Opengl32 +global wglCreateContext_string +wglCreateContext_string db 'wglCreateContext', 0 + +; Opengl32 +global wglMakeCurrent_string +wglMakeCurrent_string db 'wglMakeCurrent', 0 + +; Opengl32 +global wglGetProcAddress_string +wglGetProcAddress_string db 'wglGetProcAddress', 0 + +; Opengl32 +global glColor3us_string +glColor3us_string db 'glColor3us', 0 + +global glColor3s_string +glColor3s_string db 'glColor3s', 0 + +; Opengl32 +global glRecti_string +glRecti_string db 'glRecti', 0 + +; Gdi32 +global SwapBuffers_string +SwapBuffers_string db 'SwapBuffers', 0 + +; ___ OpenGL object handles ___ + +section .data +gl_program: dd 0 +gl_shader: dd 0 + +%ifdef USE_TIME_UNIFORM +time_uniform_loc: dd 0 +time_uniform_name: db TIME_UNIFORM_NAME, 0 +%endif + +%ifdef USE_RESOLUTION_UNIFORM +resolution_uniform_loc: dd 0 +resolution_uniform_name: db RESOLUTION_UNIFORM_NAME, 0 +%endif + +%ifdef USE_TEXTS_UNIFORM +texts_uniform_loc: dd 0 +texts_uniform_name: db TEXTS_UNIFORM_NAME, 0 +%endif + +%ifdef TIME_DIVIDER_IS_INTEGER + time_divider: dd (%[TIME_DIVIDER]) +%else + time_divider: dd __float32__(%[TIME_DIVIDER]) +%endif + + + +section .text + +; static GLchar *seireripointteri = &shader_glsl; + + ;extern _MessageBoxA@16 +;%define MessageBox _MessageBoxA@16 + +; global DllMain@12 + +; __imp__ + +extern _ChangeDisplaySettingsA@8 +extern __imp__ChangeDisplaySettingsA@8 +extern _CreateWindowExA@48 +extern __imp__CreateWindowExA@48 +extern _GetDC@4 +extern __imp__GetDC@4 +extern _ReleaseDC@8 +extern __imp__ReleaseDC@8 +extern _ChoosePixelFormat@8 +extern __imp__ChoosePixelFormat@8 +extern _SetPixelFormat@12 +extern __imp__SetPixelFormat@12 +extern _wglCreateContext@4 +extern __imp__wglCreateContext@4 +extern _wglMakeCurrent@8 +extern __imp__wglMakeCurrent@8 +extern _wglGetProcAddress@4 +extern __imp__wglGetProcAddress@4 +extern _PeekMessageA@20 +extern __imp__PeekMessageA@20 +extern _ShowCursor@4 +extern __imp__ShowCursor@4 +extern _glRecti@16 +extern __imp__glRecti@16 +extern _glColor3us@12 +extern __imp__glColor3us@12 +extern _glColor3s@12 +extern __imp__glColor3s@12 +extern _SwapBuffers@4 +extern __imp__SwapBuffers@4 +extern _GetAsyncKeyState@4 +extern __imp__GetAsyncKeyState@4 +extern _glGetError@0 +extern __imp__glGetError@0 + +; ---------- textures -------- +extern _glBindTexture@8 +extern __imp__glBindTexture@8 +extern _glTexParameteri@12 +extern __imp__glTexParameteri@12 +extern _glCopyTexImage2D@32 +extern __imp__glCopyTexImage2D@32 +; --------------------------- + + + + +%ifdef USE_TEXTS +; --- functions --- Gdi32.Lib +; CreateCompatibleDC@4 HDC CreateCompatibleDC(HDC hdc) +extern _CreateCompatibleDC@4 +extern __imp__CreateCompatibleDC@4 + +; extern __imp__CreateDCA@16 + +; CreateDIBSection@24 HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) +extern _CreateDIBSection@24 +extern __imp__CreateDIBSection@24 + +; CreateFontA@56 HFONT CreateFontA(int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCSTR pszFaceName) +extern _CreateFontA@56 +extern __imp__CreateFontA@56 + +; SelectObject@8 HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) +extern _SelectObject@8 +extern __imp__SelectObject@8 + + +extern _DeleteObject@4 +extern __imp__DeleteObject@4 + + +extern _DeleteDC@4 +extern __imp__DeleteDC@4 + + +; SetBkColor@8 COLORREF SetBkColor(HDC hdc, COLORREF color) +extern _SetBkColor@8 +extern __imp__SetBkColor@8 + +; SetTextColor@8 COLORREF SetTextColor(HDC hdc, COLORREF color) +extern _SetTextColor@8 +extern __imp__SetTextColor@8 + +; SetTextCharacterExtra@8 int SetTextCharacterExtra(HDC hdc, int extra) +extern _SetTextCharacterExtra@8 +extern __imp__SetTextCharacterExtra@8 + +; SetTextAlign@8 UINT SetTextAlign(HDC hdc, UINT align) +extern _SetTextAlign@8 +extern __imp__SetTextAlign@8 + +; SetTextJustification@8 BOOL SetTextJustification(HDC hdc, int extra, int count) +extern _SetTextJustification@12 +extern __imp__SetTextJustification@12 + + +; HGDIOBJ GetStockObject(int i) +extern _GetStockObject@4 +extern __imp__GetStockObject@4 + + +; --- functions --- User32.Lib +; DrawText@20 int DrawText(HDC hdc, LPCTSTR lpchText, int cchText, LPRECT lprc, UINT format) +%ifdef USE_WIDECHAR_TEXTS +extern _DrawTextW@20 +extern __imp__DrawTextW@20 +%else +extern _DrawTextA@20 +extern __imp__DrawTextA@20 +%endif + +; FillRect@12 int FillRect(HDC *hDC, const RECT *lprc, HBRUSH hbr) +extern _FillRect@12 +extern __imp__FillRect@12 + + +; ---- + +extern _glGenTextures@8 +extern __imp__glGenTextures@8 + +extern _glDeleteTextures@8 +extern __imp__glDeleteTextures@8 + +extern _glTexImage2D@36 +extern __imp__glTexImage2D@36 + + +; --- other --- +; font name e.g. "Times New Roman" + +%include "winconstants.inc" + + +section .data +hardcoded_font_name: db TEXT_FONT_NAME, 0 + +global text_font_name +text_font_name: dd hardcoded_font_name + +; global text_string_ptr +; text_string_ptr: dd 0 + +%endif + + +section .text + +extern _ExitProcess@4 +extern __imp__ExitProcess@4 + + +export CreateWindow +global _CreateWindow +_CreateWindow: +CreateWindow: + + push 0 + push 0 + push 0 + push 0 + push RESOLUTION_Y + push RESOLUTION_X + push 0 + push 0 + ; see WinUser.h for constant values + ; push (WS_EX_APPWINDOW | WS_VISIBLE | WS_SYSMENU) + push 0x00040000 | 0x10000000 | 0x00080000 + push 0 + push 0xC018 ; http://www.pouet.net/topic.php?which=9894 + push 0 + call [__imp__CreateWindowExA@48] + FAIL_ON_WINDOWS_ERROR CreateWindowEx_string + + mov [WindowHandle], eax + ret + + +export CreateFullscreenWindow +global _CreateFullscreenWindow +CreateFullscreenWindow: +_CreateFullscreenWindow: + push 4 + push DMSCREENSETTINGS + call [__imp__ChangeDisplaySettingsA@8] + ; RET_ON_WINDOWS_ERROR ChangeDisplaySettings_string + + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0x91000000 + push 0 + push 0xC018 ; http://www.pouet.net/topic.php?which=9894 + push 0 + call [__imp__CreateWindowExA@48] + FAIL_ON_WINDOWS_ERROR CreateWindowEx_string + + mov [WindowHandle], eax + ret + + + +export SetWindowHandle +global _SetWindowHandle +_SetWindowHandle: +SetWindowHandle: + mov eax, [esp+4] + mov [WindowHandle], eax + ret 4 + + +export SetWindowDC +global _SetWindowDC +_SetWindowDC: +SetWindowDC: + mov eax, [esp+4] + mov [WindowDC], eax + ret 4 + + +export SetUpGLContext +global _SetUpGLContext +_SetUpGLContext +SetUpGLContext: + push dword [WindowHandle] + call [__imp__GetDC@4] + mov [WindowDC], eax + FAIL_ON_WINDOWS_ERROR GetDC_string + + +export SetUpGLContextForDC +global _SetUpGLContextForDC +_SetUpGLContextForDC +SetUpGLContextForDC: + push pfd + push dword [WindowDC] + call [__imp__ChoosePixelFormat@8] + FAIL_ON_WINDOWS_ERROR ChoosePixelFormat_string + + push pfd + push eax + push dword [WindowDC] + call [__imp__SetPixelFormat@12] + FAIL_ON_WINDOWS_ERROR SetPixelFormat_string + + push dword [WindowDC] + call [__imp__wglCreateContext@4] + mov [glContext], eax + FAIL_ON_WINDOWS_ERROR wglCreateContext_string + + push dword [glContext] + push dword [WindowDC] + call [__imp__wglMakeCurrent@8] + FAIL_ON_WINDOWS_ERROR wglMakeCurrent_string + + mov eax, 1 + ret + +export FreeGLContext +global _FreeGLContext +_FreeGLContext +FreeGLContext: + + push 0 + push 0 + call [__imp__wglMakeCurrent@8] + FAIL_ON_WINDOWS_ERROR wglMakeCurrent_string + + push dword [WindowDC] + push dword [WindowHandle] + call [__imp__ReleaseDC@8] + FAIL_ON_WINDOWS_ERROR ReleaseDC_string + + mov eax, 1 + ret + + + +export SetShaderSourcePtr +global _SetShaderSourcePtr +_SetShaderSourcePtr +SetShaderSourcePtr: + mov eax, [esp+4] + +; push eax ; dword [seireripointteri] +; call ShowErrorMessage + + mov [seireripointteri], eax + + mov eax, 1 + ret 4 + +export GetShaderSourcePtr +global _GetShaderSourcePtr +_GetShaderSourcePtr +GetShaderSourcePtr: + mov eax, [seireripointteri] + ret + + +CheckShaderInfoLog: + + push glGetShaderInfoLog_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push shader_info_log + push shader_info_log_length + push SHADER_INFO_LOG_MAX_LENGTH + push dword [gl_shader] + call eax + + cmp dword [shader_info_log_length], 0 + je no_shader_error_log + +; push shader_info_log +; call ShowErrorMessage + +; push 0 +; call [__imp__ExitProcess@4] + +no_shader_error_log: + ret + +export CompileShader +global _CompileShader +_CompileShader +CompileShader: + mov dword [shader_info_log_length], 0 + mov byte [shader_info_log], 0 + + CLEAR_LAST_FAILED_OPERATION_INFO + + push glCreateProgram_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + call eax + mov [gl_program], eax + FAIL_ON_GL_ERROR glCreateProgram_string + + push glCreateShader_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push 0x8B30 ; GL_FRAGMENT_SHADER + call eax + + mov [gl_shader], eax + FAIL_ON_GL_ERROR glCreateShader_string + + + push glShaderSource_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push 0 + push seireripointteri + push 1 + push dword [gl_shader] + + call eax + FAIL_ON_GL_ERROR glShaderSource_string + + push glCompileShader_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_shader] + call eax + JUMP_ON_GL_ERROR .fail_and_infolog, glCompileShader_string + + call CheckShaderInfoLog + + push glAttachShader_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_shader] + push dword [gl_program] + call eax + FAIL_ON_GL_ERROR glAttachShader_string + + push glLinkProgram_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_program] + call eax + FAIL_ON_GL_ERROR glLinkProgram_string + + push glUseProgram_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + + push dword [gl_program] + call eax + JUMP_ON_GL_ERROR .fail, glUseProgram_string + + mov eax, 1 + ret + +.fail_and_infolog: + call CheckShaderInfoLog + +.fail + mov eax, 0 + ret + + +; Free all the GL resources allocated by CompileShader +export FreeShaderStuff +global _FreeShaderStuff +_FreeShaderStuff +FreeShaderStuff: + +; shader + cmp dword [gl_shader], 0 + je .skipdeleteshader + + ; glDetachShader + push glDetachShader_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_shader] + push dword [gl_program] + call eax + FAIL_ON_GL_ERROR glDetachShader_string + + + ; glDeleteShader + push glDeleteShader_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_shader] + call eax + FAIL_ON_GL_ERROR glDeleteShader_string + + mov dword [gl_shader], 0 +.skipdeleteshader: + + +; program + cmp dword [gl_program], 0 + je .skipdeleteprogram + + push glDeleteProgram_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword [gl_program] + call eax + FAIL_ON_GL_ERROR glDeleteProgram_string + + mov dword [gl_program], 0 +.skipdeleteprogram: + + mov eax, 1 + ret + +; --------- texts + + +export SetTextFontName +global _SetTextFontName +_SetTextFontName: +SetTextFontName: +%ifdef USE_TEXTS + mov eax, [esp+4] + mov [text_font_name], eax +%endif + ret 4 + + + + +%ifdef USE_TEXTS + + +section .data +%ifdef GEN_TEXTURES +texts_gl_texture_name: dd 0 +%endif + +current_text_ptr: dd _string0 +current_timing_ptr: dd text_string_timings + +textsDC: dd 0 +textsBitmapHandle: dd 0 +textsBitmapBitsPtr: dd 0 +textsFontHandle: dd 0 + +TextRectangle: ; we overlap this with BitmapInfo + dd 0 + ; , 0, TEXT_BITMAP_RESOLUTION_X, TEXT_BITMAP_RESOLUTION_Y + +BitmapInfo: ; bmiHeader + dd 40 ; biSize, it doesn't seem to work if you give 0 in this field +BitmapInfo_biWidth: dd TEXT_BITMAP_RESOLUTION_X ; biWidth +BitmapInfo_biHeight: dd TEXT_BITMAP_RESOLUTION_Y ; biHeight +BitmapInfo_biPlanes: dw 1 ; biPlanes + dw 32 ; biBitCount + dd 0 ; biCompression + dd 0 ; biSizeImage + dd 0 ; biXPelsPerMeter + dd 0 ; biYPelsPerMeter + dd 0 ; biClrUsed + dd 0 ; biClrImportant + dd 0 ; bmiColors +%endif + + +section .text + +; this is for testing only really! for setting the text to something that's not even in the timings/strings arrays +export SetTextPtr +global _SetTextPtr +_SetTextPtr: +SetTextPtr: +%ifdef USE_TEXTS + mov eax, [esp+4] + mov [current_text_ptr], eax +%endif + ret 4 + + +export GetTextPtr +global _GetTextPtr +_GetTextPtr: +GetTextPtr: +%ifdef USE_TEXTS + mov eax, [current_text_ptr] +%else + mov eax, 0 +%endif + ret + + +export GetTextsBitmapHandle +global _GetTextsBitmapHandle +_GetTextsBitmapHandle +GetTextsBitmapHandle: +%ifdef USE_TEXTS + mov eax, [textsBitmapHandle] +%else + mov eax, 0 +%endif + ret + + +export GetTextsBitmapBitsPtr +global _GetTextsBitmapBitsPtr +_GetTextsBitmapBitsPtr +GetTextsBitmapBitsPtr: +%ifdef USE_TEXTS + mov eax, [textsBitmapBitsPtr] +%else + mov eax, 0 +%endif + ret + +export GetTextsBitmapInfo +global _GetTextsBitmapInfo +_GetTextsBitmapInfo +GetTextsBitmapInfo: +%ifdef USE_TEXTS +; return pointer to the BITMAPINFO struct that describes the texts bitmap + mov eax, BitmapInfo +%else + mov eax, 0 +%endif + ret + + + +export ResetTimingsCursorToStart +global _ResetTimingsCursorToStart +_ResetTimingsCursorToStart +ResetTimingsCursorToStart: +%ifdef USE_TEXTS + mov eax, text_string_timings + mov [current_timing_ptr], eax + mov eax, [eax+TIMINGS_REC_STRING_PTR_FIELD_OFS] + mov [current_text_ptr], eax +%endif + ret + +; Update current_timing_ptr and current_text_ptr to current position +; Parameter : current time +export UpdateTimingsCursor +global _UpdateTimingsCursor +_UpdateTimingsCursor +UpdateTimingsCursor: +%ifdef USE_TEXTS +.seek_loop + mov eax, [current_timing_ptr] + mov ecx, dword [eax] ; get time value from the timings + cmp ecx, [esp+4] + ja .skip + ; set current string pointer + mov ecx, [eax+TIMINGS_REC_STRING_PTR_FIELD_OFS] + mov [current_text_ptr], ecx + ; move timing pointer to next timing rec + add eax, TIMINGS_REC_SIZE + mov [current_timing_ptr], eax + jmp .seek_loop +.skip: +%endif + ret 4 + + + +export InitTextDrawingStuff +global _InitTextDrawingStuff +_InitTextDrawingStuff +InitTextDrawingStuff: +%ifdef USE_TEXTS + %ifdef GEN_TEXTURES + push texts_gl_texture_name + push 1 + call [__imp__glGenTextures@8] + %endif + + push 0 + call [__imp__CreateCompatibleDC@4] + mov [textsDC], eax + test eax, eax + jz .fail + + + push TEXT_CHARACTER_EXTRA_SPACING + push eax + call [__imp__SetTextCharacterExtra@8] + + +; CreateDIBSection@24 +; HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) + push 0 ; offset + push 0 ; hSection + push textsBitmapBitsPtr ; ppvBits + push DIB_RGB_COLORS ; usage + push BitmapInfo ; BITMAPINFO *pbmi + push dword [textsDC] ; hdc + call [__imp__CreateDIBSection@24] + mov [textsBitmapHandle], eax + test eax, eax + jz .fail + + mov dword [BitmapInfo], 0 ; clear the first field of BitmapInfo, so we can use it as part of the RECT structure + +; CreateFontA@56 HFONT CreateFontA(int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, +; DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCSTR pszFaceName) + push dword [text_font_name] ; font name + push 0 ; iPitchAndFamily + push ANTIALIASED_QUALITY ; iQuality + push CLIP_DEFAULT_PRECIS ; iClipPrecision + push OUT_DEFAULT_PRECIS ; iOutPrecision + push ANSI_CHARSET ; iCharSet + push TEXT_FONT_STRIKEOUT ; bStrikeOut + push TEXT_FONT_UNDERLINE ; bUnderline + push TEXT_FONT_ITALIC ; bItalic + push TEXT_FONT_WEIGHT ; cWeight FW_BOLD = 700 + push TEXT_FONT_ORIENTATION ; cOrientation + push TEXT_FONT_ESCAPEMENT ; cEscapement + push TEXT_FONT_WIDTH ; cWidth + push -TEXT_FONT_SIZE ; cHeight + call [__imp__CreateFontA@56] + + mov [textsFontHandle], eax + +%endif +.fail: + ret + + +export FreeTextDrawingStuff +global _FreeTextDrawingStuff +_FreeTextDrawingStuff +FreeTextDrawingStuff: +%ifdef USE_TEXTS + %ifdef GEN_TEXTURES + push texts_gl_texture_name + push 1 + call [__imp__glDeleteTextures@8] + %endif + push dword [textsFontHandle] + call [__imp__DeleteObject@4] + + push dword [textsBitmapHandle] + call [__imp__DeleteObject@4] + + push dword [textsDC] + call [__imp__DeleteDC@4] +%endif ; USE_TEXTS + ret + + +export DrawTextBitmap +global _DrawTextBitmap +_DrawTextBitmap +DrawTextBitmap: + +%ifdef USE_TEXTS + +; SelectObject@8 HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) + push dword [textsBitmapHandle] + push dword [textsDC] + call [__imp__SelectObject@8] + + push dword [textsFontHandle] + push dword [textsDC] + call [__imp__SelectObject@8] + +; SetBkColor@8 COLORREF SetBkColor(HDC hdc, COLORREF color) + + push 0x000000 ; black color + push dword [textsDC] + call [__imp__SetBkColor@8] + +; SetTextColor@8 COLORREF SetTextColor(HDC hdc, COLORREF color) + push 0x00FFFFFF ; black color + push dword [textsDC] + call [__imp__SetTextColor@8] + +; some stock object constants +WHITE_BRUSH equ 0 +BLACK_BRUSH equ 4 +DC_BRUSH equ 18 + + + + push BLACK_BRUSH + call [__imp__GetStockObject@4] ; wingdi.h / Gdi32.lib / Gdi32.dll + + push eax ; HBRUSH hbr + push TextRectangle ; RECT *lprc + push dword [textsDC] ; HDC hDC + call [__imp__FillRect@12] ; winuser.h / User32.lib + +; --- functions --- User32.Lib +; DrawText@20 int DrawText(HDC hdc, LPCTSTR lpchText, int cchText, LPRECT lprc, UINT format) + push DT_CENTER ; format + push TextRectangle ; lprc + push -1 ; cchText, -1 means null-terminated + + push dword [current_text_ptr] ; lpchText + + push dword [textsDC] +%ifdef USE_WIDECHAR_TEXTS + call [__imp__DrawTextW@20] +%else + call [__imp__DrawTextA@20] +%endif + +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + ; use texture unit 1 for texts, if there's more than one texture + push GL_TEXTURE1 + call eax + JUMP_ON_GL_ERROR .fail, glActiveTexture_string +%endif + +; do we want to mipmap the texts too? +;%ifdef USE_MIPMAP + ;push GL_LINEAR_MIPMAP_LINEAR +;%else + push GL_LINEAR +;%endif + push GL_TEXTURE_MIN_FILTER + push GL_TEXTURE_2D + call [__imp__glTexParameteri@12] + JUMP_ON_GL_ERROR .fail, glTexParameteri_string + + +; "Texture names are unsigned integers with the value zero reserved to represent the default texture for each texture target." + + +%ifdef MORE_THAN_ONE_TEXTURE + +%ifdef GEN_TEXTURES + push dword [texts_gl_texture_name] +%else + ; use texture name 1 for texts, if there are more than one + push 1 + ; push TEXTS_TEXTURE_UNIT_NUMBER +%endif + push GL_TEXTURE_2D + call [__imp__glBindTexture@8] +%endif ; MORE_THAN_ONE_TEXTURE + + + push dword [textsBitmapBitsPtr] ; pixels + push GL_UNSIGNED_BYTE ; type + push GL_RGBA ; format + push 0 ; border + push TEXT_BITMAP_RESOLUTION_Y ; height + push TEXT_BITMAP_RESOLUTION_X ; width + push GL_RGBA ; internal format + push 0 ; level of detail + push GL_TEXTURE_2D + call [__imp__glTexImage2D@36] + + ;glGenTextures(1, &texture); + ;glActiveTexture(GL_TEXTURE1); + ;glBindTexture(GL_TEXTURE_2D, texture); // activate first texture +; glTexImage2D( GL_TEXTURE_2D, 0 /* level of detail */ , GL_RGBA, TEXTDISPLAY_XRES/*width*/, TEXTDISPLAY_YRES/*height*/, 0/*border*/, GL_RGBA, GL_UNSIGNED_BYTE, TextBitmaps[textindex]); + ;void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +; --- other --- +; font name e.g. "Times New Roman" + +%ifdef USE_TEXTS_UNIFORM + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push texts_uniform_name + push dword [gl_program] + call eax + mov [texts_uniform_loc], eax + JUMP_ON_GL_ERROR_EXT .fail, glGetUniformLocation_string, texts_uniform_name + + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push glUniform1i_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + +%ifdef GEN_TEXTURES + push dword [texts_gl_texture_name] +%else + push 1 +%endif + push dword [texts_uniform_loc] + call eax + JUMP_ON_GL_ERROR .fail, glUniform1i_string + +%endif ; USE_TEXTS_UNIFORM + +%endif ; USE_TEXTS + + + ret + +.fail + mov eax, 0 + ret + +; -------- + +global CompileShader_NoDebug +CompileShader_NoDebug: + + push glCreateShaderProgramv_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push seireripointteri ; strings + push 1 ; count + push 0x00008b30 ; type + call eax + ; RET_ON_WINDOWS_ERROR 0 + + push eax ; <-- this push goes to glUseProgram + push glUseProgram_string + call [__imp__wglGetProcAddress@4] + + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + call eax + ; RET_ON_WINDOWS_ERROR 0 + mov eax, 1 + ret + + +; parameter on stack : frame time position in audio samples (dword) +export DrawFrame +global _DrawFrame +_DrawFrame: +DrawFrame: + CLEAR_LAST_FAILED_OPERATION_INFO + + +%ifdef FRAME_TO_TEXTURE ; ----------------------- IF USING PREV FRAME TO TEXTURE ----------------------- + +; --- copy previous frame to texture before running the shader --- + +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push GL_TEXTURE0 + call eax + JUMP_ON_GL_ERROR .fail, glActiveTexture_string + + push 0 + push GL_TEXTURE_2D + call [__imp__glBindTexture@8] + JUMP_ON_GL_ERROR .fail, glBindTexture_string +%endif ; MORE_THAN_ONE_TEXTURE + + +%ifdef USE_MIPMAP + push GL_LINEAR_MIPMAP_LINEAR +%else + push GL_LINEAR +%endif + push GL_TEXTURE_MIN_FILTER + push GL_TEXTURE_2D + call [__imp__glTexParameteri@12] + JUMP_ON_GL_ERROR .fail, glTexParameteri_string + + + push 0 ; border + push RESOLUTION_Y ; height + push RESOLUTION_X ; width + push 0 ; y + push 0 ; x + push GL_RGBA8 ; internalformat + push 0 ; level, mipmap level-of-detail number + push GL_TEXTURE_2D ; target + call [__imp__glCopyTexImage2D@32] + JUMP_ON_GL_ERROR .fail, glCopyTexImage2D_string + + +%ifdef USE_MIPMAP + push glGenerateMipmap_string + call [__imp__wglGetProcAddress@4] + push GL_TEXTURE_2D + call eax +%endif + + +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push GL_TEXTURE0 + call eax + JUMP_ON_GL_ERROR .fail, glActiveTexture_string +%endif ; MORE_THAN_ONE_TEXTURE + + +%endif ; FRAME_TO_TEXTURE ; ----------------------- ^^^IF USING TEXTURES "PREV FRAME TO TEXTURE" ^^^----------------------- + + +%ifdef USE_TIME_UNIFORM + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push time_uniform_name + push dword [gl_program] + call eax + mov [time_uniform_loc], eax + JUMP_ON_GL_ERROR_EXT .fail, glGetUniformLocation_string, time_uniform_name +%endif ; USE_TIME_UNIFORM + +%ifdef USE_RESOLUTION_UNIFORM + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push resolution_uniform_name + push dword [gl_program] + call eax + mov [resolution_uniform_loc], eax + JUMP_ON_GL_ERROR_EXT .fail, glGetUniformLocation_string, resolution_uniform_name +%endif ; USE_RESOLUTION_UNIFORM + +%ifdef USE_TIME_UNIFORM + push glUniform1f_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + fild dword [esp+4] ; ------ current audio position is at [esp+4] (and function return address is [esp], the stack grows "downwards") + push 0 ; dummy number, just a "stack allocation", to be overwritten by the "fstp dword[esp]" instruction below + +%ifdef TIME_DIVIDER_IS_INTEGER + fidiv dword [time_divider] +%else + fdiv dword [time_divider] +%endif + + fstp dword [esp] + push dword [time_uniform_loc] + call eax + JUMP_ON_GL_ERROR .fail, glUniform1f_string +%endif ; USE_TIME_UNIFORM + +%ifdef USE_RESOLUTION_UNIFORM + push glUniform2f_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push dword __float32__(%[RESOLUTION_Y].0) + push dword __float32__(%[RESOLUTION_X].0) + push dword [resolution_uniform_loc] + call eax + JUMP_ON_GL_ERROR .fail, glUniform2f_string +%endif ; USE_RESOLUTION_UNIFORM + +; ---------- feed in the time into green color + mov eax, [esp+4] ; time (from paramters) + shr eax, 8 + push 0 + push eax + push 0 + call [__imp__glColor3us@12] + JUMP_ON_GL_ERROR .fail, glColor3us_string +; ---------- + + + push -1 + push -1 + push 1 + push 1 + call [__imp__glRecti@16] + ; call _glRecti@16 + JUMP_ON_GL_ERROR .fail, glRecti_string + + +; ________ IF TWO_PASS_RENDERING DRAW ONCE MORE, WITH TIME ZERO OR NEGATIVE TIME _______ +%ifdef TWO_PASS_RENDERING + +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push GL_TEXTURE0 + call eax + JUMP_ON_GL_ERROR .fail, glActiveTexture_string + + push 0 + push GL_TEXTURE_2D + call [__imp__glBindTexture@8] + JUMP_ON_GL_ERROR .fail, glBindTexture_string +%endif ; MORE_THAN_ONE_TEXTURE + + +%ifdef USE_MIPMAP + push GL_LINEAR_MIPMAP_LINEAR +%else + push GL_LINEAR +%endif + push GL_TEXTURE_MIN_FILTER + push GL_TEXTURE_2D + call [__imp__glTexParameteri@12] + JUMP_ON_GL_ERROR .fail, glTexParameteri_string + + push 0 ; border + push RESOLUTION_Y ; height + push RESOLUTION_X ; width + push 0 ; y + push 0 ; x + push GL_RGBA8 ; internalformat + push 0 ; level, mipmap level-of-detail number + push GL_TEXTURE_2D ; target + call [__imp__glCopyTexImage2D@32] + JUMP_ON_GL_ERROR .fail, glCopyTexImage2D_string + + +%ifdef USE_MIPMAP + push glGenerateMipmap_string + call [__imp__wglGetProcAddress@4] + push GL_TEXTURE_2D + call eax +%endif + +%ifdef USE_TIME_UNIFORM + push glUniform1f_string + call [__imp__wglGetProcAddress@4] + FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + +%ifdef SECOND_PASS_NEGATIVE_TIME + fild dword [esp+4] + push 0 + +%ifdef TIME_DIVIDER_IS_INTEGER + fidiv dword [time_divider] +%else + fdiv dword [time_divider] +%endif + fchs ; change sign + fstp dword [esp] +%else + push 0 ; the second pass is the same shader, but run with time = 0 +%endif ; (not) SECOND_PASS_NEGATIVE_TIME + + + push dword [time_uniform_loc] + call eax + JUMP_ON_GL_ERROR .fail, glUniform1f_string +%endif ; USE_TIME_UNIFORM + + mov eax, [esp+4] ; time (from function parameters) +%ifdef SECOND_PASS_NEGATIVE_TIME + neg eax + sar eax, 8 + push 0 + push eax + push 0 + call [__imp__glColor3s@12] + JUMP_ON_GL_ERROR .fail, glColor3s_string +%else + push 0 + push 0 ; this is SECOND PASS i.e. post-processing, so zero as time + push 0 + call [__imp__glColor3us@12] + JUMP_ON_GL_ERROR .fail, glColor3us_string +%endif + + push -1 + push -1 + push 1 + push 1 + call [__imp__glRecti@16] + ; call _glRecti@16 + JUMP_ON_GL_ERROR .fail, glRecti_string + +%endif ; TWO_PASS_RENDERING ; ----------------------- ^^^TWO-PASS RENDERING^^^----------------------- + +; ________________________________________ + + push dword [WindowDC] + call [__imp__SwapBuffers@4] + FAIL_ON_WINDOWS_ERROR SwapBuffers_string + + ; jmp beepquit + + mov eax, 1 + ret 4 + +.fail: + mov eax, 0 + ret 4 + +loppu: + push 0 + call [__imp__ExitProcess@4] + + ret + +extern _MessageBeep@4 +extern __imp__MessageBeep@4 +beepquit: + push 0xFFFFFFFF + call [__imp__MessageBeep@4] + jmp loppu + diff --git a/debug_visuals.dll b/debug_visuals.dll new file mode 100644 index 0000000000000000000000000000000000000000..81185b0811c9525076bc5f7610e76ba28cd788cb GIT binary patch literal 34572 zcmeI53wTu3x%XEBD54;uv52U#;H9?G$z*0Sx!-1T!Q7fm1d+NkBtvGxBoi_dz?N22 zYEf)UtzSipEedUEkM&RwwaC#H#S68z2dq}Kv=6Nw8^y0uODpx3^MBV`d-i^34?ffH z`M&2lJs+EAW$pdj?|Ro-@4D~Vd(paRgP0(Mml*EF%? zlwVx9Gq2?r7lxv-Wa02gqJJbjSlAmL8cL)JmqZFjMu!SxLxq9%uEN1YUu53YsZ-`^ z)g3`0TJla7ZzkH8iZUU-mM_F1anhVq^YYIY(;;-R5)5>}r|Uv_JzbtdmeQREN4`8Z z;4d!LUY;lOB?C}63Lt&$^$5{P86Otn=}C0|IL8_xQY7~e9{%M*?Ea82^HPyjDcnDH zI{r|)$fYxZa~y@Dqi0@UI2Fcu!{Aay9c}N>17kwiGA9x#+HSNPQ!bc%oO^at-d0 zKA$B+XOOGoz59F@4WH1@iAy`S%R^OOeS4{ip`fH75&oCB$hI z?abYDJzlU6x^FxtMrV)xZmJM;HYHl%7SqQX$H&J>U>yXuNVNkKqveQuyxMB{^N{3iRAttjBBxZ)Y zJsn9r9b`2HdH#LNGCT8NPg#WH1y+D^9$>32fYz=}b|4+cAm6{}Gp% zE-zvBd+1_Mw6TbcxG}Bhr>B}0Sx<^CwJC~H4UC>cf5y;_k9(hn#Q44&D+!5|*z?pR zd4?=KIf-P&QB*js%O{Fh2LxvuE(Iyl9 zeTKgGr?4C>wadEJBi;M9$b{RJl8UjlcEM>GX4%G-o?(+kYamk&sYrlO4~Zkb;k0WD|-;GZZ#+g%7-AH$r9#&sIht9hMOepDHW%p0UeN zW97_i&yAH-&f@g751;}@$1|$QuO~CpRI?~$1<8^VQZjb6O*DEWL+y23?bzS#IZ+M9 zZfgoYHpQm!sYx=?Nb!x8lyQ-|I=Vk2j&pe&Ygrtb)|w%MkA24`^wcD&8F46^$-dzo zL}vEPAE@(t$lr6%lw$fjjsEVOCI4c!Gkr@wPS@8=+@gf!)#UP)xf55OxxQ)Q%~J{A zxO=h`JA4S5X_N^pN5GR1@C&_5tk$2%RJzPWWYQf z;64iAr9z43VU8S~d=6PRN^?#1M+2pPH>9K6q0XL_6xIT^to-(GwyeA^?V#%FmRIQ_ z-5u*(kv5epl6?(X7mgTa@EAU8k6~j*YFvc- zzP1Siyu;jE0Bt5b%^t&V>@mFX;W3cxYh@I}tr=#lS#M4Ov=!*cTb3DE zy*cy`)SNrf<50Q2ec;h!X31`43DkYWHdaoD`;J$vTAUZ_VXwJhsDW<=)Q%5F#xs3bk_T$&_Q+TW!8&D!6p{cYO6Py5@oPxX+}u~YjGYk#-$Y2?QN zPx^FjKY}A8;gLvTbaXI0G&)!qNz%h9b=*Vip*{D|T4)cEk7=HZw@C`k%tiFWWiV*& zL$`6_IAMVk7C2#n6BamOffE)uVSy7CIAMVk7C2#n6BamOffE+^|Iq^d@%oWSI2Gwo zZykyLcpwsw*ss<7u4uR~GLpV+yG(_9qv=a^(v=t;>5V|RJ~22Pi$~J8Yg0_RIhnrG z7)hz~=AosDmP9`Sx5S2)S;^{7+R|uGlNMQl5ZyzurHPTjqNTR;n04+Zj)=5aOQJWN ziY0~sYkO0%6_F6$DHgp52*Mc<kyI)+)SnbcN1$GG!r0+t1ZVZpL;_ii zt%}4OkcV(eK-7M@(k!a_#88UfegbF>FN@TVj*LWxPX7%3jL zPU);Og4~L(mEqyK(WOfxBS}{8Q?bE_1W=KPk4gj4HAM-@zdHuAWJP48a1d>Xi@8Nt_}ao~tT2_B+L{N9ljjGmVBNwzaT@&4rzePW;dhKq6~*v-E}kyx;2-3OnxzJHpyarNBEd8zZr6RAtd%TKw;n~?IGGSQ>-Q^*GV8829iC)0;t zm1Lk#U%oKlw%^@5;7;Fq_@CU$|80{m-@QfZ=7-h0wCCZR+@(E2Y=WCk9Pgh#g?@4c z+@e`RJp2(MN@obMp+JZ`aNY+#rw~65z+Hp$`*Cmo*+Tpl?ghA);fBEn;4XmtYq-7} zG7rIj0X zg1ZJT33n6RZE*L({TOaP+$(TL;l|;n^$PJ(xOs3@aAbjeyg58kOv0+of=?dQ zpxQ7Rk0*OaB9S3Ayt1)Y1V+Lu8)%@GXBeVWb+HtU$PEb5*kTTxbfqUMDU5*fE(ud` zjLlsVVl1^n;G!j*Of`ftndxgEroo;j4%soyVCWW~&!mBx9Cf5dNQR=dohDU!@i*zD zP2r)wc*G2)Ma{^RIWUiaQgyDyn}=dD7M8irND^_!25BaO`9m@>5=wNX!Xt9hp-m&_ zaFhznLnxUIn0B<0ZS}Rj)je#P33qIln8qMIVCl4_&vn|mhw=7vgr$S3&_B_!YS>Eb zvE@Se;da_sC#FoR!1meLE-?IRDJH|2$07V)xYu@V^5gjvM}(LS=Yea2>w{Yjw*hV| z+)lW?a0lUzz@3IT3*jo@=;(n@)45yWHobU z!|i~329Az5$RC9~oF6U#7lMnzt%kcDZX4WAI6D5>)880qE_Taa3VmmmxjW@?Q$Fgu zeFjeu$B*-!b8naK$f(al-?Ai5O9Fj(^}RrIT^CK=(ecQmLUU@EwOV#1;*3M6eaQg+ zD)_2UOFBDySu-=1&r@3KmenV)UeKz878FRUMz@$t5PEvKyYj|@72a* z{W^``HQD^pWGc2ardM22eri7TiK#^IGJDFd2zIswTTJ8TlMHpe_<`L_*{Ac=0;v^i zoN#}{%(`frKr6a9_3l!?Pt-*sy4{_V7hDySiz8YX(b3)!Y->!%b5)*Wc_pR#h}&0L zk_ypF97(e;x9Ha2)9WiGc#(Y(roW-29w2f?7umP>(AlP^R`t|YHNjv}!wM~R|c zOPy?4Dmg7z8zVzhidfmI`0Bt^jbK=Klx}lbE5mnp1v|~Mn3k_CUYA&98huXo)vb9O z`QnRV^TvgF$gQq?k$h_vOp&_tJ0g)~ymVj6$C7BJ8meT%@aJUGQJcJWsP~Gs|lZy(9W);mXaut;pRTl+{78XT{28xD@RutV* zbVt#qqAf+=D|)2p>7so_zb^Vs(VIo@73I4pyQjH7>i(p=+TG>uaW8ep-6QUs++TCw z>;6~wkKF(6{tx#-_wU`Wy8rC{yL&?M)Z(*>&o92D`10b~;hik~Tdw)oZJzZAbyobQ?9Im>gQ=VH$%JT;zHPnYLv&r;8TXV`P2 z=Vs5{p6`3Mdmi-s#Ix7)yyqp)AE3g^7kfYME%FAvo!*7s9`7=5!aM4{ z&HGL7R_{*l6W*VD_j_OTzU)2X{j2v~@9DnTzK{AY^Lc!=zDD1td{_AlU(&b6ca!hS zzKyLx{3-t`|L6Ui{P+5Q;Qyij$NpdVf8~GIFG^1;omF~C=_g9v zrKP3SrSnVMN<*a!OP7>JOIMfPT>9nG+e^2V{;2ek(kDvyl|EPcQt2C|Zdt9*0$j`By#_m{s|{z~~+ z`Jc*9sW`o2R>k=hb1TX#YAaeQIx4QL=&Km0_nfWnyDAq{e!6m5`cNtE#KIs(PwcRb5|oOVw>vcU9e6_5G>`s&-X9R`qn%vsEuu z{h{jhs<*1%smiaOQaz)3R`o}#FROM}msQtQ&#&&RUR1rLdZ2ow`ZLuxRNqp4TlHPl z_f~(u`hn_Q)sIy_UHxqJOVxj<7KNCTpry@qUFM?i-O!B0JMItMc%@u^SBKkTqU$u* zS+3cxxw2JNxK_K?yY6y*2h#t2j(JP5B0zE;%ELMeZ-({f@pVi%IVj9;6)Dva6BF{j zI8BHz(P{cHzf&ZT4>uu?zF3@;zE3CSH;QzQE(bF5Yel+DA9fi$c!SJ+_)C_yj(OoF z^2r_%dYf&6XlyYWYFoO37NIi=PluABGb$xIEOMa&HZqS0@@C1j5+zT3v&e0@n#{;HT%F6vPjGbsBQN4=4kJf!MX%f`&4xU%z6GHIAUk5D#VN&ZrSKBE z$w<&4(+@%^v_h?7G6udU#R5y#S6N;{lOie)M%nd>Vw3WW_ZE!prM=5MCCygA}q*-vy!9Y~ks=@5HHm3t6@TVDThK-lg`q4idqa z6;|x8g2?x*)1lr1ksoT9t*NuIuGUYlIa{GVAU$W91TBta1btCq$(#<8PPoKQE&-7r z-lgNJ133rgfI6Lvt3b|UBnHB3_-8<uisOs$2H;!d4iG9Yi_pvePtLH%bw9|{ zjO+yYB_lrrd6tpifV{xSTOhw-WC{xORYqomyw1ocL5?s|0YZmm!z)1K^HFKBh6P4l zdrLq(40BmB-HuR89Awl%ZU!M}>A4%1$cT;XaD;lCkwC}@wRcd8%}^jM!G@5H(CM=X zMdhI4f=p*~V^fIA+=~4mWJtM1{)kK73jPc-oymLva+KMSzNlFN8LQkc0C|X!Vvt7} zsRnt9kt;#YfD%j300`Api>v^-fRUR(KF-K(ASI040}^KBM<6jq9(9oCLB7UhUIY0C zBYy>Xl95yJG1e~`DF8Xf$j3ma0RrmQ`)@)btz z0J(#aEg*L@@*v3ljQk8_2O|eT4lr^AF$-Hwf)~V1=pz zS;5GBkh>VU2IO8w20(t!$O@1*8My`IZAQKhauI5|75lv)&5S$<@+n3h1Nj^yzXbUX zBYyz7pOHU-yvWEqAn!9W4NYY0_ESs<4&axq97BV{1eqO4F2AlEU{3GxL-mV?~F z$XbvMjNA@Ft;N#34diEx>;O5+$Zn9Cs0~)A=RgV>IRp}9*D?LyRl~`GECot3mQHk4BY7B~IZXND|K+PD&GC@fFBSVdNf=X^iXu znZd~8AZIi3EXXWIehYFwBS%0!%E&}~34SpnGeMqU`I-Z=pOJYWFECOM@>@o(0(qH{ zILK>^+yp``+$z(%9AqcRY}9E>W>A&^%Xc?0A>8KGs{>9DMo!m~g=!bl;=d`3JVos86gEMjCn z$Zd>V143nQ#Weu3kC7E1M;W;Vg$Z$fU93ILLnyO34x{gE|3yNz5}wDkzF8tj64YvPm_3Jc$j{CNu|jWJo;Qd z8cTgHO=_0nRj_$37sYI~%IBfSJTTDWp#5ZMt&6Th&wu_1(u128IRdgSt(ih)*R$H8 zhxUu&dN$;sXN^P8tqwgKbI`Nap@+VU=IPm-gPwH`J=+|5w&kE_uS3rp=puP~w&$Sd z8HXNvyu|hF%t6mShn_-*p4~a6=+Hw?1G#;ga?rEbp=Yl{Pe%@V zdK`KVI`k~eK~JAU&k={7o*eW<9ePf4j9<|l^u!%{3LScebI>#F&{N^ivnmHY8ytG} zI`pi`LC@_DJ%=26*5#mQqeIUzhn@{N=-K4ZGu<&y*qDQ!%?>?<4n3Q5(6iN{$K%km zEeAc@9D14@dba1F=RSv?#ST3?bI`Nhp=a2kXLk;Ib~yCVenPze*_(r&oen*l9eVcV zpyy$S9(tC|({msPJ-Z!xo^j|ol-5(zix-}-3F;}UzNS|kYDd($Zdx&@*fsGTOKaA| zvno@@>rcxZUo(D$$XDA0=8DWvzC&rN zn%0<{PN62=y=mgq{C|reVd8I?OPJ52FxcQY4Ku+9^s_ic&IK`Zp@It0? z-5}=tN69P)F@G;mVifjd;gRT_$H;^N`)+zEB$Qo@QMV<#S%R-Si zLCk($k&~h0_xM4Dt`s>Bgbt|EBmh!zhF#`L5VKvVP=g>*CUZTAx&Bfz-vBXdogzO3 z*~ilSa}aZcRWh%Gn1>>N2kC&bQg||Qu#J_@O!|>XA1c%*K+NZLid2A@J%Az|Ad8uv zrCN_wrk@Ad$kKc#$-r4M58&#se)gp_?3PtGI{L9EKT`6)7h&c)?av4Y?lL>%)Oovc1 zJs|HuyQL=qa+Ia;iy-EqLfr|nfm!T+kO2r;mj5ZpEe!4yNa)ATAc_KS0cxu!^0&NHU+ZDe^ZE z^LGbD^6=%7dE^U2z5-n1F`x1&nKL0{{<@^d$3SMX*!>`uok?RO$a$=tUIWs>a*+aA z#AI#;>0>h6Ko&DXUuvyq_IVzJ4y(?OftYhGmF5pXhMAtTv5TAe3!Rd=9HfHDG=P|M zVJ=>5z?<#Zin_N8U$ z-kl%?ti1jeL@=43fIP!e_&bnCSbE+BIl@A{PlU;wi7)v!uryx`vYpkjI*?IDdO#Mk z*hfI98@0-7y(C0UYupVom*s002z>)cmQdDsMuoEV;V*(rzk&(3^N0@!?1i6&y zxgVsEk;g&IBVU-GoYDJ8Rton+W*yV~D#&D}=UouiC z7^w$ARJJm`8iWq3l;a>YMv$C}>oXutOwUaqx3V;E1~K0dP@(PvS<7U0ftXMAmCRm{ zLrmr%hsL+K2P{}kku^Ib0Fp~BP#YWkj+fyeGqfCu4HDNkGwOP%R$UT$y9`>uWna)quKCuvJ9p zqbg%ieMe<1k-I?{!}#Qr--z{PfZp)1{0uFQ53`J=@}pQIk^U++D>Y*JtJr_=JKD}* zy%B0|ZEkDqB0p#}GzVJ(MpyHqps?So@9qjAW5>DM73zcrqa)O5moW8`9;uLl%pmOz zUGfzo{Svob#*I)k+VyO1VYCW24Y0&#q9 z78??S$$rDGMr+Q*I;4qt3>j3*b~FTxKznyxOHfx32|8;R;LTKHL33N6eSxr}y5>-8 zZHGi%-5nk6ogqVgJ0}9IUG<&8U|Ux(6ruv6IvWZu40U$~4eX0zyF&TF@GT)!N6?n$ zwqUJ1)6y=RY!RJzw{hv{UBI}PE!|5$^3>BTA zy;F=)wFwQP?d4#IKAyIARbhfzuoRc?tT9PWln_PR7h4gd9eVJUD7{*4)VH^^cXkQ9 z0NqCYLyM?|O^y1d+D;UgXzvagfnY;zcS{JBH(1}?CF)z6J2F{qTd29VrMb2XMe(U_ zoQ19uZS8H@u&K=yGp{?EL)0QdMt!i2${%M}TBmjGAv9Zp3)(vab!Z<~2-@nT7yr*$ zpRp8Qwi+^v_OA%Vym>W6zT$bwWwBwi^RhGZv)Ih70%R~>mSBomU#jb`)6-w8qquQy z`?6ieR+1$Jnq`Qq58)~Lk}T0{rgWA#lUJgcy6?|&UomyRG|PR(GWI~A)cD;_Y0acI zf0i6-MmfyfCm`LJtQ`*OqmkZayoJe#vt+}svoVy=t;tY>5L$1>P7tJ_G)vMolSwaC zNmu6{XEsX}Q}?~{zBuSUCz9j zOvze#bGw{*Gntard1HHN%%dUOz-|(jF-j>xxm$2LqL#EQ1W4B9}o4jw!aZ#2W zYbH}xq;s6H8HY4OpWK2>cdDegD2qunQ_8eSj<3w@to0}D>CG&9)$Umab*pmflLm5l zmq>QGYG)4JHQ0!`SBFHTR*Qt7kapU_-e34aP=%J8by%mylGuV+ABH7{nj*3OXo|Cr zcz7t1q((<-ZCiubPW6T$I(jrl68+E(MPzc0zZFQf-8r(bc}aY&jnOVKEVAB3FDQbDgo@yqmOR=qANZ68+hySXFO-f5^!8gR?#?8bx*i=>XOV0WP1=nP^h zh}m*i2oKH-BQ`i}7-}YE-)E%8BMkH`Y^qCX$sFGeYYPSnV$lCwiezEeAgSF5P+E9o z=?yt#02zPgJ{# z8mV~FvLfX4E-Whlv>!_`-KQ^!Aq`s(C*}VIs{;vxcOb&Z+}s0-pw+eyjirr#PwF){ za*1JsmfoaQQ5+kb$dXFNJ`*t#ODV;@%M84|F&LxbXY&iAEfJvIypUdJWtBVU;0{-W z^-pAEMMTCv7#_e=iR9>#WkAb=EgVjcMIdkZ@LbdM^9ZH=oI ztr=sIv>ufo_FXcTgp;bl%7$Ryvj^)LYiHYZW{jlTy~+sF{!oM1vsO0gW<0ypO;3+? zQ~}bJMDA9r$cK$?(yX>kc+;`clE8YTgYvVDF=-)t$1M!oR#7OC>tv7RtQ;_xy+5Iu zxE>RAZnDgVRVQNKrm3cw27!9p&`IN)eNdCFm3pKsg9o)-9h*H1=Gc?595Rh+ZiS== zAlY&DntF5(BKPn@^>l1YoVJ-+o%wFaGC#W7(!OM>Bak&DqfN`$(>p&=OR%P`W(Ds> zY`W!TTP?se)-J|s6tG*8+JbHW>5P=yH%de7Y`bk#>sVA~vxatA{7AY)CZ#gPcx7%z>RInyzC?I)8{4I!Omddx7?)|VMQ0g_3( z+^}YAPR+3YSwA-1wDKrR+EHmJDrGBGHLR`du+YIRHRSW2%B){}t1{ArY$!FltCJpp20dp8L42qSaqV9s2ux?)ein$ 0 +; SetTextCharacterExtra@8 int SetTextCharacterExtra(HDC hdc, int extra) +extern _SetTextCharacterExtra@8 +extern __imp__SetTextCharacterExtra@8 +%endif + +; HGDIOBJ GetStockObject(int i) +extern _GetStockObject@4 +extern __imp__GetStockObject@4 + +; --- functions --- User32.Lib +; DrawText@20 int DrawText(HDC hdc, LPCTSTR lpchText, int cchText, LPRECT lprc, UINT format) +%ifdef USE_WIDECHAR_TEXTS +extern _DrawTextW@20 +extern __imp__DrawTextW@20 +%else +extern _DrawTextA@20 +extern __imp__DrawTextA@20 +%endif + +; FillRect@12 int FillRect(HDC *hDC, const RECT *lprc, HBRUSH hbr) +extern _FillRect@12 +extern __imp__FillRect@12 + + +; --- constants --- +; DIB_RGB_COLORS #define DIB_RGB_COLORS 0 /* color table in RGBs */ +; FW_BOLD #define FW_NORMAL 400 +; #define FW_BOLD 700 +; ANSI_CHARSET #define ANSI_CHARSET 0 +; OUT_DEFAULT_PRECIS #define OUT_DEFAULT_PRECIS 0 +; CLIP_DEFAULT_PRECIS #define CLIP_DEFAULT_PRECIS 0 +; ANTIALIASED_QUALITY #define NONANTIALIASED_QUALITY 3 +; #define DEFAULT_QUALITY 0 +; DEFAULT_PITCH #define DEFAULT_PITCH 0 +; +; --- other --- +; font name e.g. "Times New Roman" + +%include "winconstants.inc" + +%endif ; USE_TEXTS + + +section .code1 code align=1 + +; our main entry point is called "t" +global t +t: +main: + push 4 + push DMSCREENSETTINGS + call [__imp__ChangeDisplaySettingsA@8] + + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0 + push 0x91000000 + push 0 + push 0xC018 ; http://www.pouet.net/topic.php?which=9894 + push 0 + call [__imp__CreateWindowExA@48] + + + push eax + call [__imp__GetDC@4] + + push eax + pop edi ; edi : HDC + ; all functions we call must preserve the edi register now + + push pfd + push pfd + push edi + call [__imp__ChoosePixelFormat@8] + push eax + push edi + call [__imp__SetPixelFormat@12] + + push edi + call [__imp__wglCreateContext@4] + push eax + push edi + call [__imp__wglMakeCurrent@8] + + push seireripointteri + push 1 + push 0x00008b30 + push glCreateShaderProgramv_string + call [__imp__wglGetProcAddress@4] + call eax + +%ifdef USE_UNIFORMS + mov [gl_program], eax +%endif + + push eax + push glUseProgram_string + call [__imp__wglGetProcAddress@4] + call eax + +%ifdef USE_TEXTS + call InitTextDrawingStuff +%endif + + ; play music, running 4klang audio renderer in a separate thread +; call Play + ; create a separate thread for 4klang to render its audio in the background + push 0 + push 0 + push rendered_audio_data + (AUDIO_DELAY * 4) + push __4klang_render@4 + push 0 + push 0 + call [__imp__CreateThread@24] + +%ifdef SLEEP_TO_LET_MUSIC_THREAD_GET_A_HEAD_START + ; Wait/sleep for 200 milliseconds so that 4klang's renderer thread gets well on its way, before we start playback + push 200 ; if your music is too CPU heavy, try increasing this number + call [__imp__Sleep@4] +%endif + + push 0 + push 0 + push 0 + push pcmFormat + push -1 + push hWaveOut + call [__imp__waveOutOpen@24] + + push 32 ; sizeof(WaveHDR) + push WaveHDR + push DWORD [hWaveOut] + call [__imp__waveOutPrepareHeader@12] + + push 32 ; sizeof(WaveHDR) + push WaveHDR + push DWORD [hWaveOut] + call [__imp__waveOutWrite@12] ; <--- audio starts now + +; -------------- main program loop, repeat until we reach the ending time position, or the user presses Esc ----------- LOOP +luuppi: + ; hide mouse pointer + push 0 + call [__imp__ShowCursor@4] + + ; pump window message queue (or otherwise Windows will think that our program hung up) + push 1 + push 0 + push 0 + push 0 + push 0 + call [__imp__PeekMessageA@20] + + +%ifdef FRAME_TO_TEXTURE +; --- copy previous frame to texture before running the shader --- + call copy_framebuffer_to_texture +%endif + + call GetPosition ; <-- get the time to eax + +; did we reach the end of the prod? + cmp eax, %[PROD_END_TIME] + jae loppu + +%ifdef USE_TEXTS + push eax +%endif + +; time is in eax + call set_time_in_EAX_to_shader + +%ifdef USE_TEXTS +; pop eax + ; check + call update_texts_time_on_STACK + pushad + call DrawTextBitmap + popad +%endif + + + + +%ifdef USE_RESOLUTION_UNIFORM + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push resolution_uniform_name + push dword [gl_program] + call eax + mov [resolution_uniform_loc], eax + ; FAIL_ON_GL_ERROR glGetUniformLocation_string + + push glUniform2f_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push __float32__(%[RESOLUTION_Y].0) + push __float32__(%[RESOLUTION_X].0) + push dword [resolution_uniform_loc] + call eax + ; FAIL_ON_GL_ERROR glUniform2f_string +%endif ; USE_RESOLUTION_UNIFORM + +; draw one full-screen quad + call draw_full_screen_quad + +; ________ IF TWO_PASS_RENDERING DRAW ONCE MORE, WITH TIME = 0 _______ +%ifdef TWO_PASS_RENDERING + call copy_framebuffer_to_texture + +%ifdef SECOND_PASS_NEGATIVE_TIME + call GetPosition ; <-- get the time to eax + neg eax +%else + xor eax, eax ; push 0; pop eax might be smaller +%endif + call set_time_in_EAX_to_shader + +; draw another full-screen quad + call draw_full_screen_quad + ; ----------------------- ^^^TWO-PASS RENDERING^^^----------------------- +%endif ; TWO_PASS_RENDERING + + + + +; ------------------------------------------- SWAP BUFFERS ------------------------------------- + + push edi + call [__imp__SwapBuffers@4] + + + ; Esc pressed? + push 27 ; 0000001bH + call [__imp__GetAsyncKeyState@4] + test eax, eax + +%ifdef USE_UNIFORMS + je luuppi +%else + je SHORT luuppi +%endif + +loppu: + push 0 + call [__imp__ExitProcess@4] ; <--- end program execution + + +section .cdennn + + +section .text + +; the __imp__ versions refer to the corresponding import address table entries +extern __4klang_render@4 +extern _CreateThread@24 +extern __imp__CreateThread@24 + +%ifdef USE_SLEEP +extern _Sleep@4 +extern __imp__Sleep@4 +%endif + +extern _waveOutOpen@24 +extern __imp__waveOutOpen@24 +extern _waveOutPrepareHeader@12 +extern __imp__waveOutPrepareHeader@12 +extern _waveOutWrite@12 +extern __imp__waveOutWrite@12 +extern _waveOutGetPosition@12 +extern __imp__waveOutGetPosition@12 + +section .code2 code align=1 + +;global Play +;Play: + +; ret + + +; ---- GetPosition returns the current audio playback position ---- +section .code3 code align=1 +global GetPosition +GetPosition: + push 12 ; sizeof MMTIME struct + push MMTime + push DWORD [hWaveOut] + call [__imp__waveOutGetPosition@12] + mov eax, [MMTime_sample] + ret + + +%ifdef USE_COPY_FRAMEBUFFER_TO_TEXTURE +section .cde231 code align=1 +global copy_framebuffer_to_texture +copy_framebuffer_to_texture: +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] +; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + push GL_TEXTURE0 + call eax +; JUMP_ON_GL_ERROR .fail, glActiveTexture_string + +; --- copy previous frame to texture before running the shader --- + push 0 + push GL_TEXTURE_2D + call [__imp__glBindTexture@8] +; JUMP_ON_GL_ERROR .fail, glBindTexture_string +%endif ; MORE_THAN_ONE_TEXTURE + +%ifdef USE_MIPMAP + push GL_LINEAR_MIPMAP_LINEAR +%else + push GL_LINEAR +%endif + push GL_TEXTURE_MIN_FILTER + push GL_TEXTURE_2D + call [__imp__glTexParameteri@12] +; JUMP_ON_GL_ERROR .fail, glTexParameteri_string + + push 0 ; border + push RESOLUTION_Y ; height + push RESOLUTION_X ; width + push 0 ; y + push 0 ; x + push GL_RGBA8 ; internalformat + push 0 ; level, mipmap level-of-detail number + push GL_TEXTURE_2D ; target + call [__imp__glCopyTexImage2D@32] +; JUMP_ON_GL_ERROR .fail, glCopyTexImage2D_string + + +%ifdef USE_MIPMAP + push glGenerateMipmap_string + call [__imp__wglGetProcAddress@4] + push GL_TEXTURE_2D + call eax +%endif + + ret +%endif + + +; set_time_in_EAX_to_shader(time), as parameter: eax = time +section .cde232 code align=1 +set_time_in_EAX_to_shader: + +%ifdef USE_TIME_UNIFORM + push eax + fild dword [esp] ; load the audio position to FPU stack (0) so we can divide it + +%ifdef TIME_DIVIDER_IS_INTEGER + fidiv dword [time_divider] +%else + fdiv dword [time_divider] +%endif + fstp dword [esp] ; store from FPU stack to top of CPU stack, replacing it with the divided floating point time value + + ; on top of stack i.e. [esp] is now the SECOND parameter (pushed first in stdcall) to glUniform1f() + + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + + push time_uniform_name + push dword [gl_program] + call eax ; call glGetUniformLocation +; mov [time_uniform_loc], eax + push eax ; <-- FIRST parameter (pushed last) to glUniform1f() + +; set the shader uniform variables + push glUniform1f_string + call [__imp__wglGetProcAddress@4] + ; eax = pointer to glUniform1f() function + call eax ; call glUniform1f() + +%else +; ---- NOT USE_TIME_UNIFORM --- +; green color is (time position >> 8), meaning the color value grows by 1/65536 every 256/44100 seconds (if we have 44100 Hz audio sample rate) + ;shr eax, 8 + sar eax, 8 + push 0 + push eax ; green color is (time position >> 8), meaning the color value grows by 1/65536 every 256/44100 seconds (if we have 44100 Hz audio sample rate) + push 0 + call [__imp__glColor3s@12] +%endif ; (not) USE_TIME_UNIFORM + ret + +section .cde233 code align=1 +draw_full_screen_quad: + push -1 + push -1 + push 1 + push 1 + call [__imp__glRecti@16] + ret + + +%ifdef USE_TEXTS + +section .data +%ifdef GEN_TEXTURES +texts_gl_texture_name: dd 0 +%endif + + +hardcoded_font_name: db TEXT_FONT_NAME, 0 +text_font_name: dd hardcoded_font_name + + +current_text_ptr: dd _string0 +current_timing_ptr: dd text_string_timings + +textsDC: dd 0 +textsBitmapHandle: dd 0 +textsBitmapBitsPtr: dd 0 +textsFontHandle: dd 0 + +TextRectangle: ; we overlap this with BitmapInfo + dd 0 + ; , 0, TEXT_BITMAP_RESOLUTION_X, TEXT_BITMAP_RESOLUTION_Y + +BitmapInfo: ; bmiHeader + dd 40 ; biSize, it doesn't seem to work if you give 0 in this field +BitmapInfo_biWidth: dd TEXT_BITMAP_RESOLUTION_X ; biWidth +BitmapInfo_biHeight: dd TEXT_BITMAP_RESOLUTION_Y ; biHeight +BitmapInfo_biPlanes: dw 1 ; biPlanes + dw 32 ; biBitCount + dd 0 ; biCompression + dd 0 ; biSizeImage + dd 0 ; biXPelsPerMeter + dd 0 ; biYPelsPerMeter + dd 0 ; biClrUsed + dd 0 ; biClrImportant + dd 0 ; bmiColors + +texts_uniform_loc: dd 0 +texts_uniform_name: db TEXTS_UNIFORM_NAME, 0 + +section .cdet33 code align=1 +;update_texts_time_in_EAX: +update_texts_time_on_STACK: + ; if current time >= current_text->time + ; draw text to buffer + ; move current_text pointer to next text + +.seek_loop + mov eax, [current_timing_ptr] + mov ecx, dword [eax] ; get time value from the timings + cmp ecx, [esp+4] + ja .skip + ; set current string pointer + mov ecx, [eax+TIMINGS_REC_STRING_PTR_FIELD_OFS] + mov [current_text_ptr], ecx + ; move timing pointer to next timing rec + add eax, TIMINGS_REC_SIZE + mov [current_timing_ptr], eax + jmp .seek_loop +.skip: + ret + + +section .cde3133 code align=1 +InitTextDrawingStuff: + %ifdef GEN_TEXTURES + push texts_gl_texture_name + push 1 + call [__imp__glGenTextures@8] + %endif + + push 0 + call [__imp__CreateCompatibleDC@4] + mov [textsDC], eax + ; test eax, eax + ; jz .fail + +%if TEXT_CHARACTER_EXTRA_SPACING > 0 + push TEXT_CHARACTER_EXTRA_SPACING + push eax + call [__imp__SetTextCharacterExtra@8] +%endif + +; CreateDIBSection@24 +; HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) + push 0 ; offset + push 0 ; hSection + push textsBitmapBitsPtr ; ppvBits + push DIB_RGB_COLORS ; usage + push BitmapInfo ; BITMAPINFO *pbmi + push dword [textsDC] ; hdc + call [__imp__CreateDIBSection@24] + mov [textsBitmapHandle], eax + ; test eax, eax + ; jz .fail + + mov dword [BitmapInfo], 0 ; clear the first field of BitmapInfo, so we can use it as part of the RECT structure + +; CreateFontA@56 HFONT CreateFontA(int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, +; DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCSTR pszFaceName) + push dword [text_font_name] ; font name + push 0 ; iPitchAndFamily + push ANTIALIASED_QUALITY ; iQuality + push CLIP_DEFAULT_PRECIS ; iClipPrecision + push OUT_DEFAULT_PRECIS ; iOutPrecision + push ANSI_CHARSET ; iCharSet + push TEXT_FONT_STRIKEOUT ; bStrikeOut + push TEXT_FONT_UNDERLINE ; bUnderline + push TEXT_FONT_ITALIC ; bItalic + push TEXT_FONT_WEIGHT ; cWeight FW_BOLD = 700 + push TEXT_FONT_ORIENTATION ; cOrientation + push TEXT_FONT_ESCAPEMENT ; cEscapement + push TEXT_FONT_WIDTH ; cWidth + push -TEXT_FONT_SIZE ; cHeight + call [__imp__CreateFontA@56] + + mov [textsFontHandle], eax + +.fail: + ret + + +DrawTextBitmap: +; SelectObject@8 HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) + push dword [textsBitmapHandle] + push dword [textsDC] + call [__imp__SelectObject@8] + + push dword [textsFontHandle] + push dword [textsDC] + call [__imp__SelectObject@8] + +; SetBkColor@8 COLORREF SetBkColor(HDC hdc, COLORREF color) + + push 0x000000 ; black color + push dword [textsDC] + call [__imp__SetBkColor@8] + +; SetTextColor@8 COLORREF SetTextColor(HDC hdc, COLORREF color) + push 0x00FFFFFF ; black color + push dword [textsDC] + call [__imp__SetTextColor@8] + +; some stock object constants +WHITE_BRUSH equ 0 +BLACK_BRUSH equ 4 +DC_BRUSH equ 18 + + + + push BLACK_BRUSH + call [__imp__GetStockObject@4] ; wingdi.h / Gdi32.lib / Gdi32.dll + + push eax ; HBRUSH hbr + push TextRectangle ; RECT *lprc + push dword [textsDC] ; HDC hDC + call [__imp__FillRect@12] ; winuser.h / User32.lib + +; --- functions --- User32.Lib +; DrawText@20 int DrawText(HDC hdc, LPCTSTR lpchText, int cchText, LPRECT lprc, UINT format) + push DT_CENTER ; format + push TextRectangle ; lprc + push -1 ; cchText, -1 means null-terminated + + push dword [current_text_ptr] ; lpchText + + push dword [textsDC] +%ifdef USE_WIDECHAR_TEXTS + call [__imp__DrawTextW@20] +%else + call [__imp__DrawTextA@20] +%endif + +%ifdef MORE_THAN_ONE_TEXTURE + push glActiveTexture_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + ; use texture unit 1 for texts, if there's more than one texture + push GL_TEXTURE1 + call eax + ;JUMP_ON_GL_ERROR .fail, glActiveTexture_string +%endif + +; do we want to mipmap the texts too? +;%ifdef USE_MIPMAP + ;push GL_LINEAR_MIPMAP_LINEAR +;%else + push GL_LINEAR +;%endif + push GL_TEXTURE_MIN_FILTER + push GL_TEXTURE_2D + call [__imp__glTexParameteri@12] + ; JUMP_ON_GL_ERROR .fail, glTexParameteri_string + + +; "Texture names are unsigned integers with the value zero reserved to represent the default texture for each texture target." +%ifdef MORE_THAN_ONE_TEXTURE + +%ifdef GEN_TEXTURES + push dword [texts_gl_texture_name] +%else + push 1 +%endif + push GL_TEXTURE_2D + call [__imp__glBindTexture@8] +%endif ; MORE_THAN_ONE_TEXTURE + + + push dword [textsBitmapBitsPtr] ; pixels + push GL_UNSIGNED_BYTE ; type + push GL_RGBA ; format + push 0 ; border + push TEXT_BITMAP_RESOLUTION_Y ; height + push TEXT_BITMAP_RESOLUTION_X ; width + push GL_RGBA ; internal format + push 0 ; level of detail + push GL_TEXTURE_2D + call [__imp__glTexImage2D@36] + + ;glGenTextures(1, &texture); + ;glActiveTexture(GL_TEXTURE1); + ;glBindTexture(GL_TEXTURE_2D, texture); // activate first texture +; glTexImage2D( GL_TEXTURE_2D, 0 /* level of detail */ , GL_RGBA, TEXTDISPLAY_XRES/*width*/, TEXTDISPLAY_YRES/*height*/, 0/*border*/, GL_RGBA, GL_UNSIGNED_BYTE, TextBitmaps[textindex]); + ;void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +; --- other --- +; font name e.g. "Times New Roman" + +%ifdef USE_TEXTS_UNIFORM + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push texts_uniform_name + push dword [gl_program] + call eax + mov [texts_uniform_loc], eax + ; JUMP_ON_GL_ERROR_EXT .fail, glGetUniformLocation_string, texts_uniform_name + + push glGetUniformLocation_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + + push glUniform1i_string + call [__imp__wglGetProcAddress@4] + ; FAIL_ON_WINDOWS_ERROR wglGetProcAddress_string + +%ifdef GEN_TEXTURES + push dword [texts_gl_texture_name] +%else + push 1 +%endif + push dword [texts_uniform_loc] + call eax + ; JUMP_ON_GL_ERROR .fail, glUniform1i_string +%endif ; USE_TEXTS_UNIFORM + ret + +%endif ; USE_TEXTS + +; end-of-file diff --git a/final.config b/final.config new file mode 100644 index 0000000..14b6987 --- /dev/null +++ b/final.config @@ -0,0 +1,13 @@ +# Compofiller Studio by Yzi + +PARENT_CONFIG=minified.config +include $(PARENT_CONFIG) + +# Override things that differ from the parent + +# Visuals +RESOLUTION_X=1280 +RESOLUTION_Y=720 + +CRINKLER_ORDERTRIES=4000 +OUTPUT_EXE_NAME=release.exe diff --git a/glconstants.inc b/glconstants.inc new file mode 100644 index 0000000..4a1abf5 --- /dev/null +++ b/glconstants.inc @@ -0,0 +1,9 @@ +GL_TEXTURE_2D equ 0x0DE1 +GL_TEXTURE_MIN_FILTER equ 0x2801 +GL_LINEAR equ 0x2601 +GL_TEXTURE0 equ 0x84C0 +GL_TEXTURE1 equ 0x84C1 +GL_RGBA8 equ 0x8058 +GL_UNSIGNED_BYTE equ 0x1401 +GL_RGBA equ 0x1908 +GL_LINEAR_MIPMAP_LINEAR equ 0x2703 diff --git a/map_features_to_use_defines.inc b/map_features_to_use_defines.inc new file mode 100644 index 0000000..b81fb1f --- /dev/null +++ b/map_features_to_use_defines.inc @@ -0,0 +1,66 @@ +%if USE_TIME_UNIFORM > 0 + %define USE_UNIFORMS +%else + %undef USE_TIME_UNIFORM +%endif + +%if USE_RESOLUTION_UNIFORM > 0 + %define USE_UNIFORMS +%else + %undef USE_RESOLUTION_UNIFORM +%endif + +%if USE_TEXTS = 0 + %undef USE_TEXTS +%endif + +%if USE_WIDECHAR_TEXTS = 0 + %undef USE_WIDECHAR_TEXTS +%endif + + +%if USE_TEXTS_UNIFORM > 0 + %define USE_UNIFORMS + %define USE_TEXTURES +%else + %undef USE_TEXTS_UNIFORM +%endif + +%if TWO_PASS_RENDERING > 0 + %define USE_TEXTURES + %define USE_COPY_FRAMEBUFFER_TO_TEXTURE + %ifdef USE_TEXTS + %define MORE_THAN_ONE_TEXTURE + %endif +%else +%undef TWO_PASS_RENDERING +%endif + +%if SECOND_PASS_NEGATIVE_TIME > 0 +%else +%undef SECOND_PASS_NEGATIVE_TIME +%endif + +%if FRAME_TO_TEXTURE > 0 + %define USE_TEXTURES + %define USE_COPY_FRAMEBUFFER_TO_TEXTURE + %ifdef USE_TEXTS + %define MORE_THAN_ONE_TEXTURE + %endif +%else + %undef FRAME_TO_TEXTURE +%endif + +%if USE_MIPMAP = 0 + %undef USE_MIPMAP +%endif + +%ifndef USE_TEXTURES + %undef USE_MIPMAP +%endif + +; if there's more than one texture, we have to use uniforms to set the texture names to the samplers, using uniforms +%ifdef MORE_THAN_ONE_TEXTURE + %define USE_UNIFORMS + %define USE_TEXTS_UNIFORM +%endif \ No newline at end of file diff --git a/minified.config b/minified.config new file mode 100644 index 0000000..8326f0e --- /dev/null +++ b/minified.config @@ -0,0 +1,11 @@ +# Compofiller Studio by Yzi + +PARENT_CONFIG=base.config +include $(PARENT_CONFIG) + +# Override things that differ from the parent + + +# Visuals +EXE_LINKER_PROGRAM=Crinkler +CRINKLER_ORDERTRIES=100 diff --git a/prod.nfo b/prod.nfo new file mode 100644 index 0000000..401262d --- /dev/null +++ b/prod.nfo @@ -0,0 +1,7 @@ +*** Prod Name *** +By The Demo Group +INSERT SOMETHING HERE +made by accident +greetings to Heppo + + diff --git a/shader.glsl b/shader.glsl new file mode 100644 index 0000000..fc0d5ba --- /dev/null +++ b/shader.glsl @@ -0,0 +1,314 @@ +// Compofiller Studio by Yzi 2018 +// +// Default template shader + +// This shader program is executed in the GPU (or a CPU-based emulation) for +// every pixel (i.e. "fragment" in OpenGL jargon) of every frame. + +// The "uniforms" are the same (i.e. uniform) for all pixels/fragments of the frame, +// and they come from the main program. +uniform float time; +uniform vec2 resolution; + +// If you choose to save some bytes and not use either of these uniforms, you have to +// do some additional tricks. +// * time : if you uncheck "[ ] Use time uniform" checkbox, time is in gl_Color.y (green component) +// * resolution : if you uncheck "[ ] Use resolution uniform" checkbox, you'll have to hard-code the resolution manually + +// The uniform-less version could look like this, 88200.0 being the time divider +//float time = gl_Color.y * 256.0 * (65536.0 / 88200.0); +//vec2 resolution = vec2(1280.0, 720.0); + +// Uncomment this to use the texture-based features +uniform sampler2D texture_sampler; + +// Uncomment this to use the texture-based features +uniform sampler2D texts; + +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +// Created by S. Guillitte 2015 + +float zoom=1.; + +vec2 cmul( vec2 a, vec2 b ) { return vec2( a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x ); } +vec2 csqr( vec2 a ) { return vec2( a.x*a.x - a.y*a.y, 2.*a.x*a.y ); } + + +mat2 rot(float a) { + return mat2(cos(a),sin(a),-sin(a),cos(a)); +} + +vec2 iSphere( in vec3 ro, in vec3 rd, in vec4 sph )//from iq +{ + vec3 oc = ro - sph.xyz; + float b = dot( oc, rd ); + float c = dot( oc, oc ) - sph.w*sph.w; + float h = b*b - c; + if( h<0.0 ) return vec2(-1.0); + h = sqrt(h); + return vec2(-b-h, -b+h ); +} + +float map(in vec3 p) { + + float res = 0.; + + vec3 c = p; + for (int i = 0; i < 10; ++i) { + p =.7*abs(p)/dot(p,p) -.7; + p.yz= csqr(p.yz); + p=p.zxy; + res += exp(-19. * abs(dot(p,c))); + + } + return res/2.; +} + + + +vec3 raymarch( in vec3 ro, vec3 rd, vec2 tminmax ) +{ + float t = tminmax.x; + float dt = .02; + //float dt = .2 - .195*cos(iTime*.05);//animated + vec3 col= vec3(0.); + float c = 0.; + for( int i=0; i<64; i++ ) + { + t+=dt*exp(-2.*c); + if(t>tminmax.y)break; + + c = map(ro+t*rd); + + col = .99*col+ .08*vec3(c*c, c, c*c*c);//green + //col = .99*col+ .08*vec3(c*c*c, c*c, c);//blue + } + return col; +} + + +void CoolSphere( out vec4 fragColor, in vec2 fragCoord ) +{ + float time = time; + vec2 q = fragCoord.xy / resolution.xy; + vec2 p = -1.0 + 2.0 * q; + p.x *= resolution.x/resolution.y; + vec2 m = vec2(0.); + m-=.5; + + // camera + + vec3 ro = zoom*vec3(4.); + ro.yz*=rot(m.y); + ro.xz*=rot(m.x+ 0.1*time); + vec3 ta = vec3( 0.0 , 0.0, 0.0 ); + vec3 ww = normalize( ta - ro ); + vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) ); + vec3 vv = normalize( cross(uu,ww)); + vec3 rd = normalize( p.x*uu + p.y*vv + 4.0*ww ); + + + vec2 tmm = iSphere( ro, rd, vec4(0.,0.,0.,2.) ); + + // raymarch + vec3 col = raymarch(ro,rd,tmm); + if (tmm.x<0.)col = texture(texture_sampler, rd).rgb; + else { + vec3 nor=(ro+tmm.x*rd)/2.; + nor = reflect(rd, nor); + float fre = pow(.5+ clamp(dot(nor,rd),0.0,1.0), 3. )*1.3; + col += texture(texture_sampler, nor).rgb * fre; + + } + + // shade + + col = .5 *(log(1.+col)); + col = clamp(col,0.,1.); + fragColor = vec4( col, 1.0 ); + +} + + +float bar = time; // this is just a coding nicety to highlight that in some calculations we want musical time ... you wouldn't want to have this in a real prod's final version +// --- noise from procedural pseudo-Perlin (better but not so nice derivatives) --------- + // ( adapted from IQ ) + +float gTime = 0.; + +float sdBox( vec3 p, vec3 b ) +{ + vec3 q = abs(p) - b; + return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); +} + +float box(vec3 pos, float scale) { + pos *= scale; + float base = sdBox(pos, vec3(.4,.4,.1)) /1.5; + pos.xy *= 5.; + pos.y -= 3.5; + pos.xy *= rot(.75); + float result = -base; + return result; +} + +float box_set(vec3 pos, float time) { + vec3 pos_origin = pos; + pos = pos_origin; + pos .y += sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box1 = box(pos,2. - abs(sin(gTime * 0.4)) * 1.5); + pos = pos_origin; + pos .y -=sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box2 = box(pos,2. - abs(sin(gTime * 0.4)) * 1.5); + pos = pos_origin; + pos .x +=sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box3 = box(pos,2. - abs(sin(gTime * 0.4)) * 1.5); + pos = pos_origin; + pos .x -=sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box4 = box(pos,2. - abs(sin(gTime * 0.4)) * 1.5); + pos = pos_origin; + pos.xy *= rot(.8); + float box5 = box(pos,.5) * 6.; + pos = pos_origin; + float box6 = box(pos,.5) * 6.; + float result = max(max(max(max(max(box1,box2),box3),box4),box5),box6); + return result; +} + +float map(vec3 pos, float time) { + vec3 pos_origin = pos; + float box_set1 = box_set(pos, time); + + return box_set1; +} + + +void mainImage2( out vec4 fragColor, in vec2 fragCoord ) { + vec2 p = (fragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y); + vec3 ro = vec3(0., -0.2 ,time * 4.); + vec3 ray = normalize(vec3(p, 1.5)); + ray.xy = ray.xy * rot(sin(time * .03) * 5.); + ray.yz = ray.yz * rot(sin(time * .05) * .2); + float t = 0.1; + vec3 col = vec3(0.); + float ac = 0.0; + + + for (int i = 0; i < 99; i++){ + vec3 pos = ro + ray * t; + pos = mod(pos-2., 4.) -2.; + gTime = time -float(i) * 0.01; + + float d = map(pos, time); + + d = max(abs(d), 0.01); + ac += exp(-d*23.); + + t += d* 0.55; + } + + col = vec3(ac * 0.02); + + col +=vec3(0.,0.2 * abs(sin(time)),0.5 + sin(time) * 0.2); + + + fragColor = vec4(col ,1.0 - t * (0.02 + 0.02 * sin (time))); +} + +float noise3( vec3 x ) { + vec3 p = floor(x),f = fract(x); + + f = f*f*(3.-2.*f); // or smoothstep // to make derivative continuous at borders + +#define hash3(p) fract(sin(1e3*dot(p,vec3(1,57,-13.7)))*4375.5453) // rand + + return mix( mix(mix( hash3(p+vec3(0,0,0)), hash3(p+vec3(1,0,0)),f.x), // triilinear interp + mix( hash3(p+vec3(0,1,0)), hash3(p+vec3(1,1,0)),f.x),f.y), + mix(mix( hash3(p+vec3(0,0,1)), hash3(p+vec3(1,0,1)),f.x), + mix( hash3(p+vec3(0,1,1)), hash3(p+vec3(1,1,1)),f.x),f.y), f.z); +} + +#define noise(x) (noise3(x)+noise3(x+11.5)) / 2. // pseudoperlin improvement from foxes idea + +void mainImage3( out vec4 O, vec2 U ) // ------------ draw isovalues +{ + vec2 R = resolution.xy; + float n = noise(vec3(U*8./R.y, .1*time)), + v = sin(6.28*10.*n), + t = time; + + v = smoothstep(1.,0., .5*abs(v)/fwidth(v)); + + O = mix( exp(-33./R.y )* texture2D( texture_sampler, (U+vec2(1,sin(t)))/R), // .97 + .5+.5*sin(12.*n+vec4(0,2.1,-2.1,0)), + v ); + +} + +/* "Vortex" by @kishimisu (2024) - https://www.shadertoy.com/view/MX33Dr + + It eventually leads somewhere... + + [388 → 378 chars by @Xor] +*/ + +#define R mat2(cos(vec4(0,11,33,0) + +void mainImage(out vec4 O, vec2 F) { + + vec2 V = resolution; + vec3 o; + float r = time; + float t= .1; + float e,x; + + for (O *= e; e++ < 40.; + + o.y += t*t*.09, + o.z = mod(o.z + r, .2) - .1, + x = t*.06 - r*.2, + + o.x = fract( + o.xy *= R+floor(((atan(o.y, o.x) - x) / .314) +0.5) * .314 + x)) + ).x - .8, + + t += x = length(o)*.5 - .014, + + O += (1. + cos(t*.5 + r + vec4(0,1,2,0))) + * (.3 + sin(3.*t + r*5.)/4.) + / (8. + x*4e2) + ) + o = t * normalize(vec3((F+F-V.xy)*R+r*.15)),V.y)); +} + +void main(void) +{ + float abstime = abs(time); + vec3 l; + if (abstime < 10.0) + CoolSphere(gl_FragColor, gl_FragCoord.xy); + else if (abstime < 15.0) + { + mainImage2(gl_FragColor, gl_FragCoord.xy); + } + else if (abstime < 20.0) + { + mainImage(gl_FragColor, gl_FragCoord.xy); + } + else + { + mainImage3(gl_FragColor, gl_FragCoord.xy); + } + + vec2 texttop = vec2(0., -.35), pt = (gl_FragCoord.xy / resolution) - texttop; + if (pt.y > 0.) + l = gl_FragColor + texture(texts, pt); + + + gl_FragColor = vec4(l * (1.0), 1.0); + +} diff --git a/shader_code.asm b/shader_code.asm new file mode 100644 index 0000000..4d3c63e --- /dev/null +++ b/shader_code.asm @@ -0,0 +1,16 @@ +; Compofiller Studio by Yzi 2017 +; +; This asm file is for making a COFF object file from the GLSL shader code. + +; C++ mangled name would be something like this: +;global ?shader_glsl@@3DA +;?shader_glsl@@3DA: + +section .shader0 data align=1 + +global shader_glsl +shader_glsl: + +incbin TEMP_PROCESSED_SHADER_FILE +db 0 + diff --git a/timings_and_texts.inc b/timings_and_texts.inc new file mode 100644 index 0000000..e016c75 --- /dev/null +++ b/timings_and_texts.inc @@ -0,0 +1,71 @@ +; timings_and_texts.inc +; Compofiller Studio project text strings and timings + +section .textstr0 data + +%ifdef USE_WIDECHAR_TEXTS +%define DEFINE_STRING dw +%else +%define DEFINE_STRING db +%endif + +%define END_STRING , 0 +%define SHADER_SOURCE_TEXT + +; each timing entry is a bunch of dwords +%define DEFINE_TIMING dd + +%ifndef TIME_DIVIDER_INT +error! TIME_DIVIDER_INT MUST BE DEFINED!!! +%endif + +; Kludge Construction Kit: x and y are floating point values used by the IDE's timings and texts editor, +; and z is the final integer value that has x, y and TIME_DIVIDER_INT baked into it. :/ This is needed +; because NASM is apparently unable to do the calculation and float-to-int conversion at compile time. +%define TIMING_TIME(x,y,z) (z) +REC_TIMINGS_TIME_FIELD_SIZE equ 4 +; alias is only used by the IDE, not actually assembled into any sort of data +%define TIMING_ALIAS(x) + +%ifdef USE_CUSTOM_UNIFORM +%define TIMING_CUSTOM(x) , x +REC_TIMINGS_CUSTOM_FIELD_SIZE equ 4 +%else +%define TIMING_CUSTOM(x) +REC_TIMINGS_CUSTOM_FIELD_SIZE equ 0 +%endif + +%define TIMING_STRING(x, y) , y +REC_TIMINGS_STRING_PTR_FIELD_SIZE equ 4 + +TIMINGS_REC_SIZE equ (REC_TIMINGS_TIME_FIELD_SIZE + REC_TIMINGS_CUSTOM_FIELD_SIZE + REC_TIMINGS_STRING_PTR_FIELD_SIZE) +TIMINGS_REC_STRING_PTR_FIELD_OFS equ (REC_TIMINGS_TIME_FIELD_SIZE + REC_TIMINGS_CUSTOM_FIELD_SIZE) + +; Separating the timings and actual string data enables us to do things + +section .textstr1 data +;______STRINGS_START______ +_string0: DEFINE_STRING 'Hello World' END_STRING +_string1: DEFINE_STRING 'This is Scene1' END_STRING +_string2: DEFINE_STRING 70, 105, 114, 115, 116, 32, 100, 101, 109, 111, 13, 119, 101, 32, 101, 118, 101, 114, 32, 109, 97, 100, 101 END_STRING +_string3: DEFINE_STRING 'This is Scene2' END_STRING +_string4: DEFINE_STRING 83, 97, 121, 32, 104, 105, 32, 116, 111, 13, 77, 111, 109, 32, 102, 111, 114, 32, 109, 101 END_STRING +_string5: DEFINE_STRING 'Shout out to' END_STRING +_string6: DEFINE_STRING 'Puavohard' END_STRING +_string7: DEFINE_STRING 'Goodbye!' END_STRING +;______STRINGS_END______ + +section .textstr2 data +text_string_timings: +;______TIMINGS_START______ +DEFINE_TIMING TIMING_TIME(0,0.00000,0) TIMING_ALIAS('START_TIME') TIMING_CUSTOM(0) TIMING_STRING(0,_string0) ; this is a comment +DEFINE_TIMING TIMING_TIME(1,0.00000,88200) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string1) ; this is a comment +DEFINE_TIMING TIMING_TIME(2,0.50000,220500) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string2) ; another comment +DEFINE_TIMING TIMING_TIME(10,0.00000,882000) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string3) ; this is a komment +DEFINE_TIMING TIMING_TIME(12,0.00000,1058400) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string4) ; +DEFINE_TIMING TIMING_TIME(15,0.00000,1323000) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string5) ; abcd +DEFINE_TIMING TIMING_TIME(18,0.00000,1587600) TIMING_ALIAS('') TIMING_CUSTOM(0) TIMING_STRING(0,_string6) ; efgh +DEFINE_TIMING TIMING_TIME(20,0.00000,1764000) TIMING_ALIAS('END_TIME') TIMING_CUSTOM(0) TIMING_STRING(0,_string7) ; efgh +;______TIMINGS_END______ + dd 0xFFFFFFFF ; end-of-time + diff --git a/winconstants.inc b/winconstants.inc new file mode 100644 index 0000000..12a9794 --- /dev/null +++ b/winconstants.inc @@ -0,0 +1,18 @@ +DIB_RGB_COLORS equ 0 +FW_NORMAL equ 400 +FW_BOLD equ 700 +ANSI_CHARSET equ 0 +OUT_DEFAULT_PRECIS equ 0 +CLIP_DEFAULT_PRECIS equ 0 +ANTIALIASED_QUALITY equ 4 +NONANTIALIASED_QUALITY equ 3 +DEFAULT_QUALITY equ 0 +DEFAULT_PITCH equ 0 +DT_TOP equ 0 +DT_LEFT equ 0 +DT_CENTER equ 1 +DT_RIGHT equ 2 +DT_VCENTER equ 4 +DT_BOTTOM equ 8 +DT_WORDBREAK equ 16 +