VOGONS

Common searches


First post, by Stretch

User metadata
Rank Member
Rank
Member

Any ideas why this AutoIT script works properly with Dosbox and Doom2, but not Duke3d?

The script simulates keyboard presses, which I am using to record FM OPL to DRO files.

If I modify the script for Duke3d, ingame none of the keypresses register.

I tried Duke3d with Dos4/GW and Dos32a.

AutoIT script

#include <MsgBoxConstants.au3>

Global $dosboxPath = "C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe"
; doom2.conf runs a batch file called d2vgm.bat
Global $dosboxConfig = "C:\temp\doom2.conf"
; Length of each level in seconds
Global $audioTrackLength = "C:\temp\audioTrackLength.txt"

; Exit if required files not found
Global $fName
CheckDependency($dosboxPath)
CheckDependency($dosboxConfig)
CheckDependency($audioTrackLength)

; Run Dosbox
Run('"' & $dosboxPath & '"' & ' -conf ' & '"' & $dosboxConfig & '"')

; Wait 3 seconds for Dosbox to load
Global $hWnd = WinWait("[CLASS:Dosbox]", "", 3)
Sleep(3000)

; The main part of the script
ReadTextFile()

; Quit if required files are not found
; https://www.autoitscript.com/autoit3/docs/functions/FileExists.htm
Func CheckDependency($fName)
Local $iFileExists = FileExists($fName)
If Not $iFileExists Then
MsgBox($MB_SYSTEMMODAL, "", "The file " & $fName & " doesn't exist." & @CRLF & "FileExist returned: " & $iFileExists)
Exit 1
EndIf
EndFunc

; https://www.autoitscript.com/forum/topic/111408-read-text-file-line-by-line/
; Script from user MHz
Func ReadTextFile()
; open file to read and store the handle
$handle_read = FileOpen($audioTrackLength, 0)
; check the handle is valid
If $handle_read = -1 Then
; show warning and exit with code 1
MsgBox(0, @ScriptName, 'failed to open handle to read the file')
Exit 1
EndIf

; loop through each line of the file
While 1
; read each line from a file
$line_read = FileReadLine($handle_read)
; exit the loop if end of file
If @error Then ExitLoop

; Add 5 seconds
; And multiply by 1000 for Sleep function
If $line_read > 1 Then
Local $strTrackLength = Number(($line_read + 5) * 1000)
Else
ContinueLoop
EndIf
Show last 39 lines
		
; Activate the Dosbox window using the handle returned by WinWait.
WinActivate($hWnd)
Sleep(200)

; Begin VGM Recording
Send("^!{F7}")
Sleep(2000)
; Exit pause command in batch file
Send("ENTER")
; Wait for level to load
Sleep(8000)
; God mode idkfa
; change to dnkroz for duke3d
Send("idkfa")
; Sleep for the length of the track read from file
Sleep($strTrackLength)
; Exit Doom - Escape, Up, Enter, y
Send("{ESCAPE}")
Sleep(1000)
Send("{UP}")
Sleep(1000)
Send("{ENTER}")
Sleep(1000)
Send("y")
; Uncomment for Duke3d
; Sleep(2000);
; Send("{ENTER}")
; Wait for game to exit to command prompt
Sleep(4000)
; End VGM Recording
Send("^!{F7}")
Sleep(2000)
WEnd

; close the file handle for read
FileClose($handle_read)
EndFunc

d2vgm.bat

@echo off

REM For WAD games like Doom and Doom2
SET DMXOPTION=-opl3-phase

REM DOOM.exe -opl3 -phase -warp 1 1 -nomonsters -nosfx
REM DOOM2.EXE -opl3 -phase -warp 01 -nomonsters -nosfx
REM duke3d.exe /m /ns /v1 /l1

pause
DOOM2.EXE -opl3 -phase -warp 01 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 02 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 03 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 04 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 05 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 06 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 07 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 08 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 09 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 10 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 18 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 20 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 23 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 25 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 28 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 30 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 31 -nomonsters -nosfx
pause
DOOM2.EXE -opl3 -phase -warp 32 -nomonsters -nosfx
REM FreeDOS sleep
sleep.exe 5
exit

AudioTrackLength.txt doom2

230
292
230
155
259
417
257
300
279
263
306
279
99
115
282
279
72
79

d3dvgm.bat

@echo off

pause
duke3d.exe /m /ns /v1 /l1
pause
duke3d.exe /m /ns /v1 /l2
pause
duke3d.exe /m /ns /v1 /l3
pause
duke3d.exe /m /ns /v1 /l4
pause
duke3d.exe /m /ns /v1 /l5
pause
duke3d.exe /m /ns /v1 /l6
pause
duke3d.exe /m /ns /v1 /l7
pause
duke3d.exe /m /ns /v2 /l1
pause
duke3d.exe /m /ns /v2 /l2
pause
duke3d.exe /m /ns /v2 /l3
pause
duke3d.exe /m /ns /v2 /l4
pause
duke3d.exe /m /ns /v2 /l5
pause
duke3d.exe /m /ns /v2 /l6
pause
duke3d.exe /m /ns /v2 /l7
pause
duke3d.exe /m /ns /v2 /l8
pause
duke3d.exe /m /ns /v2 /l9
pause
duke3d.exe /m /ns /v2 /l10
pause
duke3d.exe /m /ns /v2 /l11
pause
duke3d.exe /m /ns /v3 /l1
pause
duke3d.exe /m /ns /v3 /l2
pause
duke3d.exe /m /ns /v3 /l3
pause
duke3d.exe /m /ns /v3 /l4
pause
duke3d.exe /m /ns /v3 /l5
pause
duke3d.exe /m /ns /v3 /l6
pause
duke3d.exe /m /ns /v3 /l7
pause
duke3d.exe /m /ns /v3 /l8
pause
duke3d.exe /m /ns /v3 /l9
pause
duke3d.exe /m /ns /v3 /l10
pause
duke3d.exe /m /ns /v3 /l11
Show last 25 lines
pause
duke3d.exe /m /ns /v4 /l1
pause
duke3d.exe /m /ns /v4 /l2
pause
duke3d.exe /m /ns /v4 /l3
pause
duke3d.exe /m /ns /v4 /l4
pause
duke3d.exe /m /ns /v4 /l5
pause
duke3d.exe /m /ns /v4 /l6
pause
duke3d.exe /m /ns /v4 /l7
pause
duke3d.exe /m /ns /v4 /l8
pause
duke3d.exe /m /ns /v4 /l9
pause
duke3d.exe /m /ns /v4 /l10
pause
duke3d.exe /m /ns /v4 /l11
sleep.exe 5
exit

audiotracklength.txt duke3d

164
242
359
353
353
376
103
201
315
232
146
185
311
195
147
184
153
165
246
254
334
394
289
158
401
379
161
251
220
179
190
130
217
185
212
213
193
281
200
172

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5

Reply 2 of 10, by Osprey

User metadata
Rank Member
Rank
Member

Are your DOSBox settings the same as for the other games and have you tried the game in windowed mode? I have experience using AutoHotkey with DOSBox and have found that it doesn't completely work with games in fullscreen unless the DOSBox output mode is set to opengl or openglnb. Try those (windowed mode and/or opengl) and see if they make any difference.

Speaking of AutoHotkey, converting your script to that is an option, though it's possible that you'd encounter the same problem.

Reply 3 of 10, by Stretch

User metadata
Rank Member
Rank
Member
Osprey wrote:

Are your DOSBox settings the same as for the other games and have you tried the game in windowed mode? I have experience using AutoHotkey with DOSBox and have found that it doesn't completely work with games in fullscreen unless the DOSBox output mode is set to opengl or openglnb. Try those (windowed mode and/or opengl) and see if they make any difference.

Speaking of AutoHotkey, converting your script to that is an option, though it's possible that you'd encounter the same problem.

Same settings and I also run dosbox windowed. I also tried openglnb but the key presses don't register.

I am on a mac dual booting OS X and WIndows 10. I also tried an Applescript in OS X, but got the same results where Doom works but Duke3d doesn't.

I am planning to try an Arduino USB to simulate key presses next.

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5

Reply 4 of 10, by Osprey

User metadata
Rank Member
Rank
Member

If you're not getting any inputs at all, perhaps something is going on with the window title. Instead of checking for DOSBox class, try checking for the string "DOSBox" and/or "DUKE". You'll probably want to use the SetWindowTitleMatchMode (I think that's the name) to 2 in order to check for those strings anywhere in the window title.

Reply 5 of 10, by NY00123

User metadata
Rank Member
Rank
Member

Also seen bruenor41's reply? Maybe you should add a delay between key presses and releases.

In some apps, when a key press is immediately followed by release (under a lil. bit above 0 seconds), the key press is essentially missed (at least in terms of certain behaviors).

Last edited by NY00123 on 2017-10-22, 22:01. Edited 1 time in total.

Reply 6 of 10, by Stretch

User metadata
Rank Member
Rank
Member

Thanks for the replies, I'm getting closer now to record the OPL music from Duke3d. For testing I used a batch file to load the first 3 levels and to record 30 seconds each. I was able to record the first 2 properly, but then the 3rd level didn't register the god mode code. Also sometimes, Duke3d will not load the level with an error message "couldn't find the selected sound card."

I'll try to tweak a bit more. Here's the code I placed near the top of the AutoIT file which increases the duration of a keypress.

; SendKeyDelay and SendKeyDownDelay
; https://www.autoitscript.com/autoit3/docs/functions/AutoItSetOption.htm#ExpandEnvStrings
Opt("SendKeyDownDelay", 100) ;100 milliseconds

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5

Reply 7 of 10, by Stretch

User metadata
Rank Member
Rank
Member

Switching Duke3d to Dos32a instead of Dos4/GW seems to have gotten rid of the random "Couldn't find selected sound card" error.

I will try this script tomorrow and report back if it worked.

AutoIT script

#include <MsgBoxConstants.au3>

; SendKeyDelay and SendKeyDownDelay
; https://www.autoitscript.com/autoit3/docs/functions/AutoItSetOption.htm#ExpandEnvStrings
Opt("SendKeyDownDelay", 100) ;100 milliseconds
Opt("SendKeyDelay", 10) ;10 milliseconds

Global $dosboxPath = "C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe"
; duke3d.conf runs a batch file called d3dvgm.bat
Global $dosboxConfig = "C:\temp\duke3d.conf"
; Length of each level in seconds retrieved from loading
; MIDI files in Foobar2000 with custom column seconds
Global $audioTrackLength = "C:\temp\audioTrackLength.txt"

; Exit if required files not found
Global $fName
CheckDependency($dosboxPath)
CheckDependency($dosboxConfig)
CheckDependency($audioTrackLength)

; Run Dosbox
Run('"' & $dosboxPath & '"' & ' -conf ' & '"' & $dosboxConfig & '"')

; Wait 3 seconds for Dosbox to load
Global $hWnd = WinWait("[CLASS:Dosbox]", "", 3)
Sleep(3000)

; The main part of the script
ReadTextFile()

; Quit if required files are not found
; https://www.autoitscript.com/autoit3/docs/functions/FileExists.htm
Func CheckDependency($fName)
Local $iFileExists = FileExists($fName)
If Not $iFileExists Then
MsgBox($MB_SYSTEMMODAL, "", "The file " & $fName & " doesn't exist." & @CRLF & "FileExist returned: " & $iFileExists)
Exit 1
EndIf
EndFunc

; https://www.autoitscript.com/forum/topic/111408-read-text-file-line-by-line/
; Script from user MHz
Func ReadTextFile()
; open file to read and store the handle
$handle_read = FileOpen($audioTrackLength, 0)
; check the handle is valid
If $handle_read = -1 Then
; show warning and exit with code 1
MsgBox(0, @ScriptName, 'failed to open handle to read the file')
Exit 1
EndIf

; loop through each line of the file
While 1
; read each line from a file
$line_read = FileReadLine($handle_read)
; exit the loop if end of file
If @error Then ExitLoop

; Add 5 seconds
Show last 43 lines
      ; And multiply by 1000 for Sleep function
If $line_read > 1 Then
Local $strTrackLength = Number(($line_read + 5) * 1000)
Else
ContinueLoop
EndIf

; Activate the Dosbox window using the handle returned by WinWait.
WinActivate($hWnd)
Sleep(200)

; Begin VGM Recording
Send("^!{F7}")
Sleep(2000)
; Exit pause command in batch file
Send("ENTER")
; Wait for level to load
Sleep(8000)
; God mode dnkroz
Send("dnkroz")
; Sleep for the length of the track read from file
Sleep($strTrackLength)
; Exit Duke3d - Escape, Up, Enter, y, Enter
Send("{ESCAPE}")
Sleep(1000)
Send("{UP}")
Sleep(1000)
Send("{ENTER}")
Sleep(1000)
Send("y")
Sleep(2000);
Send("{ENTER}")
; Wait for game to exit to command prompt
Sleep(4000)
; End VGM Recording
Send("^!{F7}")
Sleep(2000)
WEnd

; close the file handle for read
FileClose($handle_read)
EndFunc

d3dvgm.bat (runs in dosbox)

@echo off

pause
duke3d.exe /m /ns /v1 /l1
pause
duke3d.exe /m /ns /v1 /l2
pause
duke3d.exe /m /ns /v1 /l3
pause
duke3d.exe /m /ns /v1 /l4
pause
duke3d.exe /m /ns /v1 /l5
pause
duke3d.exe /m /ns /v1 /l6
pause
duke3d.exe /m /ns /v1 /l7
pause
duke3d.exe /m /ns /v2 /l1
pause
duke3d.exe /m /ns /v2 /l2
pause
duke3d.exe /m /ns /v2 /l3
pause
duke3d.exe /m /ns /v2 /l4
pause
duke3d.exe /m /ns /v2 /l5
pause
duke3d.exe /m /ns /v2 /l6
pause
duke3d.exe /m /ns /v2 /l7
pause
duke3d.exe /m /ns /v2 /l8
pause
duke3d.exe /m /ns /v2 /l9
pause
duke3d.exe /m /ns /v2 /l10
pause
duke3d.exe /m /ns /v2 /l11
pause
duke3d.exe /m /ns /v3 /l1
pause
duke3d.exe /m /ns /v3 /l2
pause
duke3d.exe /m /ns /v3 /l3
pause
duke3d.exe /m /ns /v3 /l4
pause
duke3d.exe /m /ns /v3 /l5
pause
duke3d.exe /m /ns /v3 /l6
pause
duke3d.exe /m /ns /v3 /l7
pause
duke3d.exe /m /ns /v3 /l8
pause
duke3d.exe /m /ns /v3 /l9
pause
duke3d.exe /m /ns /v3 /l10
pause
duke3d.exe /m /ns /v3 /l11
Show last 25 lines
pause
duke3d.exe /m /ns /v4 /l1
pause
duke3d.exe /m /ns /v4 /l2
pause
duke3d.exe /m /ns /v4 /l3
pause
duke3d.exe /m /ns /v4 /l4
pause
duke3d.exe /m /ns /v4 /l5
pause
duke3d.exe /m /ns /v4 /l6
pause
duke3d.exe /m /ns /v4 /l7
pause
duke3d.exe /m /ns /v4 /l8
pause
duke3d.exe /m /ns /v4 /l9
pause
duke3d.exe /m /ns /v4 /l10
pause
duke3d.exe /m /ns /v4 /l11
sleep.exe 10
exit

Length of audio track of each level

164
242
359
353
353
376
103
201
315
232
146
185
311
195
147
184
153
165
246
254
334
394
289
158
401
379
161
251
220
179
190
130
217
185
212
213
193
281
200
172

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5

Reply 8 of 10, by NY00123

User metadata
Rank Member
Rank
Member

Great to read that you've gotten further!

Stretch wrote:

Switching Duke3d to Dos32a instead of Dos4/GW seems to have gotten rid of the random "Couldn't find selected sound card" error.

Interesting to see that Dos32a resolves this. I have a guess that OPL chip detection (used for music) can fail on faster machines.

Reply 9 of 10, by Stretch

User metadata
Rank Member
Rank
Member

I still need to tweak the script because at some point in the logging process either the sound card error re-occurred or key presses weren't recorded, because not all songs were recorded.

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5

Reply 10 of 10, by Stretch

User metadata
Rank Member
Rank
Member

I ended up using an Arduino pro micro as a keyboard emu with a build of MAME that writes VGM, because of the random sound card error while loading a level in Dosbox.

Here is a sketch I created.

#include <Keyboard.h>

const int SendKeyDownDelay = 200; // key is held down for 200 ms
const int SendKeyDelay = 10; // 10 ms delay between key press

const int numAudioTracks = 40; // Number of audio tracks

// Time of each audio track in seconds
int arrAudioTrackTime[] = {
164, 242, 359, 353, 353, 376, 103, 201, 315, 232, 146, 185, 311, 195, 147, 184, 153, 165, 246, 254, 334, 394, 289, 158, 401, 379, 161, 251, 220, 179, 190, 130, 217, 185, 212, 213, 193, 281, 200, 172
};

int count = 0; // Loop counter

char godMode[]={'d', 'n', 'k', 'r', 'o', 'z'}; // God mode dnkroz
byte escapeSequence[]={KEY_ESC, KEY_UP_ARROW, KEY_RETURN, 0x79, KEY_RETURN}; // Quit game - Esc, Up, Enter, y, Enter

void setup()
{
delay(10000); // Wait 10 seconds before starting
Keyboard.begin(); // Start the keyboard emulator
}

void loop() {
while(count < numAudioTracks){
vgmkeypress();
count++;
}
if (count == numAudioTracks) {
count++;
Keyboard.press(71+136); // Exit MAME scroll lock and escape
delay(SendKeyDownDelay);
Keyboard.release(71+136);
delay(1000);
Keyboard.press(KEY_ESC);
delay(SendKeyDownDelay);
Keyboard.releaseAll();
Keyboard.end(); // End the keyboard emulator
}
delay(1000);
}

void vgmkeypress() {
unsigned long AudioTrackTime;
AudioTrackTime = long(arrAudioTrackTime[count]) * 1000;

Keyboard.press(KEY_RETURN); // Exit the pause command in batch file
delay(SendKeyDownDelay);
Keyboard.release(KEY_RETURN);
delay(40000); // Wait 40 seconds for game to load

for (int i = 0; i < 6; i++){ // God mode dnkroz
Keyboard.press(godMode[i]);
delay(SendKeyDownDelay);
Keyboard.release(godMode[i]);
delay(SendKeyDelay);
}

delay(AudioTrackTime); // Sleep for the length of the audio track

Show last 13 lines
  for (int i = 0; i < 5; i++){ // Quit game - Esc, Up, Enter, y, Enter
Keyboard.press(escapeSequence[i]);
delay(SendKeyDownDelay);
Keyboard.release(escapeSequence[i]);
if (i == 3) {
delay(2000);
} else {
delay(1000);
}
}
delay(2000);
}

Win 11 - Intel i7-1360p - 32 GB - Intel Iris Xe - Sound BlasterX G5