-
Notifications
You must be signed in to change notification settings - Fork 4
/
sound.asm
636 lines (607 loc) · 13.4 KB
/
sound.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
SEGMENT CODE ; 8
; Sound & music
%include "base.inc"
%include "constants.asm"
;%include "structs.asm"
%include "variables.asm"
%include "func.mac"
%include "if.mac"
%include "extern.inc"
%include "windows.inc"
; 0
%define SEM_NOOPENFILEERRORBOX 0x8000
func InitSound
sub sp,byte +0x2
push si
; Tell OpenFile not to display an error message on file not found
push word SEM_NOOPENFILEERRORBOX
call far KERNEL.SetErrorMode ; 11
mov si,ax
; Load MMSYSTEM.DLL
push ds
push word s_MMSYSTEM_DLL
call far KERNEL.LoadLibrary ; 1c
mov [hmoduleMMSystem],ax
cmp ax,0x20
if na
jmp .failedToLoadLibrary ; ↓
endif ; 2c
; Look up a bunch of functions from the library
push ax
push ds
push word s_sndPlaySound
call far KERNEL.GetProcAddress ; 31
mov [fpSndPlaySound+FarPtr.Off],ax
mov [fpSndPlaySound+FarPtr.Seg],dx
push word [hmoduleMMSystem]
push ds
push word s_mciSendCommand
call far KERNEL.GetProcAddress ; 45
mov [fpMciSendCommand+FarPtr.Off],ax
mov [fpMciSendCommand+FarPtr.Seg],dx
push word [hmoduleMMSystem]
push ds
push word s_mciGetErrorString
call far KERNEL.GetProcAddress ; 59
mov [fpMciGetErrorString+FarPtr.Off],ax
mov [fpMciGetErrorString+FarPtr.Seg],dx
push word [hmoduleMMSystem]
push ds
push word s_midiOutGetNumDevs
call far KERNEL.GetProcAddress ; 6d
mov [fpMidiOutGetNumDevs+FarPtr.Off],ax
mov [fpMidiOutGetNumDevs+FarPtr.Seg],dx
push word [hmoduleMMSystem]
push ds
push word s_waveOutGetNumDevs
call far KERNEL.GetProcAddress ; 81
mov [fpWaveOutGetNumDevs+FarPtr.Off],ax
mov [fpWaveOutGetNumDevs+FarPtr.Seg],dx
; Enable (or disable) Background Music menu item if midiOutGetNumDevs() != 0
call far [fpMidiOutGetNumDevs] ; 8d
cmp ax,0x1
sbb ax,ax
inc ax
mov [MusicMenuItemEnabled],ax
; Enable (or disable) Sound Effects menu item if waveOutGetNumDevs() != 0
call far [fpWaveOutGetNumDevs] ; 9a
cmp ax,0x1
sbb ax,ax
inc ax
mov [SoundMenuItemEnabled],ax
; If we can't play midi, turn music off
cmp word [MusicMenuItemEnabled],byte +0x0
if z
mov word [MusicEnabled],0x0
endif ; b4
; if we can't play sounds, turn sound effects off
or ax,ax
jnz .done ; ↓
mov [SoundEnabled],ax
jmp short .done ; ↓
nop
.failedToLoadLibrary: ; be
xor ax,ax
mov [hmoduleMMSystem],ax
mov [SoundMenuItemEnabled],ax
mov [MusicMenuItemEnabled],ax
mov [SoundEnabled],ax
mov [MusicEnabled],ax
.done: ; cf
; change error mode back
push si
call far KERNEL.SetErrorMode ; d0
; Return 1 if we loaded the module sucessfully, 0 otherwise
cmp word [hmoduleMMSystem],byte +0x1
sbb ax,ax
inc ax
pop si
endfunc
; e6
func TeardownSound
sub sp,byte +0x2
cmp word [hmoduleMMSystem],byte +0x0
if nz
push word [hmoduleMMSystem]
call far KERNEL.FreeLibrary ; fe
endif ; 103
mov word [hmoduleMMSystem],0x0
endfunc
; 110
; start midi
func StartMIDI
%arg hWnd:word
%arg filename:dword
%arg param_c:word
; return value in dx:ax
sub sp,byte +0x5e
cmp word [param_c],byte +0x0
if nz
jmp .label5 ; ↓
endif ; 126
mov word [bp-0x56], s_sequencer
mov [bp-0x54],ds
mov ax,[filename+FarPtr.Off]
mov dx,[filename+FarPtr.Seg]
mov [bp-0x52],ax
mov [bp-0x50],dx
mov word [bp-0x4e],EmptyStringForMciSendCommand
mov [bp-0x4c],ds
push byte +0x0
push word 0x803 ; MCI_OPEN
push byte +0x0
push word 0x2200
lea ax,[bp-0x5e]
push ss
push ax
call far [fpMciSendCommand] ; 151
mov [bp-0x6],ax
mov [bp-0x4],dx
or dx,ax
if nz
.returnSomething: ; 15f
mov ax,[bp-0x6]
mov dx,[bp-0x4]
jmp .return ; ↓
endif ; 168
mov word [bp-0x42],0x4003
mov word [bp-0x40],0x0
mov ax,[bp-0x5a]
mov [MCIDeviceID],ax
push ax
push word 0x814 ; MCI_STATUS
push byte +0x0
push word 0x100
lea ax,[bp-0x4a]
push ss
push ax
call far [fpMciSendCommand] ; 186
mov [bp-0x6],ax
mov [bp-0x4],dx
or dx,ax
jz .label4 ; ↓
.label3: ; 194
push word [MCIDeviceID]
push word 0x804 ; MCI_CLOSE
push byte +0x0
push byte +0x0
push byte +0x0
push byte +0x0
call far [fpMciSendCommand] ; 1a3
mov word [MIDIPlaying],0x0
jmp short .returnSomething ; ↑
nop
.label4: ; 1b0
cmp word [bp-0x46],byte -0x1
jz .label5 ; ↓
push byte +0x4
push ds
push word s_The_MIDI_Mapper_is_not_available_Continue?
push word [hwndMain]
call far ShowMessageBox ; 1c0 2:0
add sp,byte +0x8
cmp ax,0x7
jnz .label5 ; ↓
push word [MCIDeviceID]
push word 0x804 ; MCI_CLOSE
push byte +0x0
push byte +0x0
push byte +0x0
push byte +0x0
call far [fpMciSendCommand] ; 1dc
mov word [MIDIPlaying],0x0
jmp short .returnZero ; ↓
.label5: ; 1e8
mov word [MIDIPlaying],0x1
mov ax,[hWnd]
mov [bp-0x3a],ax
mov [bp-0x38],ds
sub ax,ax
mov [bp-0x34],ax
mov [bp-0x36],ax
push word [MCIDeviceID]
push word 0x806 ; MCI_PLAY
push ax
push byte +0x5
lea ax,[bp-0x3a]
push ss
push ax
call far [fpMciSendCommand] ; 20e
mov [bp-0x6],ax
mov [bp-0x4],dx
or dx,ax
jz .returnZero ; ↓
jmp .label3 ; ↑
.returnZero: ; 21f
xor ax,ax
cwd
.return: ; 222
endfunc
; 22a
func FUN_8_022a
sub sp,byte +0x2
push byte +0x1
push byte +0x0
push byte +0x0
push word [hwndMain]
call far StartMIDI ; 241 8:110
add sp,byte +0x8
or dx,ax
if z
mov ax,0x1
else ; 252
xor ax,ax
endif ; 254
endfunc
; 25c
func ShowMIDIError
sub sp,0x11a
push si
push word [bp+0xc] ; filename seg
push word [bp+0xa] ; filename
push ds
push word s_MIDI_Error_on_file_s
lea ax,[bp-0x11a]
push ss
push ax
call far USER._wsprintf ; 27b
add sp,byte +0xc
mov ax,[fpMciGetErrorString+FarPtr.Seg]
or ax,[fpMciGetErrorString+FarPtr.Off]
jz .label0 ; ↓
push word [bp+0x8]
push word [bp+0x6]
lea ax,[bp-0x11a]
push ss
push ax
call far KERNEL.lstrlen ; 298
mov si,ax
lea ax,[bp+si-0x11b]
push ss
push ax
push word 0x80
call far [fpMciGetErrorString] ; 2a8
or ax,ax
jz .label0 ; ↓
push byte +0x30
lea ax,[bp-0x11a]
push ss
push ax
jmp short .label1 ; ↓
.label0: ; 2ba
push byte +0x30
push ds
push word s_Unknown_Error
.label1: ; 2c0
push word [hwndMain]
call far ShowMessageBox ; 2c4 2:0
add sp,byte +0x8
pop si
endfunc
; 2d4
; stop music
func StopMIDI
sub sp,byte +0x2
cmp word [MIDIPlaying],byte +0x0
if nz
push word [MCIDeviceID]
push word 0x804 ; MCI_CLOSE
push byte +0x0
push byte +0x0
push byte +0x0
push byte +0x0
call far [fpMciSendCommand] ; 2f7
endif ; 2fb
mov word [MIDIPlaying],0x0
endfunc
; 308
; change level
func FUN_8_0308
sub sp,byte +0x12
push di
push si
; some preliminary checks
cmp word [MusicEnabled],byte +0x0
if z
jmp .returnZero ; ↓
endif ; 321
mov ax,[fpMciSendCommand+FarPtr.Seg]
or ax,[fpMciSendCommand+FarPtr.Off]
if z
jmp .returnZero ; ↓
endif ; 32d
cmp word [NumMIDIFiles],byte +0x0
if z
jmp .returnZero ; ↓
endif ; 337
call far StopMIDI ; 337 8:2d4
mov ax,[bp+0x6] ; level number
cwd
idiv word [NumMIDIFiles]
mov si,dx
.loop: ; 346
mov ax,[NumMIDIFiles]
shl ax,1
add ax,MIDIArray-2
mov [bp-0x6],ax
.label4: ; 351
mov bx,si
cmp word [bx+si+MIDIArray],byte +0x0
if nz
jmp .label9 ; ↓
endif ; 35d
lea cx,[si+0x1]
cmp cx,[NumMIDIFiles]
jnl .label7 ; ↓
mov [bp-0xc],si
mov bx,cx
shl bx,1
add bx,MIDIArray-2
mov dx,[NumMIDIFiles]
sub dx,cx
mov [bp-0x4],cx
.label6: ; 37a
mov ax,[bx+0x2]
mov [bx],ax
add bx,byte +0x2
dec dx
jnz .label6 ; ↑
mov si,[bp-0xc]
.label7: ; 388
mov bx,[bp-0x6]
sub word [bp-0x6],byte +0x2
mov word [bx],0x0
dec word [NumMIDIFiles]
cmp [NumMIDIFiles],si
if e
xor si,si
endif ; 39f
cmp word [NumMIDIFiles],byte +0x0
jnz .label4 ; ↑
call far StopMIDI ; 3a6 8:2d4
push word [hwndMain]
push word 0x111
push byte ID_BGM
push byte +0x0
push byte +0x0
call far USER.SendMessage ; 3b8
push byte +0x30
push ds
push word s_None_of_the_MIDI_files_specified___
push word [hwndMain]
call far ShowMessageBox ; 3c7 2:0
add sp,byte +0x8
push word [hMenu]
push byte ID_BGM
push byte +0x1
call far USER.EnableMenuItem ; 3d7
jmp .returnZero ; ↓
nop
.label9: ; 3e0
shl bx,1
add bx,MIDIArray
mov [bp-0x12],bx
mov ax,[bx]
mov di,ax
mov [bp-0xe],ds
push byte +0x0
push byte +0x0
push word 0x7f02 ; hourglass
call far USER.LoadCursor ; 3f7
mov [bp-0x8],ax
push word [hwndMain]
call far USER.SetCapture ; 403
push word [bp-0x8]
call far USER.SetCursor ; 40b
mov [bp-0xa],ax
push byte +0x0
push word [bp-0xe]
push di
push word [hwndMain]
call far StartMIDI ; 41d 8:110
add sp,byte +0x8
mov [bp-0x6],ax
mov [bp-0x4],dx
push word [bp-0xa]
call far USER.SetCursor ; 42e
call far USER.ReleaseCapture ; 433
mov ax,[bp-0x4]
or ax,[bp-0x6]
jz .label11 ; ↓
cmp word [bp-0x6],0x113
jnz .break ; ↓
cmp word [bp-0x4],byte +0x0
jnz .break ; ↓
mov bx,[bp-0x12]
push word [bx]
call far KERNEL.LocalFree ; 452
mov bx,[bp-0x12]
mov word [bx],0x0
jmp .loop ; ↑
nop
.break: ; 462
push word [bp-0xe] ; filename
push di
push word [bp-0x4]
push word [bp-0x6]
call far ShowMIDIError ; 46c 8:25c
add sp,byte +0x8
push word [hwndMain]
push word 0x111
push byte ID_BGM
push byte +0x0
push byte +0x0
call far USER.SendMessage ; 481
.label11: ; 486
mov ax,[bp-0x4]
or ax,[bp-0x6]
jnz .returnZero ; ↓
mov ax,0x1
jmp short .label13 ; ↓
nop
.returnZero: ; 494
xor ax,ax
.label13: ; 496
pop si
pop di
endfunc
; 4a0
; Get the path to all sound and MIDI files and store them in the
; global sound/midi arrays.
func InitAudioFiles
sub sp,0x102
push di
push si
;; Sound
xor di,di
mov si,SoundArray
.soundLoop: ; 4b5
push byte +0x0
push byte +0x1
push word 0x100
lea ax,[bp-0x102]
push ax
push di
call far GetAudioPath ; 4c2 2:1ca0
add sp,byte +0x8
inc ax
push ax
call far KERNEL.LocalAlloc ; 4cc
mov [si],ax
or ax,ax
jz .nextSound ; ↓
push ds
push ax
lea ax,[bp-0x102]
push ss
push ax
call far KERNEL.lstrcpy ; 4df
.nextSound: ; 4e4
inc di
add si,byte +0x2
cmp si,SoundArray.end
jb .soundLoop ; ↑
;; MIDI
push word ID_NumMidiFiles
call far GetIniInt ; 4f1 2:198e
add sp,byte +0x2
cmp ax,NumMidiFilesMax
if ge
mov ax,NumMidiFilesMax
else ; 504
push word ID_NumMidiFiles
call far GetIniInt ; 507 2:198e
add sp,byte +0x2
endif ; 50f
mov [NumMIDIFiles],ax
push ax
push word ID_NumMidiFiles
call far StoreIniInt ; 516 2:19ca
add sp,byte +0x4
xor di,di
cmp [NumMIDIFiles],di
jng .label6 ; ↓
mov si,MIDIArray
.midiLoop: ; 529
push byte +0x0
push byte +0x0
push word 0x100
lea ax,[bp-0x102]
push ax
push di
call far GetAudioPath ; 536 2:1ca0
add sp,byte +0x8
inc ax
push ax
call far KERNEL.LocalAlloc ; 540
mov [si],ax
or ax,ax
jz .nextMidiFile ; ↓
push ds
push ax
lea ax,[bp-0x102]
push ss
push ax
call far KERNEL.lstrcpy ; 553
.nextMidiFile: ; 558
add si,byte +0x2
inc di
cmp di,[NumMIDIFiles]
jl .midiLoop ; ↑
.label6: ; 562
pop si
pop di
endfunc
; 56c
func PlaySoundEffect
sub sp,byte +0x6
cmp word [SoundEnabled],byte +0x0
jz .end ; ↓
mov ax,[fpSndPlaySound+FarPtr.Seg]
or ax,[fpSndPlaySound+FarPtr.Off]
jz .end ; ↓
mov bx,[bp+0x6]
shl bx,1
mov ax,[SoundArray+bx]
mov dx,ds
mov cx,ax
mov [bp-0x4],dx
or dx,ax
jz .end ; ↓
push word [bp-0x4]
push cx
cmp word [bp+0x8],byte +0x1
sbb ax,ax
and ax,0x10 ; SND_NOSTOP
or al,0x3 ; SND_ASYNC | SND_NODEFAULT
push ax
call far [fpSndPlaySound] ; 5ad
.end: ; 5b1
endfunc
; 5b8
; Free the paths stored in SoundArray and MIDIArray
func FreeAudioFiles
sub sp,byte +0x4
push di
push si
mov ax,[fpSndPlaySound+FarPtr.Seg]
or ax,[fpSndPlaySound+FarPtr.Off]
if nz
push byte +0x0
push byte +0x0
push byte +0x0
call far [fpSndPlaySound] ; 5d6
endif ; 5da
mov si,SoundArray
mov di,[bp-0x4]
.soundLoop: ; 5e0
cmp word [si],byte +0x0
if nz
push word [si]
call far KERNEL.LocalFree ; 5e7
endif ; 5ec
add si,byte +0x2
cmp si,SoundArray.end
jb .soundLoop ; ↑
xor di,di
cmp [NumMIDIFiles],di
jng .end ; ↓
mov si,MIDIArray
.midiLoop: ; 600
cmp word [si],byte +0x0
if nz
push word [si]
call far KERNEL.LocalFree ; 607
endif ; 60c
add si,byte +0x2
inc di
cmp di,[NumMIDIFiles]
jl .midiLoop ; ↑
.end: ; 616
pop si
pop di
endfunc
; 620
GLOBAL _segment_8_size
_segment_8_size equ $ - $$
; vim: syntax=nasm