I'll list two use cases here. Have a good think about them.
Example 1:
Say you want to have an object move in a sinusoidal pattern like those medusa heads in Castlevania. In high level languages you could get away with calulating the position on the fly thanks to modern compilers and blazing fast CPUs. However, this is the NES, with its 6502-based CPU clocked at
1.79 MHz. In most cases we simply
do not have the time to manually calculate the position every time the object needs to. (Not to mention the fact that we would have to deal with units smaller than a pixel to make it look smooth). That's one reason why tables are used. Think of it like an answer sheet - if you include a table of precalculated sine values, all the CPU has to do is to fetch the corresponding answer to "calculate" the sine of a given value. Problem solved!
Example 2 (This'll get messy, I know):
Say you want to manage collisions using the positions of various objects. In high level languages you could afford to write slightly inefficient code for the same reason as example 1. However, this is the NES with limited room for code and game data. You might think it would be just fine to call the corrsponding variable each time you need it without having to look up tables. But what would happen if you wanted to change the position of a different object depending on some condition - like checking what to do when the player's shot hits an enemy? With a naive approach the sudocode might look like this:
Code:
; some code
switch(playerShotPosX):
case enemy1PosX:
enemy1PosX += 32 ; knockback
removePlayerShot()
; hp related stuff
case enemy2PosX:
enemy2PosX += 32 ; knockback
removePlayerShot()
; hp related stuff
case bossPosX:
bossPosX += 32 ; knockback
removePlayerShot()
; hp related stuff
default:
playerShotPosX += 16
This is
terribly inefficient and not pleasant to look at. There are redundant cases we have to check for, and it would get worse if we added more enemies! In this scenario the first enemy object hit by the player's shot will get knocked back 32 units, and the player's shot always gets removed after it hits an enemy.
A better approach would be to use tables like this:
Code:
; what the reserved memory space for enemy positions and HP might look like
; this part of memory might change depending on which enemies are loaded
enemyXPositions = [enemy1PosX, enemy2PosX, bossPosX]
enemyHPValues = [enemy1HP, enemy2HP, bossHP]
maxIndex = enemiesLoaded ; this variable would be changed when an enemy object spawns/despawns
; think of this like the pokedex numbers in pokemon - they don't match the order they were added in
enemyIndexes = [2, 0, 1]
; the enemy index determines the amount of damage we can do (the order doesn't change)
playerShotDamage = [4, 2, 1]
; later on...
;some code
idx = 0 ; the array/table index
while playerShotPos != enemyXPositions[idx] and idx < maxIndex:
idx += 1 ; increment counter
if idx == maxIndex:
playerShotPosX += 16
else:
enemyXPositions[idx] += 32 ; knockback
removePlayerShot()
enemyIndex = enemyIndexes[idx]
enemyHPValues[idx] -= playerShotDamage[enemyIndex]
if enemyHPValues[idx] <= 0:
removeEnemyObject(idx)
Look at how compact, efficient, scalable, and readable this has become. We could even make a routine which automatically updates the relevant tables when a new object is loaded in. See where we're going? This makes it easier to add new enemies in the future. As an added bonus, we can reuse the index we got as a parameter for other tables to speed up more routines!
Conditionals take time to execute and take up space - we should be trying to generalize the code so that barely any conditional checking needs to happen.
Example 2 is the most common reason for using "LDA tableAddress, X". The variable points to the start of the table of the variables you wish to access, and X is the index within it. In my sudocode format it would be written as "A = tableAddress[X]".
tl;dr: Tables are used for speeding up complex calculations (like sine) and for generalizing routines to improve the scalability.
(Thanks for putting through with this wall of text I made at around midnight. Let me know if I got something wrong.)