Re: Accessing an array of pointers in 6502
Posted: Sun May 12, 2019 7:07 pm
Unfortunately, in the situation you proposed, the answer is the same, since the list has over 256 elements and each one is 2 bytes. The 6502 is an 8-bit CPU after all, so it's not surprising that it's not particularly swift when dealing with more than 256 of anything.
What we do in assembly is we often try to avoid these problematic situations. You may have over 1000 screens, but since you don't need random access to all of them at any given time, you can resort to some sort of "banking", and change which set of 256 elements or less is visible at any given time as you go (totally not worth the trouble for something that only happens once every several seconds, but you get the point). It's true that by breaking up large amounts of data into smaller chunks you increase the path needed to reach it (there's more indirection), but as long as you don't need full random access, you don't need to reconstruct the entire path on each access, just the final step, which's ideally comprised of 8-bit operations. Whenever a big change happens (new screen, new level, etc.), you might need to recalculate the earlier sections of these paths, but that will happen way less frequently.
And even if you need total random access to a large data set, you can still optimize the most common cases, maybe by placing the 128 most commonly accessed elements first, and only doing the slower type of look-up when the index is larger than 127.
Also, when dealing with 16-bit data, in assembly it's common for the data to be split into two arrays of 8-bit values, one with the low bytes and one with the high bytes, so that you don't lose any range (an 8-bit index can still still access 256 elements) or time doubling the index.
The thing is that in assembly, we usually have more control over how we store or stuff, so we try to pick the most suitable schemes for each type of data, as opposed to always using linear arrays for everything. I don't know if the same approach is feasible in C, or if a C programmer would even want to spend time on that kind of optimization...
What we do in assembly is we often try to avoid these problematic situations. You may have over 1000 screens, but since you don't need random access to all of them at any given time, you can resort to some sort of "banking", and change which set of 256 elements or less is visible at any given time as you go (totally not worth the trouble for something that only happens once every several seconds, but you get the point). It's true that by breaking up large amounts of data into smaller chunks you increase the path needed to reach it (there's more indirection), but as long as you don't need full random access, you don't need to reconstruct the entire path on each access, just the final step, which's ideally comprised of 8-bit operations. Whenever a big change happens (new screen, new level, etc.), you might need to recalculate the earlier sections of these paths, but that will happen way less frequently.
And even if you need total random access to a large data set, you can still optimize the most common cases, maybe by placing the 128 most commonly accessed elements first, and only doing the slower type of look-up when the index is larger than 127.
Also, when dealing with 16-bit data, in assembly it's common for the data to be split into two arrays of 8-bit values, one with the low bytes and one with the high bytes, so that you don't lose any range (an 8-bit index can still still access 256 elements) or time doubling the index.
The thing is that in assembly, we usually have more control over how we store or stuff, so we try to pick the most suitable schemes for each type of data, as opposed to always using linear arrays for everything. I don't know if the same approach is feasible in C, or if a C programmer would even want to spend time on that kind of optimization...