Я пишу в старом DOS, выпущенном в 1994 году, для забавы по программированию игр, и выводю данные из файла RAD в чип OPL3 FM Synthesis. Я убегаю из DOSBox.
В попытке повысить производительность при работе с аппаратными регистрами (особенно с учетом того, что я обновляю чип FM Synth с помощью прерывания по времени (чтобы сохранить темп) и хочу вернуться к основному коду как можно быстрее), я подумал переписать мой регистр выведен в сборку.
Однако, хотя это работает, кажется, что на выходе синтезаторного чипа появляются искажения, которых нет, когда я использую outportb чистого C, и я решил попросить здесь посмотреть, может ли кто-нибудь сказать мне, что происходит. Есть ли какая-то конкретная, тонкая разница между «out dx, al» и «outp (int, char)», которые я пропускаю?
OPLStatus status = NONE;
unsigned int primAd;
unsigned int secAd;
unsigned int backAd;
void OPLWriteImpl(void *argument, unsigned int registerNumber, unsigned char registerValue) {
(void)argument; /* Unused variable */
if(status == OPL3 || status == DUALOPL2) {
if(registerNumber <= REGISTER_THRESHOLD) {
outp(primAd, registerNumber);
outp(primAd+1, registerValue);
}
else {
outp(secAd, registerNumber);
outp(secAd+1, registerValue);
}
}
else {
outp(backAd, registerNumber);
outp(backAd+1, registerValue);
}
}
EXTRN status:WORD, primAd:WORD, backAd:WORD
.CODE
PUBLIC OPLWriteImpl
OPLWriteImpl PROC FAR C argument:DWORD, regnum:WORD, regval:BYTE
cmp status,0 ; if status == 0, go to OPL3
je three
cmp status,2 ; if status == DUAL, also go to OPL3
jne two ; otherwise, go to OPL2
three:
mov dx,primAd ; put OPL3 primary bank in dx
cmp regnum,100h ; check if regnum <=than threshold (256)
jle prim ; if so, go straight to primary bank
inc dx ; otherwise, writing to secondary bank (primary+2)
inc dx
prim:
mov ax,regnum ; put the register number in ax
out dx,ax ; output to register
inc dx ; go to data address
mov al,regval ; put the value in al
out dx,al ; output to data
jmp done ; finished
two:
mov dx,backAd
mov ax,regnum
out dx,ax
mov cx,6
loopOne:
in al,dx
loop loopOne
inc dx
mov al,regval
out dx,al
dec dx
mov cx,36
loopTwo:
in al,dx
loop loopTwo
done:
ret ; return to C
OPLWriteImpl ENDP
При использовании моей подпрограммы C музыка выводится правильно, как это было в RAD Tracker. Но когда я использую свою процедуру сборки, у некоторых инструментов появляется странный шероховатый звук. Я не могу винить эмуляцию Dosbox, потому что, как я уже сказал, она отлично работает с чистым C. Разница не супер вопиющая, но она более чем заметна. Мое единственное предположение, что реализация outportb творит магию, которой нет в моей рутине.