dbLounge
Tutorial zum Einbinden von DLL Funktionen in DBP/3DGC.
Autor: Kulle / Datum: 30.08.04
ReRelease dbLounge: 03.07.2005
Für wen ist das Tut geeignet?
Das Tut ist an alle gerichtet, die mit den Abkürzungen DLL und TPC etwas anfangen können. Hierzu sollte man auch mal einen Blick in die DBP Hilfe unter Third Party Commands geworfen haben. Auf der TGC Seite darkbasicpro.thegamecreators.com findet ihr auch Infos zu diesem Thema.
Warum eine "TPC Dummy Version" und keine direkte Einbindung?
Das Hinzufügen von Resourcen an DLLs kann dazu führen, dass die Datei nicht mehr richtig geladen und in DBP eingebunden werden kann doch genau das wollen wir mit dem Anfügen der String Tables erreichen. Hiermit versuche ich einen sicheren Weg zu beschreiben, der es möglich macht DLLs wie FMOD.DLL, BASS.DLL, UNRAR.DLL u.s.w. in DBP einzubinden.
Wie soll das gehen?
Im DLL Verzeichnis dieses Tuts befindet sich die FMOD.DLL mit einer Hilfe Datei. In dem Tut werde ich beschreiben wie man 4 Funktionen dieser DLL in DBP einbindet und das ohne großen Aufwand. Einen kleinen Nachteil möchte ich nicht verschweigen! Die Orginal-DLL muß trotz Einbindung in DBP mit eurem erstellten Programm mitgeliefert werden. Meist steht dies aber sowieso in den Lizenzbestimmungen des Herstellers.
Wann gehts denn endlich los mit dem Tut?
Genau jetzt!!!
Wie bekomme ich die richtigen Funktionsnamen aus der DLL heraus?
Hierzu müsst ihr einfach mal die Datei dumpdll.bat aufrufen und euch das erzeugte dumpdll.txt File im DLL Verzeichnis anschauen. Darin sind alle öffenlichen Funktionsnamen der DLL (in unserem Fall die der FMOD.DLL) aufgeführt. Natürlich geht das so auch mit anderen DLLs! Jetzt ist auch ein guter Zeitpunkt, um ein wenig in fmod.chm zu stöbern. Wer genau hinschaut wird auch feststellen, dass die Namen der Funktionen von denen in dem dumpdll.txt File minimal abweichen. Dies soll uns bei unserem Vorhaben aber nicht stören.
Wir suchen uns jetzt 4 Grundfunktionen der FMOD.DLL heraus um sie in DBP einzubinden:
Auszug aus der FMOD API Hilfe fmod.chm
FSOUND_Init
Initializes the FMOD Sound System.

signed char F_API FSOUND_Init(
  int mixrate,
  int maxsoftwarechannels,
  unsigned int flags
);

Parameters

mixrate: Output rate in hz between 4000 and 65535. Any thing outside this will cause the function to fail and return FALSE. PS2 Note. Only rates of 24000 and 48000 are supported. SmartPhone Note. Use 22050 or the operating system may crash outside of the control of fmod.

maxchannels: Maximum number of SOFTWARE channels available. The number of HARDWARE channels is autodetected. The total number of channels available (hardware and software) after initialization can be found with FSOUND_GetMaxChannels. Having a large number of maxchannels does not adversely affect cpu usage, but it means it has the POTENTIAL to mix a large number of channels, which can have an adverse effect on cpu usage. 1024 is the highest number that can be set. Anything higher will return an error.

flags: See FSOUND_INIT_FLAGS. Controls some global or initialization time aspects of playback.

Return Value
On success, TRUE is returned.
On failure, FALSE is returned.

Remarks
You do not have control over how many hardware channels are available to you. In a lot of cases it may be 0 (the sound card does not have the ability to supply hardware channels). This is why it is usually a good idea to supply FSOUND_Init with a good number of software channels to fall back onto, for example 32. Hardware channels are 3D hardware channels only. There is no benefit in supporting hardware for 2d playback of sound effects. With todays machines and FMOD's superior mixing routines, FMOD's software engine can sometimes be faster than the driver's hardware support!


FSOUND_Close
Shuts down the WHOLE FMOD Sound System.

void F_API FSOUND_Close(
);

Return Value
void

Remarks
This also closes down the sample management system, freeing all MANAGED samples loaded (unless they were allocated with the FSOUND_UNMANAGED flag). Streams are not freed. You must close them yourself. CD Tracks are stopped.

FMUSIC_LoadSong
To load a module or bank with a given filename. FMUSIC Supports loading of 
- .MOD (protracker/fasttracker modules)
- .S3M (screamtracker 3 modules)
- .XM (fasttracker 2 modules)
- .IT (impulse tracker modules)
- .MID (MIDI files)
- .RMI (MIDI files)
- .SGT (DirectMusic segment files)
- .FSB (FMOD Sample Bank files)

FMUSIC_MODULE * F_API FMUSIC_LoadSong(
  const char *name
);

Parameters

name: Filename of module to load.

Return Value
On success, a pointer to a FMUSIC_MODULE handle is returned. On failure, NULL is returned.

Remarks
This function autodetects the format type, regardless of filename. The MIDI loader does not support user file callbacks. For WAD type data structures with embedded MIDI files FMUSIC_LoadSongEx will have to be used with memory loading. Various other functionality is not provided in MIDI. See relevant FMUSIC functions to see if a feature is supported or not.

FMUSIC_PlaySong
Starts a song playing.

signed char F_API FMUSIC_PlaySong(
  FMUSIC_MODULE *mod
);

Parameters

mod: Pointer to the song to be played.

Return Value
TRUE song succeeded playing
FALSE song failed playing

(Auszug aus der Function Dump dumpdll.txt )
Dump of file .\dll\fmod.dll

File Type: DLL

  Section contains the following exports for fmod.dll

           0 characteristics
    40E2318D time date stamp Wed Jun 30 05:20:45 2004
        0.00 version
           1 ordinal base
         230 number of functions
         230 number of names

    ordinal hint RVA      name

	.....
         25   18 0001FD7A _FMUSIC_LoadSong@4
	.....
         28   1B 0002004E _FMUSIC_PlaySong@4
	.....
         68   43 00021EE8 _FSOUND_Close@0
	.....
       130   81 000218AE _FSOUND_Init@12
	.....

Summary

        3000 .rsrc
       6B000 UPX0
       25000 UPX1
Was mache ich jetzt mit den ganzen Infos?
Anhand der herausgesuchten Funktionsnamen, sollte es jedem schon klar sein, dass wir mit Hilfe dieser Funktionen ein Song Modul (kurz MOD File) mit 4 neu eingebundenen Befehlen in DBP abspielen wollen. DBP braucht dazu die Angaben in den Resourcen der DLL als Sring Table in einem vorgeschrieben Format. Wie oben schon geschrieben solltet ihr hierzu in die DBP Hilfe schauen und die Infos auf der TGC Seite lesen. Wer dies noch nicht gemacht hat, sollte sich jetzt Zeit dafür nehmen.
Hier mal ein String Table Beispiel eines Befehls ohne Rückgabewert:

Open FMOD%LLL% _FSOUND_Init@12
Der String ist in 3 Teile gesplittet, die durch den Separator "%" unterteilt werden.

Open FMOD

Dies ist der Befehl in Reinform, so wie er später in DBP Verwendung finden soll.

LLL

Das sind die 3 Übergabewerte, die der DLL Function in FMOD übergeben werden. Dies ist in der Hilfe für die FMOD API beschrieben. Wobei jedes "L" für einen DWORD bzw. INTEGER Wert steht.
 L = Integer                              ( IN use "INT" )        ( OUT use "INT" )
 F = Float                                ( IN use "FLOAT" )      ( OUT use "DWORD" )
 S = String                               ( IN use "LPSTR" )      ( OUT use "DWORD" )
 O = Double Float (capital o)             ( IN use "DOUBLE" )     ( OUT use "DOUBLE" ) 
 R = Double Integer (capital r)           ( IN use "LONGLONG" )   ( OUT use "LONGLONG" ) 
 D = Boolean, BYTE, WORD and DWORD        ( IN use "DWORD" )      ( OUT use "DWORD" )
 0 = Zero Character (no param)            ( IN use "VOID" )       ( N/A )

 _FSOUND_Init@12
Ist der Name der Funktion, so wie sie in der DLL hinterlegt ist.

Hier mal ein String Table Beispiel eines Befehls mit Rückgabewert:

Load Song[%LS%_FMUSIC_LoadSong@4

Hier sind wieder unsere 3 Teile mit dem Unterschied, dass zwischen dem Befehlsteil und dem Seperator ein "[" steht. Die offene eckige Klammer bedeutet nur, dass die Function einen Wert zurückliefert. Der Rückgabewert ist in diesem Fall das "L" im 2. Teil des Strings. Das "S" steht wiederum nur für einen Übergabewert.

Als Übung könnt ihr jetzt noch die 2 anderen Strings für die Tabelle bilden!
Wie kommen die Strings in unsere DLL?
Als erstes rufen wir die mitgelieferten pe module explorer.exe auf und öffnen die dummy.dll damit.

Den Resourcen Tree könnt Ihr mit anklicken weiter öffnen, bis er so aussieht wie auf der nächsten Abbildung. Ich habe mir erlaubt eine 1. leere String Table Gruppe schon zu erstellen. Die Einträge für die 4 neuen Befehle müsst ihr jetzt noch selbst vornehmen. Die ID 0 muss hierbei frei gelassen werden. Durch Doppelklicken auf das Feld ID 1 könnt Ihr den ersten String eintragen und das so weiter machen bis alle Strings eigetragen sind. Die Strings nochmal genau prüfen, man kann schnell mal ein Leerzeichen zuviel dabei haben. Nun einfach das ganze noch sichern und das war's!

Noch eine kurze Erklärung zu den String Table Gruppen. Eine String Table Gruppe beinhaltet immer 16 ID Einträge. Ihr könnt natürlich noch mehr Gruppen hinzufügen mit dem Icon neben dem Speicher Symbol oder über die Resourcen Menü Leiste. Die IDs werden automatisch weiter nummeriert. Nur ID 0 muß frei bleiben den Rest könnt selbst auch mit freien ID für die Übersichtlichkeit belegen.
Jetzt wird es bestimmt richtig schwer oder?
Nö! Das war's eigentlich schon, was den schwierigen Teil betrifft.Die dummy.dll muss jetzt noch in euren plugins-user-Ordner kopiert werden. Umbenennen von dummy.dll in fmod.dll auf keinen fall vergessen. Jetzt wechseln wir noch in das SOURCE Verzeichnis und rufen dort den Beispiel-Source dbpfmod.dbpro auf. Mit F5 durch den Compiler jagen ...

Was hab ich Euch denn am Anfang des Tuts gesagt? Also schnell in das DLL Verzeichnis wechseln und dort die fmod.dll rüber in das SOURCE Verzeichnis kopieren. Jetzt drücken wir nochmal die F5 Taste! Wer jetzt ein schönes Musikstück hört hat alles richtig gemacht.