tokumaru wrote:
Yeah, I assumed it'd be doubled in advance, or already stored doubled.
Doubling the index is one of the things that makes the code bigger. Since the index is an uint, it's not just a simple
ASL.
That's why I posted this single line of C code:
Code:
CurrentData = AllData[CurrentDataIndex];
I need to do whatever this code is accomplishing. This includes doubling the value of CurrentDataIndex because that's what C does here.
If the code doesn't become much smaller than the C implementation, I can just leave it in C.
But I was thinking that the cc65 compiler maybe bloats the code and a handwritten version is much smaller.
(Just like the compiler needlessly copies your pointer to ptr1 whenever you try to access an array through a pointer, even if your own pointer is already in the zeropage.
Or if you access two arrays one after another with the same index variable: The compiler will not notice that it doesn't need to do another
LDY Index again if Index still has the same value as before.)
tokumaru wrote:
If you have to double it on the fly, you'll need more code.
Yeah, it has to be doubled on the fly. After all, this is the screen ID, a dedicated piece of information that controls the bank switching and which little square on the map is blinking etc.
I wouldn't want it doubled in advance just to acommodate to some array storage internals.
The ID belongs to the actual game logic: "This is screen number 439."
That the start address for this screen is stored in
AllScreens + 878 should only come into play when AllScreens is actually used, but CurrentScreenIndex shouldn't hold the value 878 natively.
Dwedit wrote:
Where are your (16-bit?) screen numbers coming from?
The screen numbers come from their position in the pointer array:
Code:
const byte Screen0[] = { 1, 2, 3 };
const byte Screen1[] = { 4, 5, 6, 7 };
const byte Screen2[] = { 8, 9, 10, 11, 12 };
const byte Screen3[] = { /* ... */ };
const byte Screen4[] = { /* ... */ };
const byte Screen5[] = { /* ... */ };
/* ... (more screens) */
const byte *const AllScreens[1000] = { Screen0, Screen1, Screen2, Screen3, Screen4, Screen5, /* ... */ };
In this example, if the index is 4, then AllScreens[Index] will load Screen4 simply because that's the address stored at position 4.
How do I know which screen to load when the hero leaves the current screen? Simple:
If he goes right, then CurrentScreenIndex = CurrentScreenIndex + 1.
Left: -1.
Down: +20.
Up: -20.
Dwedit wrote:
The only way to avoid an array to go from Screen Number to Address of Screen is to use a direct pointer everywhere.
I don't know what you mean. I cannot write
CurrentScreen = Screen487 (or
CurrentScreen = ScreenKingsCastle) unless I make a switch statement with a few hundred cases.
Dwedit wrote:
But how often are you converting from screen number to screen address anyway?
It's not that important in my current case. But it's a general purpose question, so I'm curious about it anyway.
If you have issues with the pointers, just imagine that I have an array of unsigned integers and the array can be larger than 256 bytes:
How would I access the array in an efficient way?
Here, this example is basically the same thing from an assembly code point of view:
Code:
enum EnemyType { Slime, Spider, Bat, Golem, Medusa ... /* 300 more enemy types */ };
const uint EnemyMaxEnergies[] =
{
50, /* Slime */
100, /* Spider */
120, /* Bat */
500, /* Golem */
2000, /* Medusa */
... /* 300 more */
};
void ProcessEnemy(byte enemiesSlot)
{
static uint enemyType;
static uint maxEnergy;
enemyType = AllActiveEnemies[enemiesSlot].Type;
maxEnergy = EnemyMaxEnergies[enemyType];
}
How would one implement
Code:
maxEnergy = EnemyMaxEnergies[enemyType]
in Assembly if maxEnergy is a two byte unsigned integer value, but the number of enemies is also larger than 256, so the array index is also unsigned int?
tokumaru wrote:
What I'm suggesting is, instead of building the map with 16-bit screen indices, build it with 16-bit screen pointers, and get rid of the AllScreens array altogether. There's no need to order the screens if you're referencing them directly.
I'm still curious how you would actually accomplish this. How shall I access the pointer directly? Let's say I have a screen named ScreenTown. Then I have a screen named ScreenTownEntrance.
When I'm in ScreenTownEntrance and I walk right, how exactly shall the program know that it has to load the ScreenTown pointer now? Where is this information stored?
In my case: It is stored in an AllScreens array. The screens in this array are laid out like in a rectangle. The top left screen is the first entry, the bottom right screen is the last entry.
When I move up, down, left right along the screens, I simply change my index to -20, +20, -1 or +1 respectively.
As far as I see, accessing pointers directly only works in two cases:
1. All screen data has the same size. Then you can add and subtract the screen size to the pointer. But my screens have a variable size.
2. If each screen stores the addresses of the four neighboring screens. Which is a total waste of space since the screens are laid out in a rectangle anyway.