home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
g
/
gusmod11.zip
/
GUSMOD.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-15
|
45KB
|
2,080 lines
; GUSMOD v1.1
; By Joshua C. Jensen (CyberStrike of Renaissance)
; Copyright (C) 1992,1993 - All Rights Reserved
;═══════════════════════════════════════════════════════════════════════════════
ideal
P286
model Huge
jumps
stack 1024
MaxVoices = 13
include "gusmod.inc"
segment MyCode
assume cs:Mycode,ds:MyData
PspAddress dw ?
Start:
mov [cs:PspAddress],es
mov ax,es
mov bx,zzzzzseg
sub bx,ax
add bx,2
mov ah, 4ah
int 21h
mov ax,Mydata
mov ds,ax
mov dx,offset MyTitle
mov ah,9
int 21h
call U_DetectGUS
jnb @@FoundGUS
mov ah,9
mov dx,offset NoGUS
int 21h
jmp @@Exit
@@FoundGUS: call U_Reset
; Scan the command line for the module name.
mov ds, [cs:PspAddress]
mov si, 128
lodsb
or al,al ; Are we at a null?
jz @@noargv
@@MoreThanOne: mov bx,si
xor ah,ah
add bx,ax
@@TopLoop: cmp bx,si
jz @@noargv
lodsb
cmp al,' '
jz @@TopLoop
@@GetFilename: xor ah,ah
dec si
mov cx,80
@@TopGet: cmp bx,si
jz @@StoreFilename
lodsb
cmp al,'.'
jnz @@NotPeriod
mov ah,1
@@NotPeriod: cmp al,13
jz @@StoreFilename
loop @@TopGet
@@StoreFilename:or ah,ah
jnz @@JustZero
mov [Byte si],'.'
mov [Byte si+1],'M'
mov [Byte si+2],'O'
mov [Byte si+3],'D'
add si,4
@@JustZero: mov [Byte si],0
mov [Byte si+1],'$'
; Load the module.
mov dx, 130 ; Psp Command Tail + 2
call s_LoadModule
jb @@nofile
jmp @@BeginPlay
@@noargv: mov ax,MyData
mov ds,ax
mov dx,offset NoFileName
mov ah,9
int 21h
jmp @@exit
@@nofile: mov ax,MyData
mov ds,ax
mov dx,offset NoFileFound
mov ah,9
int 21h
jmp @@exit
@@BeginPlay: mov al,0
call U_ChangeInOut
call sd_SetMaxVolume
call s_PlayMusic
@@PollLoop: mov ah,1
int 16h
jnz @@KeyHit
jmp @@PollLoop
@@KeyHit: call s_StopMusic
call U_Reset
@@Exit: call s_CloseAllMusic
mov ax,4C00h
int 21h
ends MyCode
segment MyData
label MyTitle byte
db ' GUSMOD v1.1',10,13
db ' By Joshua C. Jensen (CyberStrike of Renaissance)',13,10
db ' Copyright (C) 1992,1993 - All Rights Reserved',10,13
db '════════════════════════════════════════════════════════════════════════════════$'
NoGUS db 'Could not detect a Gravis Ultrasound card.',13,10,'$'
NoFileName db 'Usage: GUSMOD filename.mod',13,10,'$'
NoFileFound db 'File not found.',13,10,'$'
;
;
ends MyData
segment Sound
assume cs:Sound,ds:Sound
Header:
songname db 20 dup (0)
samples db 31*size SampleRec dup (0)
songlen db 0
restart db 0
sequences db 128 dup (0)
mk dd 0
HeaderSize = $-Header
PatternLoc dw 64 dup (0)
InsLoc dd 32 dup (0)
NumPatterns dw 0
IntStore dd 0
Base dw 220h
proc UDelay
push dx ax
mov dx,300h
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
pop ax dx
ret
endp UDelay
; BX:CX Set to whatever.
proc U_Peek
push dx
mov dx,[cs:u_Command]
mov al,43h
out dx,al
inc dx ; 104h
mov ax,cx
out dx,ax
dec dx ; 103h
mov al,44h
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
in al,dx
pop dx
ret
endp U_Peek
; BX:CX Set to whatever.
; AX Value to poke
proc U_Poke
push dx ax
mov dx,[cs:u_Command]
mov al,43h
out dx,al
inc dx
mov ax,cx
out dx,ax
dec dx
mov al,44h
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
pop ax
out dx,al
in al,dx
pop dx
ret
endp U_Poke
; DX - Base.
proc U_Probe
mov dx,[cs:u_Command]
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,0
out dx,al
call UDelay
call UDelay
sub dx,2 ; 103h
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,1
out dx,al
call UDelay
call UDelay
mov ax,0AAh
mov bx,0
mov cx,0
call U_Poke
mov ax,055h
mov bx,1
call U_Poke
mov bx,0
call U_Peek
push ax
mov ax,0
call U_Poke
sub dx,2 ; 103h
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,0
out dx,al
pop ax
cmp al,0AAh
jnz @@Nope
clc
ret
@@Nope: stc
ret
endp U_Probe
proc U_Reset
mov dx,[cs:u_Command]
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,1
out dx,al
call UDelay
sub dx,2
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,7
out dx,al
sub dx,2
mov al,0Eh
out dx,al
add dx,2
mov al,MaxVoices
or al,0C0h
out dx,al
mov cx,0
@@VoiceClearLoop:
mov dx,[cs:u_Voice]
mov al,cl
out dx,al
inc dx
mov al,0
out dx,al
add dx,2
mov al,3 ; Turn voice off
out dx,al
sub dx,2
mov al,0Dh
out dx,al
add dx,2
mov al,3
out dx,al
inc cx
cmp cx,32
jnz @@VoiceClearLoop
ret
endp U_Reset
; CX:AX - Number
proc RShift
mov bx,cx
shr ax,7
shr cx,7
shl bx,9
or ax,bx
ret
endp RShift
; AX - Voice
; Returns: DX:AX - Position
proc U_ReadPos
mov dx,[cs:u_Voice]
out dx,al
inc dx ; 103h
mov al,8ah
out dx,al
inc dx ; 104h
in ax,dx ; TEMP0
mov cx,ax
dec dx ; 103h
mov al,8bh
out dx,al
inc dx ; 104h
in ax,dx ; TEMP1
xor dx,dx
mov bx,cx
shl cx,7
shl dx,7
shr bx,9
or dx,bx
shr ax,9
and ax,7Fh
or cx,ax
mov ax,cx
ret
endp U_ReadPos
; AX-Mixer control
; bit 0: 0=linein on, 1=linein off
; bit 1: 0=output on, 1=output off
; bit 2: 0=micin off, 1=micin on
proc U_ChangeInOut
mov dx,[cs:Base]
out dx,al
ret
endp U_ChangeInOut
; The only reason I do it this way is because I haven't figured out the dump
; RAM to DRAM via DMA yet.
;
; Dump sample to Ram
; ES:BX - Max 64k sample to dump to RAM.
; SI:DI - DRAM location to dump to.
; CX - Max bytes to dump.
;
; Approximate time to dump 1 megabyte of samples to DRAM (assuming they were
; all loaded in memory) is 5 seconds.
proc U_DumpSampleToDRAM
push cx
mov dx,[cs:u_Command]
mov al,44h ; Dump upper byte, only do it on carry from now
out dx,al ; on.
add dx,2
push ax
mov ax,si
out dx,al
pop ax
sub dx,2
@@MainLoop:
mov al,43h
out dx,al
inc dx
push ax
mov ax,di
out dx,ax
pop ax
dec dx
add di,1
jnc @@DumpByte
inc si
mov al,44h
out dx,al
add dx,2
push ax
mov ax,si
out dx,al
pop ax
sub dx,2
@@DumpByte:
add dx,4
mov al,[es:bx]
xor al,ah
inc bx
out dx,al
sub dx,4
loop @@MainLoop
pop cx
ret
endp U_DumpSampleToDRAM
u_Voice dw 0
u_Command dw 0
u_DataLo dw 0
u_DataHi dw 0
; Carry set - No GUS
; No carry - GUS at Base
proc U_DetectGUS
mov [Word cs:Base],210h
@@TestIt:
mov dx,[cs:Base]
add dx,102h
mov [cs:u_Voice],dx
inc dx
mov [cs:u_Command],dx
inc dx
mov [cs:u_DataLo],dx
inc dx
mov [cs:u_DataHi],dx
call U_Probe
jnb @@FoundIt
add [Word cs:Base],10h
cmp [Word cs:Base],270h
jb @@TestIt
stc
@@FoundIt:
ret
endp U_DetectGUS
;▓────────────────────────────────────────────────────────────────────────────▓
; s_PlayMusic - Make proper calls and interrupt sets for module playing.
;▓────────────────────────────────────────────────────────────────────────────▓
proc sd_SetMaxVolume
push ds
mov ax,cs
mov ds,ax
mov al,200 ; Master volume scale value
mov [Byte Channel1+(offset (MS).MasterVolume)],al
mov [Byte Channel2+(offset (MS).MasterVolume)],al
mov [Byte Channel3+(offset (MS).MasterVolume)],al
mov [Byte Channel4+(offset (MS).MasterVolume)],al
pop ds
ret
endp sd_SetMaxVolume
proc s_PlayMusic far
pusha
push ds
mov [word cs:mt_Speed],6
mov [word cs:mt_Counter],1
mov [word cs:mt_SongPos],0
mov [Word cs:mt_PatternPos],0
call sd_SetMaxVolume
;
; Setup playing interrup routine
;
mov ax,0
mov ds,ax
mov bx,8*4
mov ax,[ds:bx]
mov [Word cs:IntStore],ax
mov ax,[ds:bx+2]
mov [Word cs:IntStore+2],ax
cli
mov [Word ds:bx],offset PlayInt
mov [ds:bx+2],cs
mov ax,cs
mov ds,ax
mov al,36h
out 43h,al ; timer program
mov ax,1193180/50
out 40h,al
mov al,ah
out 40h,al
sti
@@End: pop ds
popa
ret
endp s_PlayMusic
;▓────────────────────────────────────────────────────────────────────────────▓
; s_StopMusic - Shuts down the interrupts for generating music.
;▓────────────────────────────────────────────────────────────────────────────▓
proc s_StopMusic far
pusha
push ds
cli
mov ax,0
mov ds,ax
mov bx,8*4
mov ax,[Word cs:IntStore]
mov [ds:bx],ax
mov ax,[Word cs:IntStore+2]
mov [ds:bx+2],ax
mov al,36h
out 43h,al
xor al,al
out 40h,al
out 40h,al
sti
pop ds
popa
ret
endp s_StopMusic
; CX - Sample Size
; SI:DI - Place in DRAM
; BX - Handle
LDSeg dw 0
proc LoadDumpSample
push cx bx
mov ah,48h
mov bx,cx
shr bx,4
inc bx
int 21h
mov [cs:LDSeg],ax
pop bx
push ds
mov ah,3Fh
mov dx,0
mov ds,[cs:LDSeg]
int 21h
pop ds
pop cx
mov es,[cs:LDSeg]
mov bx,0
mov ah,0
call U_DumpSampleToDRAM
mov ah,49h
mov es,[cs:LDSeg]
int 21h
ret
endp LoadDumpSample
;▓────────────────────────────────────────────────────────────────────────────▓
; s_LoadModule - Load in the module pointed to by DS:DX.
;▓────────────────────────────────────────────────────────────────────────────▓
Handle dw 0
proc s_LoadModule
pusha
push ds es
mov ax,3D00h
int 21h
mov [cs:Handle],ax
mov ax,cs
mov ds,ax
mov es,ax
call s_ReadMod
mov ax,3E00h
mov bx,[cs:Handle]
int 21h
pop es ds
popa
ret
endp s_LoadModule
;▓────────────────────────────────────────────────────────────────────────────▓
; s_ReadMod - Read the header, all patterns, and all samples from module.
;▓────────────────────────────────────────────────────────────────────────────▓
LocInList dw ?
proc s_ReadMod
push ds
mov ax,3F00h ; Read the header
mov bx,[cs:Handle]
mov dx,offset Header
mov cx,HeaderSize
int 21h
call s_LoadPatterns
mov cx,31
mov bx,offset samples+(offset (SampleRec).Length)
@@FlipLoop:
mov ax,[cs:bx] ; Flip length
xchg ah,al
shl ax,1
mov [cs:bx],ax
mov ax,[cs:bx+4] ; Flip repeat
xchg ah,al
shl ax,1
mov [cs:bx+4],ax
mov ax,[cs:bx+6] ; Flip repeat length
xchg ah,al
shl ax,1
mov [cs:bx+6],ax
add bx,size SampleRec
loop @@FlipLoop
mov cx,31
mov bx,offset samples+(offset (SampleRec).Length)
mov [Word cs:LocInList],0
mov si,0 ; Location in DRAM to begin
mov di,0
@@DoSamples: push cx
mov ax,[cs:bx]
or ax,ax
jz @@ZeroByteSample
mov cx,ax ; Save for read from disk.
push bx
mov bx,[cs:LocInList]
mov [Word cs:bx+InsLoc],di
mov [Word cs:bx+InsLoc+2],si
add [Word cs:LocInList],4
mov bx,[cs:Handle]
call LoadDumpSample
pop bx
jmp @@Bottom
@@ZeroByteSample:
push bx
mov bx,[cs:LocInList]
mov [Word cs:bx+InsLoc],0
mov [Word cs:bx+InsLoc+2],0f000h
add [Word cs:LocInList],4
pop bx
@@Bottom: add bx,size SampleRec
pop cx
loop @@DoSamples
pop ds
ret
endp s_ReadMod
proc s_GetHighestBlock
mov si,offset sequences
mov cx,128
xor ax,ax
@@SetBlock: mov ah,al
jmp @@BotLoop
@@SearchLoop: lodsb
cmp al,ah
jg @@SetBlock
@@BotLoop: loop @@SearchLoop
mov al,ah
inc al
xor ah,ah ; Clear ah.
ret
endp s_GetHighestBlock
proc s_LoadPatterns
mov cx,64
mov di,offset PatternLoc
xor ax,ax
rep stosw
call s_GetHighestBlock
mov [cs:NumPatterns],ax
mov di,offset PatternLoc
mov cx,ax
@@BlockAllocLoop:
mov bx,1024/4+1
mov ah,48h
int 21h
stosw
loop @@BlockAllocLoop
mov si,offset PatternLoc
xor dx,dx ; Load all segments at 0 offset.
xor cx,cx
@@BlockReadLoop:
push cx
push ds
mov cx,1024
mov bx,[cs:Handle]
lodsw
mov ds,ax
mov ax,3F00h ; Load in the block.
int 21h
pop ds cx
inc cx
cmp cx,[cs:NumPatterns]
jnz @@BlockReadLoop
clc
ret
endp s_LoadPatterns
proc s_CloseAllMusic
push ds
mov ax,cs
mov ds,ax
@@FreePatterns: mov si,offset PatternLoc
mov cx,64
@@FreePatLoop: lodsw
or ax,ax
jz @@BotFreePatLoop
mov es,ax
mov ax,4900h
int 21h
jnb @@BotFreePatLoop
stc
pop ds
ret
@@BotFreePatLoop:
loop @@FreePatLoop
pop ds
ret
endp s_CloseAllMusic
proc PlayInt
pusha
push ds es
call sd_UpdateChannels
sti
mov al,20h
out 20h,al
pop es ds
popa
iret
endp PlayInt
;┌──────────────────────────────────────────────────────────────────────────┐
;│││──────────────────────── Protracker Stuff ────────────────────────────│││
;└──────────────────────────────────────────────────────────────────────────┘
;┌─┐ Protracker specific
;└─┘ variables.
mt_speed db 6
mt_counter db 0
mt_PatternPos dw 0
mt_SongPos db 0
mt_PattDelayTime2 db 0
mt_PattDelayTime db 0
mt_PBreakFlag db 0
mt_PBreakPos db 0
mt_PosJumpFlag db 0
mt_LowMask db 0FFh
mt_FunkTable db 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
mt_VibratoTable: db 0, 24, 49, 74, 97,120,141,161
db 180,197,212,224,235,244,250,253
db 255,253,250,244,235,224,212,197
db 180,161,141,120, 97, 74, 49, 24
Channel1 MS <0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
Channel2 MS <0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
Channel3 MS <0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
Channel4 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
PlayStatus db 0
MStatus db 0
MainFreq dd 0
Mode db 0
SOffsetSet db 0
mt_VolTable dw 00000h,0A000h,0A800h,0B000h,0B800h,0C000h,0C400h,0C800h,0CC00h
dw 0D000h,0D200h,0D400h,0D600h,0D800h,0DA00h,0DC00h,0DE00h
dw 0E000h,0E100h,0E200h,0E300h,0E400h,0E500h,0E600h,0E700h
dw 0E800h,0E900h,0EA00h,0EB00h,0EC00h,0ED00h,0EE00h,0EF00h
dw 0F080h,0F100h,0F180h,0F200h,0F280h,0F300h,0F380h,0F400h
dw 0F480h,0F500h,0F580h,0F600h,0F680h,0F700h,0F780h,0F800h
dw 0F880h,0F900h,0F980h,0FA00h,0FA80h,0FB00h,0FB80h,0FC00h
dw 0FC80h,0FD00h,0FD80h,0FE00h,0FE80h,0FF00h,0FF80h,0FFFFh
mt_PeriodTable:
; Tuning 0, Normal
dw 856,808,762,720,678,640,604,570,538,508,480,453
dw 428,404,381,360,339,320,302,285,269,254,240,226
dw 214,202,190,180,170,160,151,143,135,127,120,113,0
; Tuning 1
dw 850,802,757,715,674,637,601,567,535,505,477,450
dw 425,401,379,357,337,318,300,284,268,253,239,225
dw 213,201,189,179,169,159,150,142,134,126,119,113,0
; Tuning 2
dw 844,796,752,709,670,632,597,563,532,502,474,447
dw 422,398,376,355,335,316,298,282,266,251,237,224
dw 211,199,188,177,167,158,149,141,133,125,118,112,0
; Tuning 3
dw 838,791,746,704,665,628,592,559,528,498,470,444
dw 419,395,373,352,332,314,296,280,264,249,235,222
dw 209,198,187,176,166,157,148,140,132,125,118,111,0
; Tuning 4
dw 832,785,741,699,660,623,588,555,524,495,467,441
dw 416,392,370,350,330,312,294,278,262,247,233,220
dw 208,196,185,175,165,156,147,139,131,124,117,110,0
; Tuning 5
dw 826,779,736,694,655,619,584,551,520,491,463,437
dw 413,390,368,347,328,309,292,276,260,245,232,219
dw 206,195,184,174,164,155,146,138,130,123,116,109,0
; Tuning 6
dw 820,774,730,689,651,614,580,547,516,487,460,434
dw 410,387,365,345,325,307,290,274,258,244,230,217
dw 205,193,183,172,163,154,145,137,129,122,115,109,0
; Tuning 7
dw 814,768,725,684,646,610,575,543,513,484,457,431
dw 407,384,363,342,323,305,288,272,256,242,228,216
dw 204,192,181,171,161,152,144,136,128,121,114,108,0
; Tuning -8
dw 907,856,808,762,720,678,640,604,570,538,508,480
dw 453,428,404,381,360,339,320,302,285,269,254,240
dw 226,214,202,190,180,170,160,151,143,135,127,120,0
; Tuning -7
dw 900,850,802,757,715,675,636,601,567,535,505,477
dw 450,425,401,379,357,337,318,300,284,268,253,238
dw 225,212,200,189,179,169,159,150,142,134,126,119,0
; Tuning -6
dw 894,844,796,752,709,670,632,597,563,532,502,474
dw 447,422,398,376,355,335,316,298,282,266,251,237
dw 223,211,199,188,177,167,158,149,141,133,125,118,0
; Tuning -5
dw 887,838,791,746,704,665,628,592,559,528,498,470
dw 444,419,395,373,352,332,314,296,280,264,249,235
dw 222,209,198,187,176,166,157,148,140,132,125,118,0
; Tuning -4
dw 881,832,785,741,699,660,623,588,555,524,494,467
dw 441,416,392,370,350,330,312,294,278,262,247,233
dw 220,208,196,185,175,165,156,147,139,131,123,117,0
; Tuning -3
dw 875,826,779,736,694,655,619,584,551,520,491,463
dw 437,413,390,368,347,328,309,292,276,260,245,232
dw 219,206,195,184,174,164,155,146,138,130,123,116,0
; Tuning -2
dw 868,820,774,730,689,651,614,580,547,516,487,460
dw 434,410,387,365,345,325,307,290,274,258,244,230
dw 217,205,193,183,172,163,154,145,137,129,122,115,0
; Tuning -1
dw 862,814,768,725,684,646,610,575,543,513,484,457
dw 431,407,384,363,342,323,305,288,272,256,242,228
dw 216,203,192,181,171,161,152,144,136,128,121,114,0
;
;
include "ptable.inc"
macro SetVoice V
mov [Byte cs:Voice],V
mov dx,[cs:u_Voice]
mov al,V
out dx,al
endm SetVoice
Voice db 0
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ NAME : sd_UpdateChannels │
;│ *** Original code: Amiga Protracker by Lars "Zap" Hamre. │
;│ *** Converted by Joshua C. Jensen. │
;╘═══════════════════════════════════════════════════════════════════════════╛
proc sd_UpdateChannels near
mov ax,cs
mov ds,ax
mov es,ax
mt_ContinueUpdate:
inc [Byte cs:mt_counter]
mov al,[cs:mt_counter]
cmp al,[cs:mt_speed]
jb mt_NoNewNote
mov [Byte cs:mt_counter],0
cmp [Byte cs:mt_PattDelayTime2],0
jz mt_GetNewNote
call mt_NoNewAllChannels
jmp mt_dskip
mt_NoNewNote:
call mt_NoNewAllChannels
jmp mt_NoNewPosYet
mt_NoNewAllChannels:
SetVoice 1
mov si,offset Channel1
call mt_CheckEfx
SetVoice 2
mov si,offset Channel2
call mt_CheckEfx
SetVoice 3
mov si,offset Channel3
call mt_CheckEfx
SetVoice 4
mov si,offset Channel4
jmp mt_CheckEfx
mt_GetNewNote:
xor ax,ax
mov al,[cs:mt_SongPos]
mov di,ax
mov al,[cs:di+sequences]
shl al,1
mov di,offset PatternLoc
add di,ax
mov es,[cs:di]
mov di,[cs:mt_PatternPos]
SetVoice 1
mov si,offset Channel1
call mt_PlayVoice
SetVoice 2
mov si,offset Channel2
call mt_PlayVoice
SetVoice 3
mov si,offset Channel3
call mt_PlayVoice
SetVoice 4
mov si,offset Channel4
call mt_PlayVoice
jmp mt_dskip
mt_PlayVoice:
mov [Byte cs:Mode],0
cmp [Word cs:si],0
jnz mt_plvskip
cmp [Word cs:si+2],0
jnz mt_plvskip
call mt_PerNop
mt_plvskip:
mov ax,[es:di]
mov [cs:si+MS.Note],ax
mov ax,[es:di+02h]
mov [Word cs:si+MS.cmd],ax
add di,4
mov al,[cs:si+MS.cmd]
and al,0F0h
shr al,4
mov ah,[Byte cs:si+MS.Note]
and ah,0F0h
or al,ah ; Is there an ins?
jz mt_SetRegisters
dec al
mov bl,al
; mov [cs:bp+CD.sins],al
mov [cs:si+MS.SampleNum],al
mov bh,size SampleRec
mul bh
mov dx,ax
xor bh,bh
shl bx,2
add bx,offset InsLoc
mov ax,[cs:bx]
mov [Word cs:si+MS.start],ax
mov ax,[cs:bx+2]
mov [Word cs:si+(offset (MS).start)+2],ax
mov bx,dx
add bx,(offset (SampleRec).Length)
add bx,offset samples
mov cx,[Word cs:bx]
sub cx,3
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
add ax,cx
adc dx,0
mov [Word cs:si+MS.Length],ax
mov [Word cs:si+(offset (MS).Length)+2],dx
mov [Word cs:si+MS.RealLength],cx
mov ax,[Word cs:bx+2]
mov [Word cs:si+MS.FineTune],ax
mov al,ah
call volequ
mov cx,[Word cs:bx+6]; Get the Repeat length.
cmp cx,2
jbe mt_NoLoop
mov cx,[Word cs:bx+4]
or [Byte cs:Mode],00001000b
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
add ax,cx
adc dx,0
mov [Word cs:si+MS.loopstart],ax
mov [Word cs:si+(offset (MS).loopstart)+2],dx
mov [Word cs:si+MS.wavestart],ax
mov [Word cs:si+(offset (MS).wavestart)+2],dx
mov ax,[Word cs:bx+6]
mov [Word cs:si+MS.RepLen],ax
jmp mt_SetRegisters
mt_NoLoop:
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
mov [Word cs:si+MS.loopstart],ax
mov [Word cs:si+(offset (MS).loopstart)+2],dx
mov [Word cs:si+MS.wavestart],ax
mov [Word cs:si+(offset (MS).wavestart)+2],dx
mov ax,[Word cs:bx]
mov [Word cs:si+MS.RepLen],ax
mt_SetRegisters:
mov ax,[cs:si+MS.Note]
xchg ah,al
and ax,0FFFh
jz mt_CheckMoreEfx
mov ax,[Word cs:si+MS.cmd]
xchg ah,al
and ax,0FF0h
cmp ax,0E50h
jz mt_DoSetFineTune
cmp ah,3 ; Is it a tone portamento?
jz mt_ChkTonePorta
cmp ah,5 ; Is it a tone and volume slide?
jz mt_ChkTonePorta
cmp ah,9 ; Is it a sample offset command?
jnz mt_SetPeriod
call mt_CheckMoreEfx
jmp mt_SetPeriod
mt_DoSetFineTune:
call mt_SetFineTune
jmp mt_SetPeriod
mt_ChkTonePorta:
call mt_SetTonePorta
jmp mt_CheckMoreEfx
mt_SetPeriod:
mov ax,[cs:si+MS.Note]
xchg ah,al
and ax,0FFFh
mov bx,offset mt_PeriodTable
mov cx,36
mt_ftuloop:
cmp ax,[cs:bx]
jnb mt_ftufound
add bx,2
loop mt_ftuloop
mt_ftufound:
mov al,[cs:si+MS.FineTune]
mov cl,37*2
mul cl
add bx,ax
mov ax,[cs:bx]
mov [cs:si+MS.Period],ax
mov ax,[Word cs:si+MS.cmd]
xchg ah,al
and ax,0FF0h
cmp ax,0ED0h
jz mt_CheckMoreEfx
mov al,[cs:si+MS.WaveControl] ; Get the WaveControl.
and al,00000100b ; Amiga: BTST #2,WaveControl.
jz mt_vibnoc ; If it is zero, then skip.
mov [Byte cs:si+MS.VibratoPos],0
mt_vibnoc:
mov al,[cs:si+MS.WaveControl] ; Get it again.
and al,01000000b ; Amiga: BTST #6,WaveControl
jz mt_trenoc ; If it is zero, then skip.
mov [Byte cs:si+MS.TremoloPos],0 ; Zero the Tremolo offset.
mt_trenoc:
; high byte of sample start == F000H, turn off the voice
cmp [Word cs:si+(offset (MS).start)+2],0f000h
jz @@NoVoice
cmp [Byte cs:SOffsetSet],1
jz @@SkipBegin
mov dx,[cs:u_Command]
mov al,0
out dx,al
call UDelay
mov al,0
out dx,al
add dx,2
mov al,[Byte cs:Mode]
or al,3
out dx,al
; Send sample begin
mov dx,[cs:u_Command]
mov al,0ah
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.start]
mov cx,[Word cs:si+(offset (MS).start)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,0bh
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.start]
shl ax,9
out dx,ax
@@SkipBegin:
mov [Byte cs:SOffsetSet],0
mov dx,[cs:u_Command]
mov al,2
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.loopstart]
mov cx,[Word cs:si+(offset (MS).loopstart)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,3
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.loopstart]
shl ax,9
out dx,ax
mov dx,[cs:u_Command]
mov al,4
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.length]
mov cx,[Word cs:si+(offset (MS).length)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,5
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.length]
shl ax,9
out dx,ax
dec dx ; 103h
mov cx,[cs:si+MS.Period]
call mt_PerNop
; mov al,[Byte cs:si+MS.Volume]
; call volequ
mov dx,[cs:u_Command]
mov al,0ch
out dx,al
add dx,2
mov al,0 ; channel 1 pan
cmp [cs:Voice],1
jz @@C3
mov al,15 ; channel 2 pan
cmp [cs:Voice],2
jz @@C3
mov al,12 ; channel 3 pan
cmp [cs:Voice],3
jz @@C3
mov al,3 ; channel 4 pan
@@C3:
out dx,al
sub dx,2
mov al,0
out dx,al
call UDelay
mov al,0
out dx,al
add dx,2
mov al,[Byte cs:Mode]
out dx,al
jmp @@Bottom
;
; Shuts off the voice
;
@@NoVoice:
mov [Byte cs:SOffsetSet],0
mov al,0
out dx,al
add dx,2
mov al,[Byte cs:Mode]
or al,00000011b
out dx,al
@@Bottom:
@@Done:
; call SpectrumAnalyzer
mov [cs:si+MS.Trigger],1
jmp mt_CheckMoreEfx
endp sd_UpdateChannels
proc mt_dskip near
add [Word cs:mt_PatternPos],16
mov al,[cs:mt_PattDelayTime]
or al,al
jz mt_dskc
mov [cs:mt_PattDelayTime2],al
mov [Byte cs:mt_PattDelayTime],0
mt_dskc:
cmp [Byte cs:mt_PattDelayTime2],0
jz mt_dska
dec [Byte cs:mt_PattDelayTime2]
jz mt_dska
sub [Word cs:mt_PatternPos],16
mt_dska:
cmp [Byte cs:mt_PBreakFlag],0
jz mt_nnpysk
mov [Byte cs:mt_PBreakFlag],0
xor ax,ax
mov al,[cs:mt_PBreakPos]
mov [cs:mt_PBreakPos],ah
shl ax,4
mov [cs:mt_PatternPos],ax
mt_nnpysk:
cmp [Word cs:mt_PatternPos],1024
jb mt_NoNewPosYet
mt_NextPosition:
xor ax,ax
mov al,[cs:mt_PBreakPos]
shl ax,4
mov [cs:mt_PatternPos],ax
mov [Byte cs:mt_PBreakPos],0
mov [Byte cs:mt_PosJumpFlag],0
inc [Byte cs:mt_SongPos]
and [Byte cs:mt_SongPos],7Fh
mov al,[cs:mt_SongPos]
cmp al,[cs:songlen]
jnz mt_NoNewPosYet
mov [Byte cs:mt_SongPos],0
cmp [Byte cs:PlayStatus],1
jnz @@Quit
mov [Byte cs:mt_SongPos],0
ret
;---------------------------------------------------
@@Quit: mov [Byte cs:MStatus],1
mov [Byte cs:mt_SongPos],0
ret
mt_NoNewPosYet:
cmp [Byte cs:mt_PosJumpFlag],0
jnz mt_NextPosition
ret
endp mt_dskip
proc mt_CheckEfx near
call mt_UpdateFunk
mov ax,[Word cs:si+MS.cmd] ; Get the special command
xchg al,ah
and ax,0FFFh
jz mt_Return ;mt_Return
mov bl,[cs:si+MS.cmd] ; Contains the command to do
and bl,0Fh
cmp bl,0
jz mt_Arpeggio
cmp bl,1
jz mt_PortaUp
cmp bl,2
jz mt_PortaDown
cmp bl,3
jz mt_TonePortamento
cmp bl,4
jz mt_Vibrato
cmp bl,5
jz mt_TonePlusVolSlide
cmp bl,6
jz mt_VibratoPlusVolSlide
cmp bl,0Eh
jz mt_E_Commands
SetBack:call mt_PerNop
cmp bl,7
jz mt_Tremolo
cmp bl,0Ah
jz mt_VolumeSlide
mt_Return:
ret
endp mt_CheckEfx
proc mt_PerNop near
mov ax,[cs:si+MS.Period] ; get Period Value
proc mt_PerNop2 near
and ax,0FFFh
or ax,ax
jz @@Outit
push bx ; ????
push di
mov bx,ax
sub bx,100 ; bx = bx - 100
shl bx,1 ; bx = bx * 2
mov di,Offset Ptable
mov ax,[cs:di+bx]
pop di
pop bx
; mov cx,ax
; xor dx,dx
; mov ax,8448
; div cx
; mov cx,428
; mul cx
; mov cx,19
; div cx
@@OutIt:
push ax
mov dx,[cs:u_Command]
mov al,1 ; set frequency
out dx,al
inc dx
pop ax
out dx,ax
ret
endp mt_PerNop2
endp mt_PerNop
; Effect 0 -- Arpeggio
proc mt_Arpeggio near
xor ax,ax
mov al,[cs:mt_counter]
mov bl,3
div bl
xchg al,ah
cmp al,1
jz mt_Arpeggio1
cmp al,2
jz mt_Arpeggio2
mt_Arpeggio0:
mov cx,[cs:si+MS.period]
jmp ArpeggioSet
mt_Arpeggio1:
xor ax,ax
mov al,[Byte cs:si+MS.cmdlo]
shr al,4
jmp ArpeggioFind
mt_Arpeggio2:
xor ax,ax
mov al,[cs:si+MS.cmdlo]
and al,15
ArpeggioFind:
shl ax,1
mov bx,ax
mov al,[cs:si+MS.FineTune]
mov cl,37*2
mul cl
mov dx,[cs:si+MS.Period]
push di
mov di,offset mt_PeriodTable
add di,ax
mov cx,36
mt_arploop:
mov ax,[cs:bx+di]
cmp dx,[cs:di]
jnb mt_arpafterloop
add di,2
loop mt_arploop
pop di
ret
mt_arpafterloop:
pop di
mov cx,ax
ArpeggioSet:
call mt_PerNop2
ret
endp mt_Arpeggio
; Effect 1 -- Portamento Up
proc mt_PortaUp near
xor ax,ax
mov al,[cs:si+MS.cmdlo] ; Number to slide up
and al,[cs:mt_LowMask]
mov [Byte cs:mt_LowMask],0FFh
sub [cs:si+MS.Period],ax
mov cx,[cs:si+MS.Period]
and cx,0FFFh
cmp cx,71h
jnb mt_PortaUSkip
and [cs:si+MS.Period],0F000h
or [cs:si+MS.Period],71h
mt_PortaUSkip:
mov cx,[cs:si+MS.Period]
and cx,0FFFh
call mt_PerNop
ret
endp mt_PortaUp
; Effect 2 -- Portamento Down
proc mt_PortaDown near
xor ax,ax
mov al,[cs:si+MS.cmdlo] ; Number to slide down
and al,[cs:mt_LowMask]
mov [Byte cs:mt_LowMask],0FFh
add [cs:si+MS.Period],ax
mov cx,[cs:si+MS.Period]
and cx,0FFFh
cmp cx,358h
jb mt_PortaDSkip
and [cs:si+MS.Period],0F000h
or [cs:si+MS.Period],856
mt_PortaDSkip:
mov cx,[cs:si+MS.Period]
and cx,0FFFh
call mt_PerNop
ret
endp mt_PortaDown
proc mt_SetTonePorta near
push di
mov dx,[cs:si+MS.Note]
xchg dh,dl
and dx,0FFFh
xor ax,ax
mov al,[cs:si+MS.FineTune]
mov cl,37*2
mul cl
mov di,offset mt_PeriodTable
add di,ax
mov bx,0
mt_StpLoop:
cmp dx,[cs:bx+di]
jnb mt_StpFound
add bx,2
cmp bx,37*2
jb mt_StpLoop
mov bx,35*2
mt_StpFound:
mov dl,[cs:si+MS.FineTune]
and dl,8
jz mt_StpGoss
or bx,bx
jz mt_StpGoss
sub bx,2
mt_StpGoss:
mov dx,[cs:bx+di]
pop di
mov [cs:si+MS.WantedPeriod],dx
mov ax,[cs:si+MS.Period]
mov [Byte cs:si+MS.TonePortDirec],0
cmp dx,ax
jz mt_ClearTonePorta
jnb mt_Return
mov [Byte cs:si+MS.TonePortDirec],1
ret
mt_ClearTonePorta:
mov [Word cs:si+MS.WantedPeriod],0
ret
endp mt_SetTonePorta
; Effect 3 -- Tone Portamento
proc mt_TonePortamento near
mov al,[cs:si+MS.cmdlo]
or al,al
jz mt_TonePortNoChange
mov [cs:si+MS.TonePortSpeed],al
mov [Byte cs:si+MS.cmdlo],0
mt_TonePortNoChange:
cmp [Word cs:si+MS.WantedPeriod],0
jz mt_Return
xor ax,ax
mov al,[cs:si+MS.TonePortSpeed]
cmp [Byte cs:si+MS.TonePortDirec],0
jnz mt_TonePortaUp
mt_TonePortaDown:
add [cs:si+MS.Period],ax
mov ax,[cs:si+MS.WantedPeriod]
cmp ax,[cs:si+MS.Period]
jg mt_TonePortaSetPer
mov [cs:si+MS.Period],ax
mov [Word cs:si+MS.WantedPeriod],0
jmp mt_TonePortaSetPer
mt_TonePortaUp:
sub [cs:si+MS.Period],ax
mov ax,[cs:si+MS.WantedPeriod]
cmp ax,[cs:si+MS.Period]
jl mt_TonePortaSetPer
mov [cs:si+MS.Period],ax
mov [Word cs:si+MS.WantedPeriod],0
mt_TonePortaSetPer:
mov cx,[cs:si+MS.Period]
mov al,[cs:si+MS.GlissFunk]
and al,0Fh
jz mt_GlissSkip
mov al,[cs:si+MS.FineTune]
mov bl,37*2
mul bl
push di
mov di,offset mt_PeriodTable
add di,ax
mov bx,0
mt_GlissLoop:
cmp cx,[cs:bx+di]
jnb mt_GlissFound
add bx,2
cmp bx,37*2
jb mt_GlissLoop
mov bx,35*2
mt_GlissFound:
mov cx,[cs:bx+di]
pop di
mt_GlissSkip:
call mt_PerNop
ret
endp mt_TonePortamento
; Effect 4 -- Vibrato
proc mt_Vibrato near
mov al,[cs:si+MS.cmdlo]
or al,al
jz mt_Vibrato2
mov cl,[cs:si+MS.VibratoCmd]
and al,0fh
jz mt_vibskip
and cl,0F0h
or cl,al
mt_vibskip:
mov al,[cs:si+MS.cmdlo]
and al,0F0h
jz mt_vibskip2
and cl,0Fh
or cl,al
mt_vibskip2:
mov [cs:si+MS.VibratoCmd],cl
mt_Vibrato2:
mov al,[cs:si+MS.VibratoPos]
mov bx,offset mt_VibratoTable
shr ax,2
and ax,001Fh
xor cx,cx
mov cl,[cs:si+MS.WaveControl]
and cl,03h
jz mt_vib_sine
shl al,3
cmp cl,1
jz mt_vib_rampdown
mov cl,255
jmp mt_vib_set
mt_vib_rampdown:
cmp [Byte cs:si+MS.VibratoPos],0
jnb mt_vib_rampdown2
mov cl,255
sub cl,al
jmp mt_vib_set
mt_vib_rampdown2:
mov cl,al
jmp mt_vib_set
mt_vib_sine:
add bl,al
mov cl,[cs:bx]
mt_vib_set:
mov al,[cs:si+MS.VibratoCmd]
and al,0Fh
mul cl
shr ax,7
mov cx,ax
mov ax,[cs:si+MS.Period]
cmp [Byte cs:si+MS.VibratoPos],0
jb mt_VibratoNeg ; BMI
add ax,cx
jmp mt_Vibrato3
mt_VibratoNeg:
sub ax,cx
mt_Vibrato3:
mov cx,ax
call mt_PerNop2
mov al,[cs:si+MS.VibratoCmd]
shr ax,2
and ax,3Ch
add [cs:si+MS.VibratoPos],al
ret
endp mt_Vibrato
; Effect 5 -- Tone and Volume Slide
proc mt_TonePlusVolSlide near
call mt_TonePortNoChange
jmp mt_VolumeSlide
endp mt_TonePlusVolSlide
; Effect 6 -- Vibrato and Volume Slide
proc mt_VibratoPlusVolSlide near
call mt_Vibrato2
jmp mt_VolumeSlide
endp mt_VibratoPlusVolSlide
; Effect 7 -- Tremolo
proc mt_Tremolo near
mov al,[Byte cs:si+MS.cmdlo]
or al,al
jz mt_Tremolo2
mov cl,[cs:si+MS.TremoloCmd]
and al,0Fh
jz mt_treskip
and cl,0F0h
or cl,al
mt_treskip:
mov al,[Byte cs:si+MS.cmdlo]
and al,0F0h
jz mt_treskip2
and cl,0Fh
or cl,al
mt_treskip2:
mov [cs:si+MS.TremoloCmd],cl
mt_Tremolo2:
mov al,[cs:si+MS.TremoloPos]
shr al,2
and ax,001Fh
xor cx,cx
mov cl,[cs:si+MS.WaveControl]
shr cl,4
and cl,03h
jz mt_tre_sine
shl al,3
cmp cl,1
jz mt_tre_rampdown
mov cl,255
jmp mt_tre_set
mt_tre_rampdown:
cmp [Byte cs:si+MS.VibratoPos],0
jnb mt_tre_rampdown2
mov cl,255
sub cl,al
jmp mt_tre_set
mt_tre_rampdown2:
mov cl,al
jmp mt_tre_set
mt_tre_sine:
xor bx,bx
mov bl,al
mov cl,[cs:bx+offset mt_VibratoTable]
mt_tre_set:
mov al,[cs:si+MS.TremoloCmd]
and al,0Fh
mul cl
mov cx,ax
shr cx,6
mov al,[cs:si+MS.Volume]
cmp [Byte cs:si+MS.TremoloPos],0
jb mt_TremoloNeg ; BMI jns
add al,cl
jmp mt_Tremolo3
mt_TremoloNeg:
sub al,cl
mt_Tremolo3:
jnb mt_TremoloSkip
xor ax,ax
mt_TremoloSkip:
cmp al,40h
jb mt_TremoloOK ; BLS
mov al,40h
mt_TremoloOK:
call volequ
mov al,[cs:si+MS.TremoloCmd]
shr al,2
and al,3Ch
add [cs:si+MS.TremoloPos],al
ret
endp mt_Tremolo
TempHi dw 0
TempLo dw 0
; Effect 9 -- Sample Offset
proc mt_SampleOffset near
xor ax,ax
mov al,[Byte cs:si+MS.cmdlo]
or al,al
jz mt_sononew
mov [cs:si+MS.SampleOffset],al
mt_sononew:
mov al,[cs:si+MS.SampleOffset] ; Variance in Protracker code.
shl ax,8
; cmp ax,[cs:si+MS.Reallength]
; jge mt_sofskip
mov cx,ax
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
add ax,cx
adc dx,0
mov [Word cs:si+MS.start],ax
mov [Word cs:si+(offset (MS).start)+2],dx
ret
mt_sofskip:
ret
endp mt_SampleOffset
; Effect A -- Volume Slide
proc mt_VolumeSlide near
mov al,[cs:si+MS.cmdlo]
shr al,4
or al,al
jz mt_VolSlideDown
mt_VolSlideUp:
add [Byte cs:si+MS.Volume],al
cmp [Byte cs:si+MS.Volume],40h
jb mt_vsuskip
mov [Byte cs:si+MS.Volume],40h
mt_vsuskip:
mov al,[Byte cs:si+MS.Volume]
call volequ
ret
mt_VolSlideDown:
mov al,[cs:si+MS.cmdlo]
and al,0Fh
mt_VolSlideDown2:
sub [Byte cs:si+MS.Volume],al
jnb mt_vsdskip
mov [Byte cs:si+MS.Volume],0
mt_vsdskip:
mov al,[Byte cs:si+MS.Volume]
call volequ
ret
endp mt_VolumeSlide
; Effect B -- Position Jump
proc mt_PositionJump near
mov al,[Byte cs:si+MS.cmdlo] ; Get where to jump
dec al ; Update the
mov [cs:mt_SongPos],al ; information.
mt_pj2: mov [Byte cs:mt_PBreakPos],0
mov [Byte cs:mt_PosJumpFlag],1
ret
endp mt_PositionJump
; Effect C -- Volume Change
proc mt_VolumeChange near
mov al,[Byte cs:si+MS.cmdlo] ; Get value for volume
cmp al,40h ; Is it greater than 40h?
jb mt_VolumeOK ; Nope
mov al,40h
mt_VolumeOK:
mov [cs:si+MS.Volume],al ; Get it again
call volequ
ret
endp mt_VolumeChange
; Effect D -- Pattern Break
proc mt_PatternBreak near
mov al,[Byte cs:si+MS.cmdlo] ; Break to where?
mov cl,al
shr al,4
mov bl,10
mul bl
and cl,0Fh
add al,cl
cmp al,63
jg mt_pj2
mov [cs:mt_PBreakPos],al
mov [Byte cs:mt_PosJumpFlag],1
ret
endp mt_PatternBreak
; Effect F -- Set Speed
; Doesn't handle Protracker extended speeds.
proc mt_SetSpeed near
mov al,[Byte cs:si+MS.cmdlo] ; Get value for speed
or al,al
jz @@SSpe1
cmp al,32
jnb @@SSpe1
mov [Byte cs:mt_counter],0
mov [Byte cs:mt_speed],al
@@SSPe1:ret
endp mt_SetSpeed
proc mt_CheckMoreEfx near
call mt_UpdateFunk
mov bl,[cs:si+MS.cmd]
and bl,0Fh
cmp bl,09h
jz mt_SampleOffset
cmp bl,0Bh
jz mt_PositionJump
cmp bl,0Dh
jz mt_PatternBreak
cmp bl,0Eh
jz mt_E_Commands
cmp bl,0Fh
jz mt_SetSpeed
cmp bl,0Ch
jz mt_VolumeChange
jmp mt_PerNop
endp mt_CheckMoreEfx
proc mt_E_Commands near
mov bl,[Byte cs:si+MS.cmdlo]
and bl,0F0h
shr bl,4
cmp bl,0
jz mt_FilterOnOff
cmp bl,1
jz mt_FinePortaUp
cmp bl,2
jz mt_FinePortaDown
cmp bl,3
jz mt_SetGlissControl
cmp bl,4
jz mt_SetVibratoControl
cmp bl,5
jz mt_SetFineTune
cmp bl,6
jz mt_JumpLoop
cmp bl,7
jz mt_SetTremoloControl
cmp bl,8
jz mt_KarplusStrong
cmp bl,0Eh
jz mt_PatternDelay
cmp bl,9
jz mt_RetrigNote
cmp bl,0Ah
jz mt_VolumeFineUp
cmp bl,0Bh
jz mt_VolumeFineDown
cmp bl,0Ch
jz mt_NoteCut
cmp bl,0Dh
jz mt_NoteDelay
cmp bl,0Fh
jz mt_FunkIt
ret
endp mt_E_Commands
;──────────────────────────────────────────────────────────────────────────
; Effect E
;──────────────────────────────────────────────────────────────────────────
; Effect 0 -- FilterOnOff
proc mt_FilterOnOff near
mov al,[Byte cs:si+MS.cmdlo]
and al,1
sal al,1
; Amiga
; Stuff
ret
endp mt_FilterOnOff
; Effect 1 -- Fine Porta Up
proc mt_FinePortaUp near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov [Byte cs:mt_LowMask],0Fh
jmp mt_PortaUp
endp mt_FinePortaUp
; Effect 2 -- Fine Porta Down
proc mt_FinePortaDown near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov [Byte cs:mt_LowMask],0Fh
jmp mt_PortaDown
endp mt_FinePortaDown
; Effect 3 -- Set Gliss Control
proc mt_SetGlissControl near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
and [Byte cs:si+MS.GlissFunk],0F0h
or [cs:si+MS.GlissFunk],al
ret
endp mt_SetGlissControl
; Effect 4 -- Set Vibrato Control
proc mt_SetVibratoControl near
mov al,[cs:si+MS.cmdlo]
and al,0Fh
and [Byte cs:si+MS.WaveControl],0F0h
or [cs:si+MS.WaveControl],al
ret
endp mt_SetVibratoControl
; Effect 5 -- Set Fine Tune
proc mt_SetFineTune near
mov al,[cs:si+MS.cmdlo]
and al,0Fh
mov [cs:si+MS.FineTune],al
ret
endp mt_SetFineTune
; Effect 6 -- Jump Loop
proc mt_JumpLoop near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jz mt_SetLoop
cmp [Byte cs:si+MS.loopcount],0
jz mt_jumpcnt
dec [Byte cs:si+MS.loopcount]
jz mt_Return
mt_jmploop:
mov al,[cs:si+MS.pattpos]
mov [cs:mt_PBreakPos],al
mov [Byte cs:mt_PBreakFlag],1
ret
mt_jumpcnt:
mov [cs:si+MS.loopcount],al
jmp mt_jmploop
mt_SetLoop:
mov ax,[cs:mt_PatternPos]
shr ax,4
and ax,63
mov [cs:si+MS.pattpos],al
ret
endp mt_JumpLoop
; Effect 7 -- Set Tremolo Control
proc mt_SetTremoloControl near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
shl al,4
and [Byte cs:si+MS.WaveControl],0Fh
or [cs:si+MS.WaveControl],al
ret
endp mt_SetTremoloControl
proc mt_KarplusStrong near
; mov ax,[cs:si+MS.loopstart]
mov bx,ax
; mov ax,[cs:si+MS.RepLen]
add ax,ax
sub ax,2
karplop:
; More here.
ret
endp mt_KarplusStrong
; Effect 9 -- Retrig Note
proc mt_RetrigNote near
mov bl,[Byte cs:si+MS.cmdlo]
and bl,0Fh
jz mt_rtnend
xor ax,ax
mov al,[cs:mt_counter]
or al,al
jnz mt_rtnskp
mov ax,[cs:si+MS.Note]
xchg ah,al
and ax,0FFFh
jnz mt_rtnend
; mov [Byte cs:mt_counter],0
xor ax,ax
mov al,[cs:mt_counter]
mt_rtnskp:
div bl
xchg ah,al
or ax,ax
jnz mt_rtnend
mt_DoRetrig:
xor ax,ax
; mov [cs:bp+CD.sofs],ax
; mov ax,[cs:si+MS.Length]
shl ax,1
; mov [cs:bp+CD.slen],ax
; mov ax,[cs:si+MS.LoopStart]
; mov [cs:bp+CD.sloops],ax
; mov cx,[cs:si+MS.RepLen]
add ax,cx ; Add on the offset.
add ax,cx ; Add it again.
sub ax,3
; mov [cs:bp+CD.sloope],ax
mt_rtnend:
ret
endp mt_RetrigNote
; Effect A -- Volume Fine Up
proc mt_VolumeFineUp near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jmp mt_VolSlideUp
endp mt_VolumeFineUp
; Effect B -- Volume Fine Down
proc mt_VolumeFineDown near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jmp mt_VolSlideDown2
endp mt_VolumeFineDown
; Effect C -- Note Cut
proc mt_NoteCut near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp al,[cs:mt_counter]
jnz mt_Return
mov [Byte cs:si+MS.Volume],0
mov al,[Byte cs:si+MS.Volume]
call volequ
ret
endp mt_NoteCut
; Effect D -- Note Delay
proc mt_NoteDelay near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp al,[cs:mt_counter]
jnz mt_Return
mov ax,[cs:si]
and ax,0FFFh
jz mt_Return
jmp mt_DoRetrig
endp mt_NoteDelay
; Effect E -- Pattern Delay
proc mt_PatternDelay near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp [Byte cs:mt_PattDelayTime2],0
jnz mt_Return
inc al
mov [cs:mt_PattDelayTime],al
ret
endp mt_PatternDelay
; Effect F -- Funk It
proc mt_FunkIt near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
shl al,4
and [Byte cs:si+MS.GlissFunk],0Fh
or [cs:si+MS.GlissFunk],al
or al,al
jz mt_Return
jmp mt_UpdateFunk
endp mt_FunkIt
proc mt_UpdateFunk near
xor bx,bx
mov bl,[cs:si+MS.GlissFunk]
shr bl,4
or bl,bl
jz mt_funkend
mov al,[cs:bx+offset mt_FunkTable]
add [cs:si+MS.FunkOffset],al
mov al,[cs:si+MS.FunkOffset]
and al,10000000b
jz mt_funkend
mov [Byte cs:si+MS.FunkOffset],0
; This is my best try at converting this code.
; mov ax,[cs:si+MS.LoopStart]
; mov bx,[cs:si+MS.RepLen]
; add ax,bx
; add ax,bx
; mov cx,[cs:si+MS.WaveStart]
; inc cx
; cmp cx,ax
; jb mt_funkok
; mov cx,[cs:si+MS.LoopStart]
;mt_funkok:
; mov [cs:si+MS.WaveStart],cx
; mov ax,-1
; mov bx,cx
; sub [cs:bx],ax
; mov ax,[cs:bx]
mt_funkend:
ret
endp mt_UpdateFunk
proc volequ near
push bx
mul [Byte cs:si+MS.MasterVolume]
mov bl,ah
xor bh,bh
shl bx,1
mov dx,[cs:u_Command]
mov al,9
out dx,al
inc dx
; cmp [Byte cs:Voice],4
; jnz @@Leave
mov ax,[cs:bx+mt_VolTable]
out dx,ax
pop bx
ret
@@Leave:
mov ax,0
out dx,ax
pop bx
ret
endp volequ
ends Sound
segment zzzzzseg
db 16 dup (?)
ends zzzzzseg
end Start