Giter Site home page Giter Site logo

Comments (10)

akarnokd avatar akarnokd commented on August 23, 2024 1

It's complicated. Here is the Ghidra Project I've been using. Open INTRO.EXE as it is only meant to play game videos, and surprisingly, can play XMF music along provided it is named URES.XMF.

I've noticed these modules are very quiet.

Not that quiet, volume is probably between 0x00 and 0x40. I added the global volume straight (not scaled).
MAIN1.ZIP

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024 1

Effects testing module with all of the working effects, plus the original MOD and a recording of DOSBox's audio with the Gravis UltraSound driver: xmftest.zip

All of my other effects and sample findings, and the custom MOD to XMF converter I wrote for testing: https://gist.github.com/AliceLR/deeb651c7629c8ee4b8a079f62304827

Given that the official XMFs only use effects Axy, Cxx, EAx, EBx, Fxx, 10xy, and that 10xy is directly compatible with Ultra Tracker Bxy (or can be dropped if you don't want panning), converting to ULT will probably work.

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024

A couple of things:

  • To the best of my knowledge, the ULT format does not support the Set Global Volume effect.
  • libmodplug fundamentally can not properly support ULT or ULT-like formats because it does not have two full effects channels. libxmp and libopenmpt can, but that doesn't help with VLC.
  • ULT also has some really weird behaviors, especially regarding finetune, and I don't recommend using it as an intermediate format for anything.

Which game format are you trying to convert?

from libmodplug.

akarnokd avatar akarnokd commented on August 23, 2024

Imperium Galactica 1 (1996) XMF.

The conversion to ULT does work 99%. I know it doesn't support set global volume; I'm trying to emulate it.

So the question still remains: how do I do it? How do other formats, which support 0x10 calculate the actual note volume?

Edit:

Looking through libxmp, I found these:

https://github.com/libxmp/libxmp/blob/master/src/player.c#L309-L310

https://github.com/libxmp/libxmp/blob/master/src/player.c#L989-L991

So either

  • volume_actual = volume_global * volume_current * other_factors >> 24
  • volume_actual = volume_global * volume_current >> 12

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024

After doing a bit of reverse engineering, it seems that every instance of effect 10h is only used with a parameter in the range from 0-f. Given this and what looks like a channel default panning table that starts at offset 1103h: this is probably not global volume, but rather Gravis UltraSound-style 4-bit panning.

This is pure speculation: the author's previous game Reunion uses MODs, so if this format was based on ULT, Tamas Kreiner may not have liked that Ultra Tracker uses the Bxx effect for panning, so he moved it to 10xx instead. That said, it doesn't seem like any of these modules use Bxx at all.

Since Ultra Tracker uses 4-bit panning, you should just be able to directly convert effect 10xx to Bxx if it really is panning.

from libmodplug.

akarnokd avatar akarnokd commented on August 23, 2024

Since Ultra Tracker uses 4-bit panning, you should just be able to directly convert effect 10xx to Bxx if it really is panning.

I tried that already. It resulted in an output where each track had its distinct pan position throughout the music, which was completely different how the same music sounds ingame - centered mono.

Reverse engineering the music code, it looked like when 10 is executed, the issues Gravis volume slide commands relative to the current and global volume.

Ghidra Decompiled Code
                             CX = xmf_sample_count + byte_5ac7
                             BP = channel index
                             For each channels
                             LAB_1010_31d7                                   XREF[1]:     1010:3251 (j)   
       1010:31d7 8b  f5           MOV        SI,BP
       1010:31d9 d1  ee           SHR        SI,0x1
       1010:31db 65  80  bc       CMP        byte ptr GS:[SI + smp_global_volume ],0xff
                 73  4f  ff
       1010:31e1 74  14           JZ         LAB_1010_31f7
       1010:31e3 65  8a  84       MOV        AL,byte ptr GS:[SI + smp_volume_curr ]
                 93  4f
       1010:31e8 65  2a  84       SUB        AL,byte ptr GS:[SI + smp_global_volume ]
                 73  4f
       1010:31ed 0a  c0           OR         AL,AL
       1010:31ef 79  02           JNS        LAB_1010_31f3
       1010:31f1 f6  d8           NEG        AL
                             LAB_1010_31f3                                   XREF[1]:     1010:31ef (j)   
       1010:31f3 3c  05           CMP        AL,0x5
       1010:31f5 72  56           JC         LAB_1010_324d
                             LAB_1010_31f7                                   XREF[1]:     1010:31e1 (j)   
       1010:31f7 c1  e6  02       SHL        SI,0x2
       1010:31fa 66  65  83       CMP        dword ptr GS:[SI + Smp_Play_Index ],-0x1
                 bc  33  4e  ff
       1010:3201 74  4a           JZ         LAB_1010_324d
       1010:3203 65  8b  16       MOV        DX,word ptr GS:[SB_Port ]                                    = 240h
                 ab  5a
       1010:3208 81  c2  02  01    ADD        DX,0x102
       1010:320c 8b  c5           MOV        AX,BP
       1010:320e d1  e8           SHR        AX,0x1
                             GUS Select Voice (BP >> 1)
                             Base + 0x102
       1010:3210 ee              OUT        DX,AL
       1010:3211 42              INC        DX
       1010:3212 b0  0d           MOV        AL,0xd
                             GUS Set Volume Control
                             Base + 0x103
       1010:3214 ee              OUT        DX,AL
       1010:3215 83  c2  02       ADD        DX,0x2
       1010:3218 b0  03           MOV        AL,0x3
                             Base + 0x105 <- 0x3 (Volume Stopped | Stop Volume)
       1010:321a ee              OUT        DX,AL
       1010:321b 83  ea  02       SUB        DX,0x2
       1010:321e b0  07           MOV        AL,0x7
                             Base + 0x103 <- Set Volume Start
       1010:3220 ee              OUT        DX,AL
       1010:3221 42              INC        DX
       1010:3222 65  a1  98  6b    MOV        AX,GS:[Volume_Start_W ]
                             Base + 0x104 <- Voice_Volume_Start Word
       1010:3226 ef              OUT        DX,AX
       1010:3227 4a              DEC        DX
       1010:3228 b0  08           MOV        AL,0x8
                             Gus Set Volume End
                             Base + 0x103 <- 0x08
       1010:322a ee              OUT        DX,AL
       1010:322b 42              INC        DX
       1010:322c 65  8b  86       MOV        AX,word ptr GS:[BP + Voice_Volume_End_W ]
                 47  54
       1010:3231 65  3b  06       CMP        AX,word ptr GS:[Volume_Table ]                               = A00h
                 96  6b
       1010:3236 74  15           JZ         LAB_1010_324d
       1010:3238 65  8b  1e       MOV        BX,word ptr GS:[Volume_Start_W ]
                 98  6b
       1010:323d 65  89  9e       MOV        word ptr GS:[BP + Voice_Volume_End_W ],BX
                 47  54
                             Base + 0x104 <- Voice_Volume_End
       1010:3242 ef              OUT        DX,AX
       1010:3243 4a              DEC        DX
       1010:3244 b0  0d           MOV        AL,0xd
                             Base + 0x103 <- Set Volume Control
       1010:3246 ee              OUT        DX,AL
       1010:3247 83  c2  02       ADD        DX,0x2
       1010:324a b0  40           MOV        AL,0x40
                             base + 0x105 <- 0x40 (Volume_Direct)
       1010:324c ee              OUT        DX,AL
                             LAB_1010_324d                                   XREF[3]:     1010:31f5 (j) , 1010:3201 (j) , 1010:3236 (j)   
       1010:324d 83  c5  02       ADD        BP,0x2
       1010:3250 49              DEC        CX
       1010:3251 75  84           JNZ        LAB_1010_31d7
       1010:3253 61              POPA
       1010:3254 0f  a9           POP        GS
       1010:3256 cf              IRET

So if it is for global volume, I'd have to try another mod format that accepts 10 natively. However, FastTracker's XM format looks too convoluted. What would be the closest format to ULT?

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024

I think the following would work for global volume, at least to experiment with. The following would have to be applied to every event with a note or with a volume or 10xx:

if Cxx is used: volume = [ cxx_param * global_volume ] / global_volume_max
else: volume = [ instrument_default_volume * global_volume ] / global_volume_max

Cxx and instrument default volume both look like they're 0-255, so the same formula ought to work...

Reverse engineering the music code, it looked like when 10 is executed, the issues Gravis volume slide commands relative to the current and global volume.

OK, I'll try to make sense of this in a little bit.

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024

This disassembly looks like GUS volume ramping. There are a few things that aren't clear currently:

  • Where is GUS voice register 0x6 (volume increment) being written? Is this what command 10 changes?
  • How is Volume_Start_W and the initial value of Voice_Volume_End_W[channel] set?
  • Where does smp_global_volume[channel] come from?

This command plausibly might be meant to trigger the volume ramps, or to at least control the rate at which they're performed for the current channel.

I'm working on basic support for this format for libxmp, and I've noticed these modules are very quiet. Is that normal?

from libmodplug.

akarnokd avatar akarnokd commented on August 23, 2024

Addendum to 0x10 and quietness: I'm 99% sure this is Set Global Volume command of FastTracker ][.

from libmodplug.

AliceLR avatar AliceLR commented on August 23, 2024

More effects info coming when I finish black box testing, but I figured out 10xx. It is Gravis UltraSound panning, and is not implemented for the Sound Blaster driver:

image

More typical MOD extended panning effects (8xx, E8x) do not work.

from libmodplug.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.