Code: Code (Text): ROM:198D ; =============== S U B R O U T I N E ======================================= ROM:198D ROM:198D ROM:198D sub_198D: ; CODE XREF: ROM:1061p ROM:198D ; sub_1343+17p ... ROM:198D ld h, 1 ; 100h ROM:198F ld a, b ; a = b - c ROM:1990 sub c ROM:1991 jr nc, loc_199E ; if a xxx 0 goto loc ROM:1993 neg ; a = -a ROM:1995 srl a ; a >>= 1 (a /= 2) ROM:1997 ld c, a ; c = a ROM:1998 add a, b ; a += b ROM:1999 ld l, a ; a = (100h)[a] ROM:199A ld a, (hl) ROM:199B ld l, c ; a -= (100h)[c] ROM:199C sub (hl) ; alternatively, swap b and c, then do the below ROM:199D ret ROM:199E ; --------------------------------------------------------------------------- ROM:199E ROM:199E loc_199E: ; CODE XREF: sub_198D+4j ROM:199E srl a ; a >>= 1 (a /= 2) ROM:19A0 ld b, a ; b = a ROM:19A1 add a, c ; a += c ROM:19A2 ld l, a ; a = (100h)[a] ROM:19A3 ld a, (hl) ROM:19A4 ld l, b ; a -= (100h)[b] ROM:19A5 sub (hl) ROM:19A6 ret ROM:19A6 ; End of function sub_198D Data at 100h: Code (Text): ROM:0100 db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ROM:0100 db 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 ROM:0100 db 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 0Ah, 0Ah ROM:0100 db 0Ah, 0Bh, 0Bh, 0Ch, 0Ch, 0Dh, 0Dh, 0Eh, 0Eh, 0Fh, 0Fh ROM:0100 db 10h, 10h, 11h, 11h, 12h, 12h, 13h, 13h, 14h, 14h, 15h ROM:0100 db 15h, 16h, 17h, 17h, 18h, 19h, 19h, 1Ah, 1Ah, 1Bh, 1Ch ROM:0100 db 1Ch, 1Dh, 1Eh, 1Eh, 1Fh, 20h, 21h, 21h, 22h, 23h, 24h ROM:0100 db 24h, 25h, 26h, 27h, 27h, 28h, 29h, 2Ah, 2Bh, 2Bh, 2Ch ROM:0100 db 2Dh, 2Eh, 2Fh, 30h, 31h, 31h, 32h, 33h, 34h, 35h, 36h ROM:0100 db 37h, 38h, 39h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h, 41h ROM:0100 db 42h, 43h, 44h, 45h, 46h, 47h, 48h, 49h, 4Ah, 4Bh, 4Ch ROM:0100 db 4Dh, 4Eh, 4Fh, 51h, 52h, 53h, 54h, 55h, 56h, 57h, 59h ROM:0100 db 5Ah, 5Bh, 5Ch, 5Dh, 5Fh, 60h, 61h, 62h, 64h, 65h, 66h ROM:0100 db 67h, 69h, 6Ah, 6Bh, 6Ch, 6Eh, 6Fh, 70h, 72h, 73h, 74h ROM:0100 db 76h, 77h, 79h, 7Ah, 7Bh, 7Dh, 7Eh, 7Fh, 81h, 82h, 84h ROM:0100 db 85h, 87h, 88h, 8Ah, 8Bh, 8Dh, 8Eh, 90h, 91h, 93h, 94h ROM:0100 db 96h, 97h, 99h, 9Ah, 9Ch, 9Dh, 9Fh, 0A0h, 0A2h, 0A4h ROM:0100 db 0A5h, 0A7h, 0A9h, 0AAh, 0ACh, 0ADh, 0AFh, 0B1h, 0B2h ROM:0100 db 0B4h, 0B6h, 0B7h, 0B9h, 0BBh, 0BDh, 0BEh, 0C0h, 0C2h ROM:0100 db 0C4h, 0C5h, 0C7h, 0C9h, 0CBh, 0CCh, 0CEh, 0D0h, 0D2h ROM:0100 db 0D4h, 0D5h, 0D7h, 0D9h, 0DBh, 0DDh, 0DFh, 0E1h, 0E2h ROM:0100 db 0E4h, 0E6h, 0E8h, 0EAh, 0ECh, 0EEh, 0F0h, 0F2h, 0F4h ROM:0100 db 0F6h, 0F8h, 0FAh, 0FCh, 0FEh The given function takes b and c as input and produces a as output. This is a sound driver, and at this point in the program I come across a structure like Code (Text): db command_byte db unknown_parameter dw jump_table_target_1 dw jump_table_target_2 dw jump_table_target_3 ... jump_table_target_1: db command_bytes... unknown_parameter is loaded into b and some other value is loaded into c; the result is the index into the jump table. I am trying to determine one of the following two things: 1) Is unknown_parameter the size of the jump table? Or in other words, is b the upper bound of a? 2) What does this function do? I have no idea... Thanks.
Something from a sound driver ... interesting. Let's begin with the table at 100h: It's a simple lookup table for 256 squared values between 0 and 1. You can recreate the table with this code: Code (Text): for (idx = 0x00; idx < 0x100; idx ++) { value = (idx / 256.0) * (idx / 256.0); LUT[idx] = floor(value * 256.0); } I'm not sure what prupose the actual function has, but it does this: Code (Text): float sub_198D(float param_b, float param_c) { val_low = abs(param_b - param_c) / 2; val_high = (param_b + param_c) / 2; return (val_high * val_high) - (val_low * val_low); } (float = register / 256.0 and vice versa.) If I would need to guess, I'd say it has something to do with modulation. (Just because squares don't make much sense anywhere except for frequencies.)
All right; trial and error on your float code shows me that yes b is the upper bound, which gives me the answer to 1)... except Ican't reproduce it with the original Z80 code, unless I transcribed the code wrong...? I'm also unsure what's going on here, since the c parameter doesn't seem to be set anywhere; there's another function elsewhere that divides it by 2 (it's a 16-bit value and the low byte is used as c here), so I'm assuming there's still a block of code I haven't come across (or it's set subtly).
You have indeed a tiny error in your code. Code (Text): if int8(a) >= 0 { goto loc_199E } If you set b = 224 and c = 64 you get 224-64 = 160 or 0x90. Treat this as int8 and you get -96. The Z80 calculates 224 - 64 and gets 160, but since the calculation doesn't underflow, the carry flag stays at 0. (Your line equals "jr p, loc_199E") It checks, if B-C >= 0, that's equal to (C < B). For reference, here is the non-float version of my code: Code (Text): Private Function DoFunc(ByVal ParamB As Byte, ByVal ParamC As Byte) As Byte Dim IdxLow As Byte Dim IdxHigh As Byte If ParamB >= ParamC Then ' loc_199E IdxLow = (ParamB - ParamC) \ 2 IdxHigh = IdxLow + ParamC 'IdxHigh = ParamB/2 + ParamC/2 'IdxLow = ParamB/2 - ParamC/2 DoFunc = ValArr(IdxHigh) - ValArr(IdxLow) Else IdxLow = (ParamC - ParamB) \ 2 IdxHigh = IdxLow + ParamB 'IdxHigh = ParamB/2 + ParamC/2 'IdxLow = ParamC/2 - ParamB/2 DoFunc = ValArr(IdxHigh) - ValArr(IdxLow) End If End Function (Yes, I often test things in Visual Basic 6. "\" means "integer divide")
Ah okay; carry flag is something I can never remember Thanks I'll leave this question open if anyone wants to try figuring out what mathematical thing this is doing; when I figure out where else this function is used I will update. Thanks again!
I can now tell you the function is mainly used for volume calculations. Here's what seems to happen: Code (Text): For each operator x = current operator TL ^ 0x7F If the current operator IS an output operator/slot x = this function(b = x, c = an external parameter loaded by the 68000; I think it's the global volume and it's 0xFF by default and 0xFF or 0x00 otherwise) x = this function(b = x, c = current channel volume (set by an effect command)) LoadTL(x ^ 0x7F) (to set back to TL) My best guess is that this is a linear->log (linear->exponential?) conversion function with built-in max()...