ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл лллллллллллллллллллл лллллллллллллллллллллл лллллллллллллллллллл Psychose'Player : DOCUMENTATION лллллллллллллллллллллл лллллллллллллллллллл ппппппппппппппппппппппппппппппп лллллллллллллллллллллл лллллллллллллллллллл Psychose'Player was лллллллллллллллллллллл лллллллллллллллллллл Coded by LCA of Psychose Inc. лллллллллллллллллллллл лллллллллллллллллллл V.1 лллллллллллллллллллллл лллллллллллллллллллл лллллллллллллллллллллл лллллллллллллллллллл (C)opyright 1993 by LCA of лллллллллллллллллллллл лллллллллллллллллллл Psychose Inc. лллллллллллллллллллллл лллллллллллллллллллл лллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл л л л л л 1) Introduction л л р/ Who's done it? л л р/ What for? л л р/ Can you use it? л л л л 2) How to use it? л л р/ What can it do? л л р/ What can't it do? л л р/ The Object-File : "PLAYER.OBJ" л л л л 3) Do you want to contact "Psychose Inc."? л л р/ Use your MINITEL if you're French л л р/ Write to me л л л л 4) Conclusion л л л л л ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл 1) Introduction ппппппппппппппп р/ Who's done it? ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ I (LCA of "Psychose Inc.") coded this Object-File. It was of course programmed in assembler. р/ What for? ЭЭЭЭЭЭЭЭЭЭЭЭ This Object-File can play Amiga-Modules (.MOD files) on your Sound-Blaster (Pro) card. It can also play 6 or 8 channels Modules. Those Modules should be made, by example, on Fast-Tracker (Hei!! Mr.H/Triton, please insert in your coming version of Fast-Tracker a "Sample" option!!). This Player requires 32bMM from Psychose Inc., because the module is played in XMS-Memory. Therefore, you've got lots of free conventional memory!! Of course this player requires a 80386 or above processor. р/ Can you use it? ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ This Object-File is FreeWare : you can use it IF AND ONLY IF : * The program using Psychose'Player is not a commercial program (shareware is considered as commercial software). * You mention in your program that you used "Psychose'Player". * Psychose'Player is not modified in any way and stay in its original form. You can (sorry, YOU MUST!!!!) copy the Psychose'Player package. I just hope it won't be used by little coders also called lamers............ Moreover, SEND me your programs using Psychose'Player, I would be pleased to try them!!! лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл 2) How to use it? ппппппппппппппппп р/ What can it do? ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ * It detects if a Sound-Blaster/Sound-Blaster Pro card is installed. It also detects the I/O Port and the IRQ. But the DMA channel must be 1. * If a Sound-Blaster Pro card was detected, then the modules will be played in Stereo. * The modules are converted into a Fast-Format in memory. * If an XMS-Driver was detected by 32bMM, then this Fast-Format module will be located in XMS-Memory. * It uses the Flat-Real Mode * It can load old-15-Instr. modules * It can play 4 or 6 or 8 channels modules It detects the number of voices with the "M.K." bytes: in 6/8 channels Modules, those bytes are changed by the tracker in "6..." or "...6" (for a 6 channels module) where "..." can be anything. * Using DMA for a faster Replay-Routine * 4 playing-modes which 3 are very useful!! - 50 Hz Mode (useless mode!!) : You must call a procedure at least 50 times per second. - "Auto-Mode" (useful mode!!) : You've got NOTHING to do. - "Calling-Mode No1" (useful mode!!) : You set the frequence (=f) at which you'll call a Procedure (f>50 Hz). With this mode, you can make some nice effects on screen such as rasters, without a problem because interrupts are disabled. - "Calling-Mode No2" (useful mode!!) : It is exactly the same mode as the one above EXCEPT that now interrupts are enabled and the quality is much better!! Don't worry, I'll soon explain you how to use those modes... р/ What can't it do? ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ * Arg!! It doesn't support all Effects, only the most important. It supports: - 0xy : Normal Play/Arpeggio - 1xx : Slide Up - 2xx : Slide Down - Axy : Volume Slide - Bxx : Position Jump - Cxx : Set Volume - Dxx : Break Pattern - Fxx : Set Tempo As soon as I can, I'll code other effects... * It can't detect the DMA channel. р/ The Object-File "PLAYER.OBJ" ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ To use Psychose'Player in your programs, you just have to do two things: * Insert the line: INCLUDE PLAYER.INC INCLUDE 32bMM .INC in your source-text. * LINK your Objects-Files with "PLAYER.OBJ" and "32bMM.OBJ". Note : The Psychose'Player Procedures or Variables are in a FAR-Segment, but the Class of this segment is 'CODE' so that you won't have problems to set the memory size needed by your program, as you'll soon see in the example-file. Ok, here you'll learn how to call the Psychose'Player Procedures with their parameters and so on..... (See the Example-File for a concrete use) 1) VARIABLES * Num_Voices (Byte) Here you'll have the number of channels there are in the current Module. * Max_Volume (Byte) This is the higher Volume with which an instrument can be played. You can make a fade Up/Down with this variable. * Pattern_Index (Byte) This is the number corresponding to the pattern being played. With this variable, you can synchronize your program with the music. * Beat_Index (Byte) This is the line in current pattern. With this variable, you can synchronize your program with the music. * Voice_Info (Structure) For each channel, there are in this structure the needed informations concerning the sound to play. This structure is useful for you for one reason: the byte "VmVolume". Indeed, this is the Volume of the Channel. You can do whatever you want with this byte. At every new note, the Volume is put in this byte. Here is the way to make a Vue-Meter: Vue_Meter: mov ax,Seg Num_Voices mov fs,ax mov cl,fs:Num_Voices ; number of voices mov esi,fs:PTR_Voice_Info ; 32 bits pointer (see below) Label_0: mov al,[gs:esi].VmVolume ; keep vue-meter value dec [gs:esi].VmVolume ; self-decrementing volume call Draw_VueMeter ; whatever you want!! add esi,Size Struc_Voice_Info dec cl jne Label_0 Here is the total structure, but lots of bytes are USELESS for you!! Struc_Voice_Info STRUC Off_InstrInfo dd ? OffsetDigit dd ? Instrument db ? InstrVolume db ? VmVolume db ? InstrFineTune db ? Arp_Counter db ? QueDalle db ? Rate dw ? Corrector dd ? CorrectorVal dd ? EffectCommand dw ? SauveRate dw ? Struc_Voice_Info ENDS * PTR_Voice_Info This is a 32 bits pointer of Voice_Info. This is useful in Flat-Real mode. See the example above... 2) PROCEDURES * InitPlayer -Parameters: CALL : AX = Playing-Rate (Maximum is 22000 Hz) RETURN : Nothing -Action: You must call this procedure at the beginning of your program. It detects if a Sound-Blaster (Pro) card is installed, its I/O Port and its IRQ. It also saves the Interrupt Controler (8259) status. * EndPlayer -Parameters: Nothing -Action: You must call this procedure at the end of your program. It restores the 8259 status. * InfoSoundBlaster -Parameters: CALL : Nothing RETURN : AL=Sound-Card (see the constants below) AH=IRQ number DX=I/O Port -Action: It returns the sound-config. In AL, there can be one of the following values: No_SB = 0 : Sound-Blaster not detected SB_Mono = 1 : Sound-Blaster detected SB_Stereo = 2 : Sound-Blaster Pro detected * LoadModule -Parameters: CALL : DS:DX : Offset of an ASCIIZ String corresponding to the name of the module to load (and of course to play!!) RETURN : Carry=0 : Ok : No error Carry=1 : Arg!! ERROR!!!! -Action: This procedure loads a file and convert it into a new Fast-Format in XMS-Memory (if it can!!). If there is an error when loading, or if there is not enough free memory, then Carry=1. * EraseModule -Parameters: Nothing -Action: It erases the Module from the memory. You MUST call it before calling End-Player, or if you want to load another module: Example: call Init32bMM ; Init Flat-Real Mode mov ax,18000 ; 18Khz call InitPlayer lea dx,NameModule_1 call LoadModule call EraseModule lea dx,NameModule_2 call LoadModule call EraseModule call EndPlayer call End32bMM * ConvertModule -Parameters: CALL : GS:ESI = 32 bits offset of the module in memory CX=Size in Kilo-Byte of the .MOD File. RETURN : Carry=0 : Ok carry=1 : ERROR!! (Not Enough Memory!!) -Action: It converts the loaded Module (.MOD file) into the Fast-Format and it tries to put this new Format in XMS-Memory. Usualy, you don't need to call this procedure except if you've got your own file-loader. * StartPlaying -Parameters: CALL : AL=Playing-Mode If AL=Mode_2 or Mode_3, then BX=Calling Rate RETURN : Nothing -Action: Well I think it's not too difficult to understand what it does!! You put in AL the Playing-Mode. The correct values are: Mode_0 = 0 Mode_1 = 1 Mode_2 = 2 Mode_3 = 3 I shall now explain you what those Playing-Modes are: ** Mode_0 : In this mode, you MUST call a procedure at least 50 times a second. This Procedure is HandleMusic0 (see below). This Mode is totaly USELESS!!! But why did I let it?? Well I let it because it emulates the Amiga Players (they are called 50 times a second). And, as you'll learn soon, the Mode 1 uses HandleMusic0, so I let this Procedure PUBLIC... Don't worry, it doesn't take a simple byte more in memory!! ** Mode_1 : This is the easier mode : you haven't got anything to do!!! Example: call Init32bMM mov ax,18000 call InitPlayer lea dx,Name_Module call LoadModule mov al,Mode_1 call StartPlaying .... ; your program .... .... call StopPlaying call EraseModule call EndPlayer call End32bMM How does it work? In this mode, as soon as the DMA-Buffer is totaly sent to the Sound- Blaster's DAC, the Sound-Blaster informs it to the CPU, with its IRQ channel. Then the IRQ handler fills a new DMA-buffer (it uses, of course, a double- buffering technik). That way, the IRQ-handler is called 50 times a second. Here is its algorithmus: begin Send new DMA-Buffer to the DAC Call HandleMusic0 to prepare a buffer end ** Mode_2 : This is the calling mode. I think you'll understand how it works threw an example: Example: call Init32bMM mov ax,18000 call InitPlayer lea dx,Name_Module call LoadModule mov al,Mode_2 mov bx,70 ; calling rate : 70 times a second ; at regular steps call StartPlaying Loop_0: call Wait_VBL call HandleMusic2 ; Call HandleMusic2 at each VBL ; that means, 70 times a second ; in 320*200 graphic mode. in al,60h cmp al,01h ; ESC? jne Loop_0 call StopPlaying call EraseModule call EndPlayer call End32bMM Is it Ok?? If you are in 320*240 graphic mode, then BX=60...... Well maybe, you'll have little problems in stereo. This is VERY easy to understand why, and therefore, to solve them!! Before, I WANT to tell you THIS IS NOT A BUG!!!!!!!!! If the sound goes right and left and right and... Why? This is because of the DMA-buffer length calculation with the Sound- Blaster's DAC-Processor. With this bad length, a DMA-Session takes more than a period (in the upper example, a DMA session may take more than 1/70ј second). And you call HandleMusic2 at every period <=> you cut a DMA-Session to put a new one, and in Stereo, the DAC doesn't like it!! The error calculation depends on the Playing-Rate (18000Hz in the example) but it doesn't depend on the Calling-Rate (70Hz). Have you already found the solution?? No?? Well, just put a higher Calling-Rate, so that the period will be smaller. Example: If a Calling-Rate of 70Hz "bugs", then : ... ... mov al,Mode_2 mov bx,71 ; a higher calling-rate call StartPlaying ... ... And don't worry, the music won't sound bad!! REMEMBER IT: NEVER call HandleMusic2 when the current DMA-Session isn't finished!! ** Mode_3 : The concept of this mode is inspired from both mode_0 and mode_2. With StartPlaying, you put in AL the number 3 and in BX the frequency at which you will call the Calling_Procedure (=HandleMusic3)in a second. For instance, in you set a frequency of 65, then you MUST call at least HandleMusic3 65 times in a second. You can call it with irregular steps if you want... What is the difference between Mode_2 & Mode_3?? hehe!! the difference is in the DMA-management: in Mode_2, the DMA is programmed at which call, but in Mode_3, the DMA is programmed by an interrupt controller that is called by the Hardware (SB-IRQ). The second difference is that the Mode_3 fills a VERY VERY VERY... VERY big buffer (0.5 second!!), therefore, the quality of the tune is higher. You can call HandleMusic3 at irregular steps if you want, provided that you call this procedure BX times a second at least!! You should call HandleMusic3 more times than set with StartPlaying (=BX), so as to prevent from missing a Buffer-Filling. For example, if you want to call it 70 times a second, you should put in BX the value 68. (You've got 2 chances to miss the synchro!!). * StopPlaying -Parameters: Nothing -Action: Guess!! * MusicMode -Parameters: CALL : AL=Playing-Mode If AL=Mode_2 then BX=Calling-Rate RETURN : Nothing -Action : It changes (while a music is played) the current Playing- mode. Analyse the following example to use this Procedure in the good way: call Init32bMM mov ax,18000 call InitPlayer lea dx,Name_Module call LoadModule mov al,Mode_1 call StartPlaying ; you are now in Mode_1 mov cx,70*5 ; wait 5 seconds: Loop_0: call WaitVBL loop Loop_0 mov al,Mode_2 mov bx,71 call MusicMode ; You are now in Mode_2 hlt ; Wait for the end of the DMA-session ; You can know when it finishes, ; because at the end of each one ; there is an interrupt. mov cx,70*5 Loop_1: call WaitVBL ; You may hear a little "TIC" call HandleMusic2 loop Loop1 mov al,Mode_1 call MusicMode ; You are now in Mode_1 mov ax,Seg Max_Volume mov fs,ax Loop_2: call WaitVBL ; Fade down call WaitVBL dec fs:Max_Volume jne Loop_2 call StopPlaying call EraseModule call EndPlayer call End32bMM * HandleMusic0 * HandleMusic2 -CALL : Nothing -Action : It fills a DMA-Buffer... See the procedures above for more informations................. лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл 3) Do you want to contact "Psychose Inc."? пппппппппппппппппппппппппппппппппппппппппп If your deepest dream is to get in touch with us (hahaha!!!???), then р/ If you are French, use your lovely MINITEL: ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ * 3615 RTEL BAL : LCA (Coder of Psychose Inc.) BAL : NAPALM (......................) BAL : HACKER CROLL (......................) р/ If you wanna contact me, then write to: ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ BERMOND Cedric (LCA) 12, Rue Paul RONIN 42100 Saint-Etienne FRANCE But, you must know that I may not answer to every letters since I am not rich and I've got lots of homework with my study. Therefore can you put in your letter a self-addressing envelope??? лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл 3) Conclusion ппппппппппппп I hope you'll enjoy this Object-File. Well I haven't got anything else to tell you, so Have a good programming (ASM ONLY!!!!!!), LCA of Psychose Inc.