Something that seems impossible to do in C
Posted: Wed Mar 23, 2016 9:27 pm
I'm studying how to optimize "dynamic" sprites (sprites whose patterns are dynamically loaded in VRAM at each frame).
Shadow Dancer uses a list of VDP commands, stored in ROM. For example, for Musashi at address 0x1ADA6, you'll find :
The 93xx 94yy give the number of patterns and the 95aa 96bb 97cc give the address in ROM (or RAM in this case, because Musashi patterns are Nemesis compressed, but it's not the case of the ennemies) where the patterns are stored. The last long word activates the DMA and give the VRAM pos. For Musashi, the VRAM loation is always the same but for ennemies the command long word is adjusted at runtime according to the ennemy slot.
These commands are then sent to the VDP control port during VINT. I find it clever and fast.
I want to do the same with my SGDK-written engine but I encountered an unexpected problem.
When I want to generate the command table, I first declare my patterns array :
Then I declare my command table (for the sake of simplicity, there will be only one entry of length 1) :
I get an error at compilation time :
or, if I cast patterns as a u32 :
I asked a question on stackoverflow and it turrned out that a >> and a & are forbidden when declaring constants (even if it involves only constants and thus is actually computable at link time).
Two suggestions were made :
1) declaring the array with the right size but null data, then using a script after the compilation time that reads the symbol table and modify the binary file to put the right values in the table
2) playing with the linker scripting language
Solution 2) may be cleaner, but I know nothing about the linker scripting language. I don't see many difficulties in using 1), but I'd like to automatize the process. How can I specify in the makefile that a certain python script should be used on the binary output file after it and the symbol.txt have been created ?
Or do you see a better option ?
Shadow Dancer uses a list of VDP commands, stored in ROM. For example, for Musashi at address 0x1ADA6, you'll find :
Code: Select all
0003 // number of chunks of commands
9330 9400 9580 96C9 977F 74000083 // chunk 1
9380 9400 95B0 96C9 977F 74600083 // chunk 2
9300 9401 9530 96CA 977F 75600083 // chunk 3
These commands are then sent to the VDP control port during VINT. I find it clever and fast.
I want to do the same with my SGDK-written engine but I encountered an unexpected problem.
When I want to generate the command table, I first declare my patterns array :
Code: Select all
const u32 patterns[] = {
0x00024666,
// ... some 100ths of lines
};
Code: Select all
const u16 temp[] = {
0x9370,
0x9400,
0x9500 + ((patterns >> 1) & 0xFF),
0x9600 + ((patterns >> 9) & 0xFF),
0x9700 + ((patterns) >> 17) & 0xFF)
};
Code: Select all
error: invalid operands to binary >>
error: initializer element is not constant
Code: Select all
warning: initializer element is not computable at load time
error: initializer element is not computable at load time
Two suggestions were made :
1) declaring the array with the right size but null data, then using a script after the compilation time that reads the symbol table and modify the binary file to put the right values in the table
2) playing with the linker scripting language
Solution 2) may be cleaner, but I know nothing about the linker scripting language. I don't see many difficulties in using 1), but I'd like to automatize the process. How can I specify in the makefile that a certain python script should be used on the binary output file after it and the symbol.txt have been created ?
Or do you see a better option ?