[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]
{
Here is the PASCAL version of a portion of the Assembler code I used in my
game to get General Midi sound. I've compiled the program, and it works fine
on my GM device, MEGA-EM a TSR for the Gravis Ultrasound.
No checking is performed, make sure you have the correct hardware, but
it should run due to the timeout checking.
If you don't get sound, then it's probably because no instrument was
defined. Send a program change midi sequence.
Feel free to toss this in SWAG. Sound code is always requested,
and General Midi is so simple compared to everything else.
}
Program GMTest;
(*
Take from Colin Buckley's cheezy shareware game Tubes, written in BP.
The actual GM code is a converted assembler file, thus the obvious macro
like sequences, register passing, and semi-colon comments. Sorry for any
typos/bugs introduced during the quick conversion.
This is completely public domain. Which means no restrictions whatsoever.
{$DEFINE EducateTheMasses}
To the uninformed, you can not say something is public domain, then paste a
copyright on it and say it's required for you to be acknowledged or
get a post card or something. You give up all rights when you give something
to the public domain. What you want, is called freeware.
{$ENDIF}
*)
Const
GMPort = $331;
Send = $80;
Receive = $40;
{ AL:=Command; }
Procedure WriteGMCommand; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ;Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Receive {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
OUT DX,AL {;Send Data }
End;
{ ; AL:=Data }
Procedure WriteGM; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ; Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{ ; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Receive {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
DEC DX {;DX:=DataPort }
OUT DX,AL {;Send Data }
End;
{ ;Returns Data }
Function ReadGM:Byte; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ; Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{ ; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Send {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
DEC DX {;DX:=DataPort }
IN AL,DX {;Receive Data }
End;
Procedure ResetGM; Assembler;
ASM
{ ;Reset GM }
MOV DX,GMPort
MOV AL,0FFh
OUT DX,AL
{; Get ACK }
CALL ReadGM
{; UART Mode }
MOV AL,03Fh
CALL WriteGMCommand
End;
Procedure SetNoteOn(Channel,Note,Volume:Byte); Assembler;
ASM
MOV AL,[Channel]
ADD AL,90h
Call WriteGM
MOV AL,[Note]
CALL WriteGM
MOV AL,[Volume]
CALL WriteGM
End;
Procedure SetNoteOff(Channel,Note,Volume:Byte); Assembler;
ASM
MOV AL,[Channel]
ADD AL,80h
Call WriteGM
MOV AL,[Note]
CALL WriteGM
MOV AL,[Volume]
CALL WriteGM
End;
Begin
ResetGM;
SetNoteOn(0,64,127);
ASM
{ ;Wait for Key }
XOR AX,AX
INT 16h
End;
SetNoteOff(0,64,127);
ResetGM;
End.
[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]