Closed Allofich closed 5 months ago
SpellcastingItemMiscSpellPricesPerCharge
was similarly wrong. Here is the data from A.EXE.
Each set of data has 8 entries. The value for the start of SpellcastingItemMiscSpellPricesPerCharge
was pointing to 4b80:1f1c here, halfway through the data.
WaterTwilightLightLevels
is probably incorrect, too, for A.EXE at least (I haven't checked ACD.EXE). The offset points into the middle of a two-byte value. It should probably be one byte less, at 0x3F40A.
From A.EXE:
The current value of 0x3F40B points to 4b80:3c0b here (subtract 0x3B800 to get the value shown in the 4b80 segment here). The data starts at 3c0a, though, and 3c0a is what the code references, not 3c0b.
src/Assets/ExeData.h
has in it
std::array<uint16_t, 14> waterTwilightLightLevels;
but it looks like, starting from the corrected offset, it has 16 elements, the last two being 0.
The spellcastingItemMiscSpell
data had the wrong number of entries set in ExeData.h
(9 instead of 8) for the values except for the spell names.
Thanks Allofich. I'm checking this branch but I think the spell prices per charge need to be two bytes each. Otherwise spellcastingItemAttackSpellPricesPerCharge
is like [0x32, 0x0, 0x32, 0x0, 0x64, ...]
.
You're right. I'll fix that as well.
I got it, no worries!
I'm looking at the water light level values but it seems okay at a glance. Will test some more. I'm pretty sure the game only has 14 light levels, so two extra ones might not make sense.
armorEnchantmentBonusPrices
, weaponEnchantmentBonusPrices
, spellcastingItemBasePrices
and enhancementItemBasePrices
should also be read as 2-byte values.
plateArmorBasePrices
, chainArmorBasePrices
and leatherArmorBasePrices
are correct as 1-byte values.
Done.
Yeah so about the light levels, if the water changes during sunrise/sunset like I'm thinking, then the values in that array should be between 1 and 13. They're probably indices into which .LGT light table to use to convert texture colors to shaded colors. See these in ArenaRenderUtils.h
:
constexpr uint8_t PALETTE_INDEX_LIGHT_LEVEL_LOWEST = 1;
constexpr uint8_t PALETTE_INDEX_LIGHT_LEVEL_HIGHEST = 13;
Well, if counting from the adjusted offset I suggested the final four 00 bytes seem to fit neatly in the array as two "0" values, and also the values are in descending order by 100h, so they fit with that.
The last few values of the array (if using the adjusted offset) are 400h, 400h, 300h, 300h, 200h, 200h, 100h, 100h, so the next two values being 0h and 0h fits the pattern.
It could be though that the game never accesses the water light level values with an index high enough that it would reach them.
Of course values such as 400h, 300h, wouldn't be what you'd expect as indices.
But, as I showed above, the game code does access the data from the adjusted offset. I haven't reversed how the values are used after that.
I changed it. Maybe Arena treats them like # of bytes to skip. If there's nothing else then I'll merge this now.
If you're looking for anything else to help with, it would be awesome to have the screen-space fog finally documented in the wiki in a concise way. I haven't touched it since Carmina gave the info in #201 and honestly it still scares me a little (with the apparent self-modifying assembly from what I heard).
WaterTwilightLightLevels
seem to be related to how many 1/1024ths of the in-game day have passed.
Here is the only place in the code (as far as I can find) that references them:
MOV BX,word ptr [1/1024thsOfDayThatHavePassed]
JS LAB_1000_04b9
SUB BX,0x100
JMP LAB_1000_04bf
LAB_1000_04b9
SUB BX,0x300
NEG BX
LAB_1000_04bf
MOV SI,BX
ADD BX,BX
MOV BX,word ptr [BX + WaterTwilightLightLevels]
CMP BX,word ptr [DAT_4b80_3b4b]
JZ LAB_1000_048a
MOV word ptr [DAT_4b80_3b4b],BX
You can see that in
MOV BX,word ptr [BX + WaterTwilightLightLevels]
the value in BX, which was assigned 1/1024thsOfDayThatHavePassed
with various adjustments then made to it, has the value of WaterTwilightLightLevels
added to it. That suggests the values in WaterTwilightLightLevels
also represent something related to 1/1024ths of a day.
1/1024thsOfDayThatHavePassed
is the value at 4b80:cb70
in the disassembly of A.EXE. Another usage it has is in order to decide whether to play the night MIDI or not.
MOV SI,s_night.xmi_4b80_40e2 = "night.xmi"
CMP word ptr [1/1024thsOfDayThatHavePassed],0x10c
JBE LAB_311a_056a
CMP word ptr [1/1024thsOfDayThatHavePassed],0x2f4
JNC LAB_311a_056a
MOV SI,s_sunnyday.xmi_4b80_40ec = "sunnyday.xmi"
If you're looking for anything else to help with, it would be awesome to have the screen-space fog finally documented in the wiki in a concise way.
I may take a look at it, but if it's complicated it may be beyond me.
As you can see in the code snippet above, the values from WaterTwilightLightLevels
are used to compute a value stored in DAT_4b80_3b4b
. DAT_4b80_3b4b
is used in a few different places. It is sometimes compared against 0xFFFF, and it is stored in BX right before a call to a function that references "waterani.rci", so it's probably used with that, which maybe you already know.
If there's nothing else then I'll merge this now.
I don't intend to add any more commits.
Sorry, the value I called GameMinutesPassedToday
isn't game minutes, it is 1/1024ths of the day that have passed. (Looking back at the MIDI-related code I noticed that the values didn't match the game if they were interpreted as minutes). So the WaterTwilightLightLevels
would be related to that.
Edit: I updated the above code to use 1/1024ths of the day.
Fixes the offsets for
SpellcastingItemAttackSpellPricesPerCharge
. They were pointing into the previous data atSpellcastingItemAttackSpellQualities
.Here's the data in A.EXE (after decompression).
Each set of data has 15 entries for the 15 item attack spells. The value for the start of
SpellcastingItemAttackSpellPricesPerCharge
was pointing at 0x3D5E2, which is 4b80:1de2 here, within theSpellcastingItemAttackSpellQualities
data.