Hi Could anyone help me with this question? I can add "*.wav" file into "rsrc.rc" and play it in my "*.exe", ==================================================== Rsrc.rc 101 WAVE DISCARDABLE "somesound.wav" ====== SomeMASM.asm .code invoke PlaySound,101,NULL,SND_RESOURCE or SND_ASYNC ==================================================== , but this techinque does not work with "somemusic.mid" files. I guess I should use "mciSendCommand" but still I cannot play it from "rsrc.rc". Could anyone write some example what should be in the "rsrc.rc" and in "*.asm" files? Thank you in advance.
Hello Ol, I have a small demo that has the midi file included. It is actually not by me but by Test Department because I asked them how to do it. I slightly modified it. The code is commented, so you shouldn't have problems with it. The trick here is that we include the midi file as RCDATA, when the program runs we save the midi file as a temp file and then you can play it. Maybe there are other ways, but this works. Go and get it under http://win32asmnewbies.cjb.net Stefan
This is one way to do it. ;*.rc file STRINGTABLE DISCARDABLE BEGIN ;A full qualified path ;I can't get it to load right if it is: M:\ARCHIVES\SND_MID\Trouble.mid ;Maybe someone can help me with that. 4488 "M:?ARCHIVES?SND_MID?Trouble.mid" ;No path ;The Midi file must be placed in your *.rc directory. 4488 "Trouble.mid" END ;Your source program. include \MASM32V1\include\WINMM.inc includelib \MASM32V1\lib\WINMM.lib .data MIDI db 50 dup(' '),0 P db 'play ',0 S db 'close ',0 midiP1 db 50 dup(0),0 midiS1 db 50 dup(0),0 .code . . ;Load the string from the string table INVOKE LoadString, hInst, 4488, addr MIDI, lengthof MIDI ;If its a full qualified path you will need to do the following to ;replace the ? with a \. mov ecx, eax lea esi, MIDI mov edi, esi ; Dest = source strfix: lodsb ; Get byte in al .if al == '?' mov al, '\' ; Replace with \ .endif stosb ; store al loop strfix ; for length of string ;else ;Build the Play string. INVOKE lstrcpy, addr midiP1, addr P INVOKE lstrcat, addr midiP1, addr MIDI ;Build the Stop string. INVOKE lstrcpy, addr midiS1, addr S INVOKE lstrcat, addr midiS1, addr MIDI ;Play the Midi INVOKE mciSendString, addr midiP1, 0, 0, 0 ;Stop the Midi INVOKE mciSendString, addr midiS1, 0, 0, 0 Ewayne
Hello Stefan, Hello Ewayne, I think with your help I can solve the problem now. Thank You.
Hello again Ewayne, I think this will help you: === 4488 "M:\\ARCHIVES\\SND_MID\\Trouble.mid" === on my machine it works. Stefan, You gave me a wonderful example how to extract and save some data from resources and this is what I could not find for a long time, thanks a lot once again! But my problem with MIDI is solved partly. How should I avoid saving the MIDI on the disk? Why cannot it be played directly, like with WAVE files (there is no need to save "*.wav" on the disk to have it played)? For sure it can be played, (I saw some "*.exe" files) but how to code it. Does anybody have any idea? Regards, Ol
You don't have to save the Midi file back to disk with the example I showed you. The Midi file can be anywhere on your hard drives if you use the full path in the *.rc file. You could go one step further and use OpenFile to open any Midi file and play it. Ewayne
What I want to do is: to make an "exe" file with some MIDI included and do not extract the MIDI on the disk at all (even as a TEMP file) while playing it. This perfectly works with WAVE files, but with MIDI so far I can play them from disk only either from full path or from a TEMP file extracted from resources. In the other words the MIDI file must not be present on the disk in any ways but played directly from "exe".
Hello Ol, I don't think, that it is possible to play a MIDI file included as RCDATA directly, as the program doesn't know the format correctly to use it as a MIDI file. One way I could imagine of would be to create an custom resource data and then tell the program what kind of data this is. I didn't check that, but here is a samll essay derived from www.gamedev.net (actually in C/C++) I think that it can be translated into Win32ASM easily. GOOD LUCK Stefan Custom Resources The standard Windows resources are those which have special functions for loading and handling them, but they are not the only types you can use. Resources can be any data you want them to be! Working with custom resources requires a little more work since you must locate and read the resource data manually, but it's not too bad. The script file entry for a custom type follows the basic format you're already used to: The resource type name is a string that defines your custom resource, and can be whatever you want. For the purposes of this example, let's say you want to include a data file called p1config.dat that contains information necessary to initialize a character in a game program. We'll call the custom resource type CHARCONFIG. With that in mind, here's an example of what the script file entry might look like for your data file: DATA_PLAYERINIT CHARCONFIG p1config.dat Pretty simple, hey? Now that you've included your file, there are three steps you must take in order to retrieve a pointer to the resource data. Each involves calling a function we haven't talked about yet, so let's go through them one at a time. The first thing you must do is to find the resource with a call to FindResource(). Here's the prototype: HRSRC FindResource( HMODULE hModule, // module handle LPCTSTR lpName, // pointer to resource name LPCTSTR lpType // pointer to resource type ); The return value is a handle to the resource's information block, or NULL if the function fails. The parameters are as follows: HMODULE hModule: The HMODULE data type is simply an HINSTANCE. Don't ask me why they felt they needed another name for it, but you should simply pass the instance of your application. You don't even need a typecast because the data types are exactly the same. LPCTSTR lpName: This is the resource identifier. Remember to use MAKEINTRESOURCE() on this one if you're using numeric constants to define your resources. LPCTSTR lpType: This is the resource type, so pass the string you used to define your resource type. In our case, this is CHARCONFIG. A sample function call looks like this: HRSRC hRsrc = FindResource(hinstance, MAKEINTRESOURCE(DATA_PLAYERINIT), "CHARCONFIG"); This is a handle to the info block the resource resides in. The next step to getting a pointer to the data is to take this handle and pass it to LoadResource() to actually load the data. This yields a handle to the resource itself. Here is the function prototype: HGLOBAL LoadResource( HMODULE hModule, // resource-module handle HRSRC hResInfo // resource handle ); The return type, HGLOBAL, is a pretty general handle type, as opposed to the other load functions we've covered, which returned specific handle types like HBITMAP or HICON. If the function fails, this value will be NULL. The parameters are straightforward: HMODULE hModule: Again, simply the application instance. HRSRC hResInfo: Pass the handle that was returned by FindResource(). Now that you have a handle to the resource, you can finally get a pointer to the data that was in the resource file you included. This is achieved with a call to LockResource(), shown here: LPVOID LockResource(HGLOBAL hResData); Simply pass the handle that was returned by LoadResource(). If the return value is NULL, the function call failed. If not, you've got your pointer! Now you're free to do whatever you like with the data. Note that the return type is LPVOID (Windows-speak fo