Reply 80 of 167, by superfury
sub_9A6 does indeed seem to be a procedure to set an Adlib register. AL contains the register number, AH contains the value that the register needs to be set to. All those IN instructions are simply delays to wait for the OPL2 chip to be ready(delays, like those documented by the chip documentation). Almost no registers are destroyed, except AL becoming the value in AH.
sub_89E loads 0x12 adlib registers specified at location DS:171 and onwards (starting at Adlib register 0x80+[DS:171], 0x80+[DS:172] and onwards) with the value 0xFF.
loc_1EB seems to be the startup routine. It check AX for the 'drive letter status' (according to http://stackoverflow.com/questions/3715618/ho … ram-into-memory ), stores AX at word_2C6 when not zeroed, otherwise leaves it at value 0xA21F. Then it calls sub_1C8 to process the extension in the program's filename, loads 0x20 into Adlib register 0x01, clears register 0xBD(Drumkit information register) and loads register 0x08 with value 0x40. Then it saves CS on the stack to provide a 32-bit return pointer for RETF instructions and calls sub_211. Upon return it sets BX to 0xF00 and executes a far return(to the address at SS:SP, first IP, then CS that's pushed on the stack).
sub_1C8 seems to search the string pointer(char *var=&referencedstring-2; in C/C++) at [BP+(n<<1)+2] for a '.' character within the first 9 characters. n being increased after each loop. When it finds a '.' character, it replaces the following 3 bytes with the values in word_2C3 and byte_2C5, probably replacing the extensions of files found into the end-of-string(NULL byte) to terminate the string and filling the remaining two extension bytes with 1E, 0E(Record seperator, Shift out ASCII characters), then continuing the loop.
- So it's processing the referenced filenames pointed by a table at [BP+(n<<1)+2], terminating each string with a dot in it after the dot, adding a Record seperator and Shift out ASCII character(according to http://www.asciitable.com/ ) to each string with a '.' within the first 9 characters, probably for some list processing routine.
Edit: Looking at it again, it's probably processing the application filename from the MS-DOS PSP segment, replacing the second and third bytes into the Record seperator and Shift out ASCII character as a seperate string. The filename itself is reduced to become everything up to and including the dot of the filename.
sub_211 saves the flags on the stack(to be restored later), disables interrupts, and calls sub_81F, clears AX and clears byte_19A, returning to the called procedure while restoring the flags stored previously.
sub_81F saves DS on the stack for restoration before returning, points DS to CS(probably for the subroutine to use DX as a pointer into CS, when needed), loads CX to process 9 items in a loop. Then it calls sub_98B with DX being 8 to 0 in a loop. Finally it returns to the calling function, restoring DS in the process.
sub_98B loads AX with the value at memory location DS:[(2*DX)+0x15F], then copies it into CX. AL is loaded with (the low 8-bits of DX provided by the caller function)+0xA0 to provide a register index, then SI is set to a copy of the calculated register/value to set and sub_9A6 is called to set the adlib register. Upon return AX is restored to the value read at the start of the function, 0x10 is added to the register that was written and AH is set to the register set in the call to sub_9A6. Then it passes-though(executes) sub_9A6 on the resulting register/value pair, updating the same register with 0x10 added to it's original value, before letting sub_9A6 return to the caller of sub_98B.
Looking at the combined information of sub_81F and sub_98B, this might be processing all 9 adlib channels and producing a note OFF, then immediately a note-on on said channel, thus triggering a note, with information about it at the word variable located at DS:[(2*DX)+0x15F].
Edit: Whoops, bit 3 in register A0+ is part of the frequency LSB. So it's toggling the frequency between the selected frequency and 0x10 higher instead? Why would it do that? First load frequency LSB n, then n+16(wrapping around 256)?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io