News:

Herr Otto Partz says you're all nothing but pipsqueaks!

Main Menu

MT15.DRV reverse engineering project

Started by llm, June 04, 2021, 12:02:52 PM

Previous topic - Next topic

llm

my MT15.DRV reverse engineering project goes very well - when i find free time to work on it :)

DONE:

  • fully disassembled Stunts 1 and 1.1 MT15.DRV with script based building and binary comparison to original drivers - producing 100% identical drv files
  • build flags to keep the drvs binary compatible or to allow remove of dead code/data etc.
  • C/asm stubs, my base for the C port - does mimic the original drv layout for beeing loadable - also builded with scripts

i've found some functions that are not in use (dead code) in both drv versions, and init data that is also not used
its very relevant for the C port to test these "cleaned-up" versions if there is anything strange happen (both work on my side so far)

attached are the re-assembled versions without the dead code/data stuff
anyone interested in testing?

NEXT:

  • more analyse of the parameter/data-segment dependencies in the functions, use constants for Port/IO/MPU401 port accesses, more documentation
  • combine the two driver versions into one asm source - with a flag to switch between versions - but still 100% identical drv files in the end - for history preserving reasons :)
  • port that old dirty asm over to C - at this point only function identical - binary equality is hard to reach using a C compiler
  • understand the known bug in the 1.1 version
  • port the other drivers also this way

im using Dosbox Staging for testing - the lastest development version integrates the MT32 stuff so its easier to get it going
download the alpha here if you got a github account: https://dosbox-staging.github.io/downloads/devel/ (clicks windows link and the the bottom dosbox-staging-windows-x64-v0.77.0-alpha-856-g2e93f file)

your dosbox staging config should then contain

[midi]
mididevice=mt32

[mt32]
romdir=rom-dir #  use the mame roms
model=mt32_old # for original stunts release version of MT32
#model=cm32l_102 # or the new one

llm

#1
interestingly i find many small dead code parts in the MT15.DRV - sometimes parts of functions or complete functions that are not in use in the newer or not used in both versions - does not speak for the review quality of that time :)

for example a counter in one of the primary sub-functions - responsible to transfer data bytes to the MPU401
- the complete cx  register based/using code is just not used - a jump skips that part completely

it seemd first had a max try count of 65535 and then then the code for the try-count was disabled - leaving you waiting forever if the hardware does not
return the wanted feedback

someone able to confirm that?


this is the hex-code for the complete function from stunts 1 driver (the 1.1 driver is identical)

51 52 50 BA 31 03 B9 FF FF EC A8 40 74 13 D0 C0 73 1A EB EF 49 83 F9 01 7D EF 58
B8 FF FF EB 09 90 BA 30 03 58 EE B8 00 00 5A 59 C3 56 2E 8B 36 72 01 BA 30 03 EC
2E 88 84 4A 01 46 83 FE 28 75 02 33 F6 2E 89 36 72 01 5E EB B8


disassembled in shell-storm online, or ndisasm from nasm or IDA/Gidra with code starting at offset 0

http://shell-storm.org/online/Online-Assembler-and-Disassembler/?opcodes=51+52+50+BA+31+03+B9+FF+FF+EC+A8+40+74+13+D0+C0+73+1A+EB+EF+49+83+F9+01+7D+EF+58+B8+FF+FF+EB+09+90+BA+30+03+58+EE+B8+00+00+5A+59+C3+56+2E+8B+36+72+01+BA+30+03+EC+2E+88+84+4A+01+46+83+FE+28+75+02+33+F6+2E+89+36+72+01+5E+EB+B8&arch=x86-16&endianness=little&dis_with_addr=True&dis_with_raw=True&dis_with_ins=True#disassembly]http://shell-storm.org/online/Online-Assembler-and-Disassembler/?opcodes=51+52+50+BA+31+03+B9+FF+FF+EC+A8+40+74+13+D0+C0+73+1A+EB+EF+49+83+F9+01+7D+EF+58+B8+FF+FF+EB+09+90+BA+30+03+58+EE+B8+00+00+5A+59+C3+56+2E+8B+36+72+01+BA+30+03+EC+2E+88+84+4A+01+46+83+FE+28+75+02+33+F6+2E+89+36+72+01+5E+EB+B8&arch=x86-16&endianness=little&dis_with_addr=True&dis_with_raw=True&dis_with_ins=True#disassembly]http://shell-storm.org/online/Online-Assembler-and-Disassembler/?opcodes=51+52+50+BA+31+03+B9+FF+FF+EC+A8+40+74+13+D0+C0+73+1A+EB+EF+49+83+F9+01+7D+EF+58+B8+FF+FF+EB+09+90+BA+30+03+58+EE+B8+00+00+5A+59+C3+56+2E+8B+36+72+01+BA+30+03+EC+2E+88+84+4A+01+46+83+FE+28+75+02+33+F6+2E+89+36+72+01+5E+EB+B8&arch=x86-16&endianness=little&dis_with_addr=True&dis_with_raw=True&dis_with_ins=True#disassembly)

disassembler gives following result:


0x0000000000000000:  51                push cx
0x0000000000000001:  52                push dx
0x0000000000000002:  50                push ax
0x0000000000000003:  BA 31 03          mov  dx, 0x331
0x0000000000000006:  B9 FF FF          mov  cx, 0xffff
0x0000000000000009:  EC                in   al, dx
0x000000000000000a:  A8 40             test al, 0x40
0x000000000000000c:  74 13             je   0x21
0x000000000000000e:  D0 C0             rol  al, 1
0x0000000000000010:  73 1A             jae  0x2c
0x0000000000000012:  EB EF             jmp  3
0x0000000000000014:  49                dec  cx
0x0000000000000015:  83 F9 01          cmp  cx, 1
0x0000000000000018:  7D EF             jge  9
0x000000000000001a:  58                pop  ax
0x000000000000001b:  B8 FF FF          mov  ax, 0xffff
0x000000000000001e:  EB 09             jmp  0x29
0x0000000000000020:  90                nop 
0x0000000000000021:  BA 30 03          mov  dx, 0x330
0x0000000000000024:  58                pop  ax
0x0000000000000025:  EE                out  dx, al
0x0000000000000026:  B8 00 00          mov  ax, 0
0x0000000000000029:  5A                pop  dx
0x000000000000002a:  59                pop  cx
0x000000000000002b:  C3                ret 
0x000000000000002c:  56                push si
0x000000000000002d:  2E 8B 36 72 01    mov  si, word ptr cs:[0x172]
0x0000000000000032:  BA 30 03          mov  dx, 0x330
0x0000000000000035:  EC                in   al, dx
0x0000000000000036:  2E 88 84 4A 01    mov  byte ptr cs:[si + 0x14a], al
0x000000000000003b:  46                inc  si
0x000000000000003c:  83 FE 28          cmp  si, 0x28
0x000000000000003f:  75 02             jne  0x43
0x0000000000000041:  33 F6             xor  si, si
0x0000000000000043:  2E 89 36 72 01    mov  word ptr cs:[0x172], si
0x0000000000000048:  5E                pop  si
0x0000000000000049:  EB B8             jmp  3


my IDA Pro makes it more beautiful :)

; __int16 __usercall isub2<ax>(__int8 mpu_command_@<al>)
isub2 proc near
push cx
push dx
push ax

isub2_0:
mov dx, 331h
mov cx, 0FFFFh ; <==== NOT IN USE DUE TO DEAD CODE

isub2_1:
in al, dx

test al, 40h
jz short isub2_2

    rol al, 1
jnb short isub2_4
   
jmp short isub2_0

; <==== THIS IS DEAD CODE (due to the jump before)

dec cx
cmp cx, 1
jge short isub2_1
   
pop ax
mov ax, 0FFFFh
jmp short isub2_3

nop
<===== UNTIL HERE

isub2_2:
mov dx, 330h
pop ax
out dx, al
mov ax, 0

isub2_3: ; <=== UNUSED LABLE DUE TO DEAD CODE
pop dx
pop cx
retn
; ---------------------------------------------------------------------------

isub2_4:
push si
mov si, cs:word_172
mov dx, 330h
in al, dx
mov cs:byte_14A[si], al
inc si
cmp si, lengthof byte_14A
jnz short isub2_5
xor si, si

isub2_5:
mov cs:word_172, si
pop si
jmp short isub2_0
isub2 endp


Gihdra just ignores the dead code parts and shows only question marks for the bytes

that is the C port of that code - dead-code already removed


#define MPU_401_BASE 0x330
#define MPU_401_DATA (MPU_401_BASE+0)
#define MPU_401_STATUS_AND_COMMAND (MPU_401_BASE+1) // write => COMMAND-Port, read => STATUS-Port

#define MPU_401_OUTPUT_READY 0x40 // bit 6
#define MPU_401_INPUT_AVAIL 0x80 // bit 7

static uint16_t word_172;
static uint8_t byte_14A[40];

static inline uint16_t isub2(const uint8_t mpu_command_)
{
  for(;;)
  {
    const uint8_t val = inb(MPU_401_STATUS_AND_COMMAND);
   
    // is command send allowed?
    if( ( val & MPU_401_OUTPUT_READY ) == 0 )
    {
      break;
    }   
   
    // still data waiting?
    if( ( val & MPU_401_INPUT_AVAIL ) == 0 )
    {
      byte_14A[word_172++] = inb(MPU_401_DATA);
      if( word_172 == sizeof(byte_14A))
      {
        word_172 = 0;
      }
    }   
  }
 
  outb( MPU_401_DATA, mpu_command_ );
  return 0;
}

Duplode

Quote from: llm on June 04, 2021, 12:02:52 PM
anyone interested in testing?

I have done some quick testing with the reassembled drivers in the first post with 1991 Stunts, and didn't notice any difference so far. In particular, the 1.1 driver remains obviously buggy, and with the 1.0 driver the issue of missing sound effects after loading a replay from the pause menu also remains. Later I will replace the driver in my main Stunts setup when I start racing in Z239, and will also do some tests with 1990 4D.

llm

#3
thanks for testing, i think there will be some releases but better small changes then bigger that makes it hard to understand what of my changes introducing new bugs

Quote from: Duplode on June 06, 2021, 04:46:37 PM
In particular, the 1.1 driver remains obviously buggy, and with the 1.0 driver the issue of missing sound effects after loading a replay from the pause menu also remains.

so there are two bugs? never heard of the replay sound bug
is there a list of bugs in the MT15 driver and versions?

hope that the much simpler C code will let us do a bugfree version of the driver

Duplode

#4
Quote from: llm on June 06, 2021, 04:58:16 PM
so there are two bugs? never heard of the replay sound bug
is there a list of bugs in the MT15 driver and versions?

I should note that one is not specifically a MT15 bug; in my experience, it happens with all drivers. (That is unlike, say, the 1990 4D issue I had mentioned in the other thread, an that I'll try to reproduce later.)

llm

your link does not work, post action inlined in url, but i know the post

does that also happen to dosbox staging or a real MT32?

Duplode

Link fixed, thanks.

Quote from: llm on June 06, 2021, 06:42:59 PM
does that also happen to dosbox staging or a real MT32?

I have seen those issues on vanilla DosBox + munt, dosbox-staging + munt and, as you suggested, standalone dosbox-staging. No idea about a real MT32, unfortunately.

llm

#7
We should ask on vogons if there is someone who can test the know bugs on a real DOS/MT32? also recording would be great

llm

another finding:

stunts 1.1 + 1.1 DRV sends sometimes wrong MT32 sysex messages for some "Patch Temporary Area" and "BENDER RANGE" value


F0 41 10 16 12 03 00          F7  <-- Incomplete message
F0 41 10 16 12 03 00 04 18 61 F7  Patch Temporary Area (part 1), BENDER RANGE =  24
F0 41 10 16 12 03 00 14 00 69 F7  Patch Temporary Area (part 2), BENDER RANGE =   0
F0 41 10 16 12 03 00 24 00 59 F7  Patch Temporary Area (part 3), BENDER RANGE =   0
F0 41 10 16 12 03 00 34 00 49 F7  Patch Temporary Area (part 4), BENDER RANGE =   0
F0 41 10 16 12 03 00 44 00 39 F7  Patch Temporary Area (part 5), BENDER RANGE =   0
F0 41 10 16 12 03 00 44 02 37 F7  Patch Temporary Area (part 5), BENDER RANGE =   2
F0 41 10 16 12 03 00 54 00 29 F7  Patch Temporary Area (part 6), BENDER RANGE =   0
F0 41 10 16 12 03 00 54(70)39 F7  Patch Temporary Area (part 6), BENDER RANGE = 112 <-- This is not a valid setting
F0 41 10 16 12 03 00 64 00 19 F7  Patch Temporary Area (part 7), BENDER RANGE =   0
F0 41 10 16 12 03 00 74 02 07 F7  Patch Temporary Area (part 8), BENDER RANGE =   2


the first message gets ignored by the MT32 due to checksum error and the invalid value 112 for the bender-range gets clamped to 24 by the MT32

stunts 1.1 + 1.0 DRV does not contain the code to send these sysex messages

llm

#9
these are sysex midi messages from a listen-to-some-music-gameplay - while tracing messages :)


Patch Temp Area/Bender range
F0 41 10 16 12 03 00 04 18 61 F7
F0 41 10 16 12 03 00 14 00 69 F7
F0 41 10 16 12 03 00 14 18 51 F7
F0 41 10 16 12 03 00 24 00 59 F7
F0 41 10 16 12 03 00 34 00 49 F7
F0 41 10 16 12 03 00 44 00 39 F7
F0 41 10 16 12 03 00 44 02 37 F7
F0 41 10 16 12 03 00 54 02 27 F7
F0 41 10 16 12 03 00 54 70 39 F7 # <-- 0x00-0x18 is allowed range, 0x70 gets clamped to 0x18 [Patch Temporary Area (part 6), BENDER RANGE = 112]
F0 41 10 16 12 03 00 74 02 07 F7
F0 41 10 16 12 03 00 F7 # <-- illformed, wrong checksum

Patch Memory, full, from MT32.PLB
F0 41 10 16 12 05 00 00 02 00 18 32 18 00 00 00 17 F7
F0 41 10 16 12 05 00 08 02 01 18 32 0C 00 01 00 19 F7
F0 41 10 16 12 05 00 10 02 02 18 32 0C 00 01 00 10 F7
F0 41 10 16 12 05 00 18 02 03 18 32 0C 00 01 00 07 F7
F0 41 10 16 12 05 00 20 02 04 18 32 0C 00 01 00 7E F7

Timbre Memory, full, from MT32.PLB
F0 41 10 16 12 08 00 00 45 6E 67 69 6E 65 20 31 20 20 07 05 0F 00 17 15 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 17 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 18 32 0B 01 01 35 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 00 00 0B 01 01 2B 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 53 F7
F0 41 10 16 12 08 02 00 53 71 75 65 65 6C 20 20 20 20 00 08 0F 00 24 19 0B 01 00 25 64 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 24 56 0B 01 00 25 58 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 13 0B 0B 01 01 35 25 07 00 00 00 00 00 00 00 00 4E 4E 4E 00 32 64 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 02 00 00 00 64 63 00 64 07 5E 0B 01 00 35 64 07 00 00 00 00 00 00 00 00 50 50 51 00 21 64 00 1C 1E 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 3C F7
F0 41 10 16 12 08 04 00 44 61 6D 61 67 65 20 20 20 20 05 05 0F 00 15 00 0F 00 00 12 42 00 04 00 00 14 1E 00 00 00 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 0E 00 46 00 0A 00 61 00 00 09 00 0F 00 00 13 41 00 04 00 00 14 14 00 00 64 50 00 00 00 0A 1E 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 13 11 3B 37 00 00 63 2D 04 12 00 0F 00 00 18 41 04 08 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 00 41 1D 0E 00 5E 17 03 14 00 0F 00 00 53 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 32 33 50 0C 53 64 2D 00 44 F7
F0 41 10 16 12 08 06 00 4D 65 74 61 6C 43 6C 61 6E 6B 08 09 03 00 05 00 0F 00 00 45 41 00 03 00 00 14 1E 00 00 31 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 3F 3D 00 0A 62 00 00 00 0D 00 0F 00 01 58 41 00 04 00 00 3D 00 00 00 31 2F 00 00 00 18 0D 05 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 0C 04 2A 64 00 00 00 24 00 0F 00 00 18 41 04 05 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 40 06 17 1D 64 00 00 00 36 00 0F 00 00 53 41 00 02 00 00 0A 0A 00 00 64 50 32 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 00 26 2C 64 00 00 00 04 F7
F0 41 10 16 12 08 08 00 45 6E 67 69 6E 65 20 31 20 20 02 02 0F 00 24 32 0B 01 00 53 64 0E 00 00 00 37 2D 2D 23 0A 32 46 46 14 13 64 10 22 00 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0D 32 40 0C 00 0C 00 00 05 00 00 00 13 64 64 64 64 18 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 16 32 0B 01 01 58 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0E 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 0C 36 0B 01 00 00 32 07 02 00 00 37 28 32 23 32 32 37 40 14 0D 10 10 38 12 0B 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 23 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 29 F7

System Area/Master volume (these messages just set volume between 0-100)
F0 41 10 16 12 10 00 16 00 5A F7
F0 41 10 16 12 10 00 16 02 58 F7
F0 41 10 16 12 10 00 16 04 56 F7
F0 41 10 16 12 10 00 16 06 54 F7
F0 41 10 16 12 10 00 16 08 52 F7
F0 41 10 16 12 10 00 16 0A 50 F7
F0 41 10 16 12 10 00 16 0C 4E F7
F0 41 10 16 12 10 00 16 0E 4C F7
F0 41 10 16 12 10 00 16 10 4A F7
F0 41 10 16 12 10 00 16 12 48 F7
F0 41 10 16 12 10 00 16 14 46 F7
F0 41 10 16 12 10 00 16 16 44 F7
F0 41 10 16 12 10 00 16 18 42 F7
F0 41 10 16 12 10 00 16 1A 40 F7
F0 41 10 16 12 10 00 16 1C 3E F7
F0 41 10 16 12 10 00 16 1E 3C F7
F0 41 10 16 12 10 00 16 20 3A F7
F0 41 10 16 12 10 00 16 22 38 F7
F0 41 10 16 12 10 00 16 24 36 F7
F0 41 10 16 12 10 00 16 26 34 F7
F0 41 10 16 12 10 00 16 28 32 F7
F0 41 10 16 12 10 00 16 2A 30 F7
F0 41 10 16 12 10 00 16 2C 2E F7
F0 41 10 16 12 10 00 16 2E 2C F7
F0 41 10 16 12 10 00 16 30 2A F7
F0 41 10 16 12 10 00 16 32 28 F7
F0 41 10 16 12 10 00 16 34 26 F7
F0 41 10 16 12 10 00 16 36 24 F7
F0 41 10 16 12 10 00 16 38 22 F7
F0 41 10 16 12 10 00 16 3A 20 F7
F0 41 10 16 12 10 00 16 3C 1E F7
F0 41 10 16 12 10 00 16 3E 1C F7
F0 41 10 16 12 10 00 16 40 1A F7
F0 41 10 16 12 10 00 16 42 18 F7
F0 41 10 16 12 10 00 16 44 16 F7
F0 41 10 16 12 10 00 16 46 14 F7
F0 41 10 16 12 10 00 16 48 12 F7
F0 41 10 16 12 10 00 16 4A 10 F7
F0 41 10 16 12 10 00 16 4C 0E F7
F0 41 10 16 12 10 00 16 4E 0C F7
F0 41 10 16 12 10 00 16 50 0A F7
F0 41 10 16 12 10 00 16 52 08 F7
F0 41 10 16 12 10 00 16 54 06 F7
F0 41 10 16 12 10 00 16 56 04 F7
F0 41 10 16 12 10 00 16 58 02 F7
F0 41 10 16 12 10 00 16 5A 00 F7
F0 41 10 16 12 10 00 16 5C 7E F7
F0 41 10 16 12 10 00 16 5E 7C F7
F0 41 10 16 12 10 00 16 60 7A F7
F0 41 10 16 12 10 00 16 62 78 F7
F0 41 10 16 12 10 00 16 64 76 F7

LCD text
F0 41 10 16 12 20 00 00 20 20 28 43 29 31 39 39 30 2C 31 39 39 31 20 44 53 49 20 20 79 F7


and the "Timbre Memory" and "Patch Memory" bytes directly comming from the MT32.PLB - seems to be sound effects for the engine, crash etc.


Sysex messages

F0 41 10 16 12 08 00 00   45 6E 67 69 6E 65 20 31 20 20 07 05 0F 00 17 15 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 17 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 18 32 0B 01 01 35 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 00 00 0B 01 01 2B 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64   53 F7
F0 41 10 16 12 08 02 00   53 71 75 65 65 6C 20 20 20 20 00 08 0F 00 24 19 0B 01 00 25 64 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 24 56 0B 01 00 25 58 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 13 0B 0B 01 01 35 25 07 00 00 00 00 00 00 00 00 4E 4E 4E 00 32 64 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 02 00 00 00 64 63 00 64 07 5E 0B 01 00 35 64 07 00 00 00 00 00 00 00 00 50 50 51 00 21 64 00 1C 1E 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63   3C F7
F0 41 10 16 12 08 04 00   44 61 6D 61 67 65 20 20 20 20 05 05 0F 00 15 00 0F 00 00 12 42 00 04 00 00 14 1E 00 00 00 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 0E 00 46 00 0A 00 61 00 00 09 00 0F 00 00 13 41 00 04 00 00 14 14 00 00 64 50 00 00 00 0A 1E 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 13 11 3B 37 00 00 63 2D 04 12 00 0F 00 00 18 41 04 08 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 00 41 1D 0E 00 5E 17 03 14 00 0F 00 00 53 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 32 33 50 0C 53 64 2D 00   44 F7
F0 41 10 16 12 08 06 00   4D 65 74 61 6C 43 6C 61 6E 6B 08 09 03 00 05 00 0F 00 00 45 41 00 03 00 00 14 1E 00 00 31 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 3F 3D 00 0A 62 00 00 00 0D 00 0F 00 01 58 41 00 04 00 00 3D 00 00 00 31 2F 00 00 00 18 0D 05 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 0C 04 2A 64 00 00 00 24 00 0F 00 00 18 41 04 05 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 40 06 17 1D 64 00 00 00 36 00 0F 00 00 53 41 00 02 00 00 0A 0A 00 00 64 50 32 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 00 26 2C 64 00 00 00   04 F7
F0 41 10 16 12 08 08 00   45 6E 67 69 6E 65 20 31 20 20 02 02 0F 00 24 32 0B 01 00 53 64 0E 00 00 00 37 2D 2D 23 0A 32 46 46 14 13 64 10 22 00 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0D 32 40 0C 00 0C 00 00 05 00 00 00 13 64 64 64 64 18 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 16 32 0B 01 01 58 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0E 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 0C 36 0B 01 00 00 32 07 02 00 00 37 28 32 23 32 32 37 40 14 0D 10 10 38 12 0B 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 23 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64   29 F7

MT32.PLB content

05 -> 5 sounds
02 00 18 32 18 00 00 00   45 6E 67 69 6E 65 20 31 20 20 07 05 0F 00 17 15 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 17 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 18 32 0B 01 01 35 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 00 00 0B 01 01 2B 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64  ...2....Engine 1  ..........5....7(2#.2FF....#..i.7....*.d2ddddd2[..........dddd.L....5....7(2#.2FF....#..i.7....*.d2ddddd2[..........dddd.2...5%....7--#.2FF....9..i.7....*,d2ddddd2[..........ddcd.....+5....7(2#.2FF....#..i.7....*.d2ddddd2[..........dddd
02 01 18 32 0C 00 01 00   53 71 75 65 65 6C 20 20 20 20 00 08 0F 00 24 19 0B 01 00 25 64 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 24 56 0B 01 00 25 58 07 00 00 00 00 06 00 00 00 64 64 64 00 48 64 00 03 1E 09 69 07 64 00 00 00 00 00 00 00 00 64 64 64 64 32 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63 13 0B 0B 01 01 35 25 07 00 00 00 00 00 00 00 00 4E 4E 4E 00 32 64 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 02 00 00 00 64 63 00 64 07 5E 0B 01 00 35 64 07 00 00 00 00 00 00 00 00 50 50 51 00 21 64 00 1C 1E 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 46 64 5B 0C 1B 0C 00 00 05 00 00 00 00 64 63 00 63  ...2....Squeel    ....$....%d.........ddd.Hd....i.d........dddd2d[..........dc.c$V...%X.........ddd.Hd....i.d........dddd2d[..........dc.c.....5%.........NNN.2d.9..i.7....*,d2ddddFd[..........dc.d.^...5d.........PPQ.!d....i.7....*,d2ddddFd[..........dc.c
02 02 18 32 0C 00 01 00   44 61 6D 61 67 65 20 20 20 20 05 05 0F 00 15 00 0F 00 00 12 42 00 04 00 00 14 1E 00 00 00 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 0E 00 46 00 0A 00 61 00 00 09 00 0F 00 00 13 41 00 04 00 00 14 14 00 00 64 50 00 00 00 0A 1E 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 13 11 3B 37 00 00 63 2D 04 12 00 0F 00 00 18 41 04 08 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 00 41 1D 0E 00 5E 17 03 14 00 0F 00 00 53 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 32 33 50 0C 53 64 2D 00  ...2....Damage    ..........B..........(.....d.................dL........F...a........A........dP......d.................dL........;7..c-.......A....L...4.......d.................dL........A...^.......SA................d.................dL.......23P.Sd-.
02 03 18 32 0C 00 01 00   4D 65 74 61 6C 43 6C 61 6E 6B 08 09 03 00 05 00 0F 00 00 45 41 00 03 00 00 14 1E 00 00 31 14 28 00 00 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 3F 3D 00 0A 62 00 00 00 0D 00 0F 00 01 58 41 00 04 00 00 3D 00 00 00 31 2F 00 00 00 18 0D 05 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 0C 04 2A 64 00 00 00 24 00 0F 00 00 18 41 04 05 00 00 4C 17 13 0A 34 00 00 00 11 05 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 40 06 17 1D 64 00 00 00 36 00 0F 00 00 53 41 00 02 00 00 0A 0A 00 00 64 50 32 00 00 00 00 00 64 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 4C 00 00 00 00 00 00 00 39 00 26 2C 64 00 00 00  ...2....MetalClank.........EA........1.(.....d.................dL.......?=..b........XA....=...1/......d.................dL.......9..*d...$.....A....L...4.......d.................dL.......@...d...6....SA........dP2.....d.................dL.......9.&,d...
02 04 18 32 0C 00 01 00   45 6E 67 69 6E 65 20 31 20 20 02 02 0F 00 24 32 0B 01 00 53 64 0E 00 00 00 37 2D 2D 23 0A 32 46 46 14 13 64 10 22 00 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0D 32 40 0C 00 0C 00 00 05 00 00 00 13 64 64 64 64 18 4C 0B 01 01 00 35 07 00 00 00 37 28 32 23 0A 32 46 46 14 0D 10 10 23 14 09 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 64 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64 16 32 0B 01 01 58 25 07 00 00 00 37 2D 2D 23 0A 32 46 46 14 0C 00 10 39 14 09 69 07 37 00 00 00 00 2A 2C 64 32 64 64 64 64 0E 32 5B 0C 1B 0C 00 00 05 00 00 00 1D 64 64 63 64 0C 36 0B 01 00 00 32 07 02 00 00 37 28 32 23 32 32 37 40 14 0D 10 10 38 12 0B 69 07 37 00 00 00 00 2A 2E 64 32 64 64 64 64 23 32 5B 0C 1B 0C 00 00 05 00 00 00 19 64 64 64 64  ...2....Engine 1  ....$2...Sd....7--#.2FF..d."..i.7....*,d2dddd.2@..........dddd.L....5....7(2#.2FF....#..i.7....*.d2ddddd2[..........dddd.2...X%....7--#.2FF....9..i.7....*,d2dddd.2[..........ddcd.6....2....7(2#227@....8..i.7....*.d2dddd#2[..........dddd


llm

#10
so i think im fully aware of the System exclusive (sysex) message that are used/generated by Stunts - now i need to look at the ordinary midi messages

and then back to porting

llm

anyone got a nice c/cpp example for playing midi under dosbox, all the old samples i've tried do just nothing :/

Cas

Somewhere... but it will take me quite some time to find... I had code I downloaded once for DOS that could play CMF files. These files contain MIDI, only they use OPL2 FM instruments, but the procedure is pretty much the same. I have a "driver" that came with the SBPro/SB16 called SBFMDRV.COM, that assisted in playing those files too. That one is easy to provide, but reading it would mean disassembling. It's not long, though. But the code I mentioned did this without using SBFMDRV. It was in QuickBasic. Easy to read. If you're interested, I can look it up in the mess I have.
Earth is my country. Science is my religion.

llm

A simple c/cpp code would be best, qbasic would be problematic under pure dosbox without the interpreter, i just want some reference for midi playing

llm

better documented and combined assembler code (https://pastebin.ubuntu.com/p/6MHxkS8tbf/) of the Stunts 1.0 and 1.1 MT15.DRV - ready to reassembled - same binary as original but with fresher bits :)
next step is the C Port

1. Download the 7z
2. Install the needed tools (Win64 currently) - its easy, see: \tools\install_howto.txt - you need at least uasm, ulink and watcom (for later C source)
3. run \stunts_drvs\unified_MT15\build.cmd (and the resulting files are compared against the original drivers)
4. find 100% identical version 1.0 and 1.1 in DRV in _build\unified_MT15\10 or 11

should looks likes this on console output:

https://pasteboard.co/K6dGjHF.png

what the 7z contains:


\stunts_drvs\setup_env.cmd <-- helper to find the tools (not for direct use)

\stunts_drvs\unified_MT15\build.cmd <-- builds Version 1.0 and 1.1 of the MT15.DRV <- this is the one you want to run
\stunts_drvs\unified_MT15\build_helper.cmd  <-- build-helper (not for direct use)
\stunts_drvs\unified_MT15\MT15.asm <-- the combined 1.0 and 1.1 MT15.DRV source code

\stunts_drvs\unified_MT15\org\10\MT15.DRV <-- original 1.0 MT15.DRV - used for compare the result
\stunts_drvs\unified_MT15\org\11\MT15.DRV <-- original 1.1 MT15.DRV - used for compare the result

\tools\ <-- here do you need to copy the needed tools
\tools\install_howto.txt <-- what is needed to get the tools
\tools\result_tree.txt <-- how should the tree look like after installation